Introduction
On this article, I’m going to evaluation and implement the deep studying paper titled “CBAM: Convolutional Block Consideration Module” by Woo et al. [1]. Because the identify suggests, that is primarily a block we are able to connect to a CNN-based mannequin to boost characteristic high quality by performing an consideration mechanism. Regardless of the identify consideration, it’s utterly totally different from the one within the ViT (Imaginative and prescient Transformer) structure. Understand that CBAM was first launched in 2018, whereas ViT was solely launched in 2020. So, we are able to merely say that CBAM is the older method to use an consideration mechanism to picture knowledge. Regardless of being older, we must always not fear about its relevance since CBAM is much more light-weight as in comparison with ViT, which makes it appropriate for use as a place to begin for deployment on low-power units.
Higher Than SENet
If we had been to speak in regards to the historical past, CBAM was truly proposed as the development of SENet (Squeeze-and-Excitation Community), which was launched a yr earlier than CBAM. Should you bear in mind the SENet structure, it primarily works by performing consideration throughout the channel dimension. By doing so, the channels that appear unimportant could be weighted lower than that of the extra necessary ones. — I truly obtained a separate article speaking extra completely about SENet, which you’ll be able to entry via the hyperlink given in reference quantity [2].
As a substitute of simply assigning weights to every channel, CBAM additionally provides weights to each single pixel within the spatial dimension of the picture. So, we are able to say that CBAM has two consideration mechanisms, which the authors seek advice from because the CAM (Channel Consideration Module) and the SAM (Spatial Consideration Module). So, primarily based solely on this principle, CBAM ought to carry out higher than SENet.
···
CBAM Structure
Let’s speak extra particularly in regards to the CBAM structure which I show in Determine 1 beneath. As I’ve talked about earlier, CBAM consists of CAM and SAM. These two sub-blocks are accountable for creating consideration weights, which can then be utilized to the unique tensor by multiplication. The output tensor of this block (the one known as Refined Options) has the very same dimension because the enter (Enter Function), that means that we are able to simply plug CBAM to any spine mannequin with no need to fret about altering the tensor shapes.

Channel Consideration Module (CAM)
Now let’s take a more in-depth take a look at the channel consideration module in Determine 2 beneath. This element is definitely similar to the SENet block, besides that CAM additionally makes use of world maxpooling layer along with the worldwide average-pooling layer. It’s defined within the paper that the 2 operations seize totally different form of data, permitting the tensor produced by CAM to be extra informative as in comparison with that of the SENet block.

Do not forget that the spatial dimension of the tensor collapses to 1×1 once we apply world pooling operation to it. This primarily implies that the enter tensor, which has the unique form of C×H×W, now turns into C×1×1, permitting us to course of it additional simply with the MLP within the subsequent step. There are two linear layers on this MLP, the place the primary one is used to shrink the variety of options in response to the discount ratio parameter, whereas the second works by increasing the characteristic vector again to the unique size (i.e., the variety of channels C). These two linear layers within the MLP are collectively accountable to be taught the significance of every channel. Additionally, understand that this MLP is shared for the tensor produced by the maxpooling and the average-pooling operations, that means that these two tensors will likely be processed by the very same MLP.
As these two tensors have been processed, we then mix them by element-wise summation and move it via a sigmoid perform. Since this perform shrinks any quantity to the vary of 0 to 1, we are able to now understand the ensuing tensor because the channel consideration weight. The weather that correspond to the extra necessary channels can have the worth near 1, indicating that these channels will likely be weighted greater than the others. In keeping with the paper, this type of mechanism helps the mannequin to know what form of options to attend.
You’ll be able to see the formal mathematical expression of the channel consideration module in Determine 3 beneath, the place F is an arbitrary intermediate tensor inside a community. One factor you want to remember right here is that there needs to be a ReLU activation perform positioned between the 2 linear layers (i.e., W₀ and W₁) but is in some way not written on this equation.

Spatial Consideration Module (SAM)
The spatial consideration module is conceptually just like the channel consideration module. Check out the illustration of this sub-block in Determine 4 beneath.

What primarily differentiates SAM from CAM is the axis the place the pooling operation is carried out. Beforehand in CAM the pooling is completed throughout the spatial dimension, permitting every channel to have a single worth representing that channel. In the meantime, right here in SAM the pooling is completed throughout the channel dimension for every spatial pixel location. Thus, each pixel now incorporates a single worth that represents all channels directly. By doing so, the enter tensor that originally has the form of C×H×W will collapse to 1×H×W. Do not forget that since we use most and average-pooling operations, we’ll thus have two tensors of that dimension. These two tensors are then concatenated, forming a brand new tensor of form 2×H×W. This tensor is then processed with a 7×7 convolution layer of a single kernel, which successfully combines the data from the 2 channels into one. So, at this level the tensor turns into 1×H×W once more and is then forwarded to the sigmoid perform. Just like CAM, the tensor produced by this sigmoid acts because the spatial consideration weight. By utilizing this weight tensor, we are able to primarily let the mannequin know the place it ought to pay extra consideration to. Beneath is what the formal mathematical definition of the spatial consideration module seems to be like.

Integrating CBAM to Any Spine Mannequin
Beforehand I discussed that the output form of CBAM is precisely the identical because the enter, permitting it to be built-in to any spine mannequin simply. In actual fact, the authors additionally present an illustration relating to how we are able to try this, which I present you in Determine 6 beneath. On this instance, they illustrate methods to plug CBAM right into a ResNet constructing block. As soon as we’ve efficiently built-in them like this, we are able to simply stack these blocks as typical. Later within the coding half I’ll exhibit methods to implement CBAM from scratch and methods to plug it right into a ResNeXt mannequin.

···
Experimental Outcomes
The design of the CBAM structure itself was not chosen arbitrarily. As a substitute, it was constructed primarily based on empirical outcomes on their ablation research, wherein they proved that their remaining mannequin is certainly essentially the most optimum one.
Ablation Examine on the Channel Consideration Module
The primary ablation examine they performed was associated to the pooling layers within the CAM. The outcomes of this experimental set are proven in Determine 7. We will see on this desk that the errors once we use both of the 2 poolings are considerably decrease than the plain spine ResNet50 mannequin. This primarily signifies that the data extracted by the maximum-pooling and the average-pooling are each necessary. Moreover, once we make the most of each pooling mechanisms concurrently, the top-1 error goes even decrease to 22.80%, which I consider this proves that the 2 tensors comprise data that aren’t solely necessary but additionally complementary (i.e., finishing one another). Theoretically talking, the options produced by maxpooling and average-pooling ought to certainly be complementary because the former captures essentially the most outstanding pixel worth inside a channel whereas the latter extracts the overall data of the channel. So, that is primarily the explanation why in Determine 2 the authors ended up utilizing each pooling operations.

Ablation Examine on the Spatial Consideration Module
Concerning the spatial consideration module, it’s defined within the paper that the authors additionally used various configurations as displayed in Determine 8 beneath. You’ll be able to see right here that the configuration within the final row produces the perfect consequence, the place it makes use of the 2 pooling operations adopted by a convolution layer with 7×7 kernel. Within the case of SAM, each the utmost and the average-pooling operations are technically replaceable by a 1×1 convolution (which can mix data throughout channel dimension with learnable parameters as a substitute of utilizing a “fastened” common and max operations), but the classification efficiency seems to be suboptimal.

Ablation Examine on the Placement of CAM and SAM
The final ablation examine the authors performed was associated to how the CAM and SAM are organized throughout the CBAM. It’s proven in Determine 9 beneath that utilizing sequential technique, particularly CAM adopted by SAM, permits the mannequin to carry out finest with the top-1 error of solely 22.66%. You’ll be able to see within the subsequent row that they tried to swap the sequence of the 2 modules, however they discovered that the error will increase as a substitute. Moreover, the classification efficiency was getting even worse after they tried to parallelize CAM and SAM, regardless that this method remains to be higher than the ResNet50 with SE module solely.

Comparability with Different Fashions
Within the subsequent experiment the authors in contrast the efficiency of a plain mannequin, the mannequin with SE module, and the mannequin with CBAM on totally different backbones. You’ll be able to see in Determine 10 beneath that the mannequin that makes use of CBAM virtually at all times performs higher than the opposite two as highlighted in inexperienced. Furthermore, in ResNeXt50, though the mannequin with SE module is best than the identical mannequin with CBAM, the error hole is just 0.01%, which I feel is negligible.
I additionally discovered on this determine that the error of ResNet50 with CBAM is decrease than the plain ResNet101 as highlighted in orange. Apparently, it’s seen right here that the variety of params and the GFLOPs of ResNet50 with CBAM are a lot smaller. These information present that CBAM permits a shallower community to outperform the deeper one whereas considerably conserving computational assets, which is good for deployment on low-end units.

Consideration Heatmap
Along with the quantitative outcomes defined above, the authors additionally used Grad-CAM to carry out qualitative analysis. Should you’re not but acquainted with Grad-CAM, it’s primarily a way we are able to use to seek out out the particular space that contributes extra to the anticipated class. Determine 11 beneath shows a number of examples of the eye heatmap produced utilizing Grad-CAM, the place the realm highlighted in purple signifies that it provides extra contribution to the anticipated class.

The outcomes are fairly attention-grabbing. Let’s now check out the Croquet ball class. With the plain ResNet50, it seems to be just like the mannequin focuses on each the ball and the particular person. Because the SE module is utilized (i.e., channel-wise consideration solely), the eye map turns into extra refined towards the ball. After which, after we substitute the SE module with CBAM, the mannequin achieves a fair sharper give attention to the goal object.
The same factor will also be noticed within the different courses. In Eskimo canine and Snow leopard, for instance, we are able to see that the mannequin solely pays consideration to the eyes. If I had been to say, that is mainly not flawed so long as the anticipated class is right. Nonetheless, if we had been to foretell one thing (as a human), it could make extra sense to see the complete object each time doable, proper? And so, that is precisely what the eye modules do. You’ll be able to see that when CBAM is used, the purple space within the consideration heatmap covers the complete face, indicating the mannequin now take that facial area into consideration to make predictions.
Moreover, additionally it is seen within the determine that through the use of CBAM we are able to make the mannequin extra assured when making predictions. Check out the Faculty bus picture within the above determine. You’ll be able to see right here that the bus will not be centered on the center of the picture. This mainly causes the plain ResNet50 to have a confidence rating of solely 0.07 in predicting the bus (which I consider this could have been misclassified). In the meantime, SE module permits the mannequin to accurately classify it with the boldness of 0.92, after which CBAM improves it even additional to 0.98.
···
CBAM Implementation
As we’ve understood all of the theories behind CBAM, let’s now roll our sleeves and get our arms soiled with some code! As I’ve talked about earlier, right here I’m going to implement CBAM and attempt to combine it into the ResNeXt spine. Though I’m implementing each from scratch, I’ll focus the dialogue totally on the CBAM module. So if you happen to’re not but acquainted with ResNeXt, I do encourage you learn my earlier article about that mannequin beforehand, which you’ll be able to entry via the hyperlink at reference [4].
As typical, the very very first thing we have to do is to import the required modules, i.e., the bottom torch module and its nn submodule.
Subsequent, in Codeblock 2 beneath I initialize the configurable variables. The discount ratio R is used to regulate the width of the MLP layer contained in the CAM. I set the worth for this to 16 as steered within the paper. In the meantime, CARDINALITY, NUM_CHANNELS, and NUM_BLOCKS are those belong to ResNeXt.
···
CAM Implementation
Let’s begin with the CAM first. Should you return to Determine 2, you’ll be able to see that we’ve two pooling operations. In Codeblock 3 beneath, the 2 layers that correspond to them are initialized at traces #(1) and #(2). Don’t overlook to set the output_size parameter to (1,1) since we wish every channel to be represented as a single quantity.
What we do subsequent contained in the __init__() technique is initializing the MLP that consists of two linear layers. The primary linear layer is accountable to scale back the variety of options in response to the R parameter (#(3)), whereas the second is used to develop it again to the unique variety of options (#(5)). Additionally, don’t overlook to put the ReLU activation perform in between (#(4)). In actual fact, the construction of this MLP layer is precisely the identical because the one utilized in SENet. — You’ll be able to learn extra in regards to the underlying thought behind this construction in my earlier article about that module at reference [2]. — The very last thing we do contained in the __init__() technique is to initialize the sigmoid activation perform (#(6)), which is accountable to rescale the tensor such that the values will at all times be between 0 and 1, appropriate for use as an consideration weight.
Now let’s transfer on to the ahead() technique the place the execution would occur. You’ll be able to see at line #(7) within the above codeblock that we take a single tensor x because the enter. This enter tensor will then be saved within the authentic variable, which is completed as a result of we’ll later multiply it with the ensuing channel consideration weight tensor (#(17)). The x tensor itself will likely be processed by maxpooling and average-pooling operations in parallel (#(8–9)). Each x_max and x_avg are forwarded to the identical MLP, which is the explanation why this MLP known as “shared” (#(12–13)). Then at line #(14), we mix x_max and x_avg via element-wise summation earlier than forwarding the ensuing tensor to the sigmoid perform (#(15)). There’s a little technical factor we do at line #(16), which is used to reintroduce the spatial dimension we beforehand dropped at traces #(10) and #(11). Lastly, as the burden tensor is prepared, we are able to then truly weight the unique tensor by multiplying them (#(17)).
At this level we already obtained our CAM class accomplished. What we’re going to do subsequent is to check it with the next code. Right here I initialize a CAM occasion that accepts a 512-channel picture and move a dummy tensor of dimension 512×28×28 via it, simulating an arbitrary intermediate tensor inside a community.
Should you run the above code, you need to get the next output. Discover that beforehand in Codeblock 3 I wrote a lot of print features, which is the explanation why right here you’ll be able to clearly see the detailed stream of the community.
It’s vital to know that though the MLP seems to be prefer it doesn’t change the tensor dimension in any respect (#(1–2)), you’ll want to know that the characteristic vector size is internally diminished to 32 by the primary linear layer earlier than ultimately expanded again to 512 by the second. Subsequent, it may also be price noting that the channel consideration weight tensor initially has the form of 512×1×1 (#(3)), indicating that each single channel within the authentic tensor has a single weighting quantity related to it. This consideration weight is then utilized to the unique tensor through the use of a easy multiplication, which technically talking, this weight tensor is broadcasted alongside the spatial dimension of the unique tensor (#(4)). At this level our tensor is now able to be forwarded to the SAM, which we’re going to construct very quickly.
···
SAM Implementation
The implementation of the spatial consideration module is displayed in Codeblock 5 beneath. What we have to initialize contained in the __init__() technique is just a single 7×7 convolution layer (#(1)) and a sigmoid activation perform (#(2))
Within the ahead() technique, the very first thing we do is to retailer the unique enter right into a separate variable (#(3)), which is precisely the identical as what we did within the CAM. The pooling mechanism within the SAM is a bit distinctive since right here we wish to try this throughout the channel dimension. That is primarily the explanation that I didn’t initialize any pooling layers within the __init__() technique since nn.AdaptiveMaxPool2d() and nn.AdaptiveAvgPool2d() function on spatial dimension, which is irrelevant for this case. As a substitute, right here we use a easy torch.max() and torch.imply() features to do the maxpooling (#(4)) and average-pooling (#(5)) operations, respectively. Simply don’t overlook to set the dim parameter to 1 in order that they actually do the operations throughout the channel dimension.
Regardless of taking totally different values, the tensor form produced by the 2 poolings are precisely the identical, which is the explanation that we are able to simply concatenate them as proven at line #(6). Understand that tensor concatenation does not likely mix data because it solely stacks the 2 with out mixing the numbers. Thus, within the subsequent step we apply the convolution layer we initialized earlier to really try this (#(7)). This convolution solely consists of a single kernel, which means that the ensuing tensor can have a single channel as nicely. This concept is conceptually totally different from the one within the CAM, the place in that module we mix the data by element-wise summation. Technically talking, we are able to primarily use summation for the SAM too as it would produce the very same tensor dimension. Nonetheless, I do consider that the authors may also supposed to seize the correlation between neighboring pixels as a substitute of independently giving weight to every pixel, which is the explanation why they determined to make use of convolution over summation.
As the 2 tensors have been mixed, the following factor we do is to move the ensuing tensor via the sigmoid activation perform to really receive the spatial consideration weight (#(8)). And eventually, we’ll multiply this weight tensor with the unique SAM enter as proven at line #(9).
Now let’s run the Codeblock 6 beneath to check if our spatial consideration module works correctly.
And beneath is what the stream of the SAM seems to be like. We will see right here that because the pooling operations are utilized to the enter tensor, the channel dimension collapses to 1 (#(1–2)). This primarily implies that each pixel is now represented as a single quantity aggregated from all channels in that spatial location. Then at line #(3), the tensor turns into 2×28×28 as we concatenate the 2 earlier than ultimately lowering it once more to 1×28×28 utilizing the convolution layer (#(4)). After being processed by the sigmoid perform, the ensuing spatial consideration weight is then multiplied with the unique tensor, wherein the previous is broadcasted alongside the channel dimension of the latter, permitting the ultimate output tensor to have the very same form because the enter (#(5)).
···
The Full CBAM Block
Now because the CAM and SAM are accomplished, we’ll now put them collectively within the CBAM class. See the main points in Codeblock 7 beneath. You’ll be able to see right here that this class could be very easy as what we have to do is simply to initialize the 2 consideration modules and place them sequentially. Understand that we have to move the num_channels parameter each time we wish to initialize a CBAM occasion (#(1)) since we’ll later combine this module into ResNeXt, wherein each single one among its constructing blocks accepts totally different variety of channels, and so we have to make this CBAM block versatile as nicely.
Once more, simply to make sure that this class works correctly, let’s move a dummy tensor via it utilizing the Codeblock 8 beneath.
···
Implementing CBAM on ResNeXt Constructing Block
Alright, so at this level our CBAM is prepared and on this part I’m going to really exhibit how we are able to connect this module to a ResNeXt constructing block. The code I write in Codeblock 9 onwards are mainly the identical because the one used once I demonstrated methods to combine SENet on ResNeXt. I do encourage you to learn that article [2] and my clarification on the pure ResNeXt spine [4] as a result of it could be too lengthy if I clarify all the things right here.
The one factor I wish to emphasize in Codeblock 9 is that the CBAM module itself is initialized at line #(1) which is then hooked up to the stream at line #(2).
And now we are able to check the Block class above by working the Codeblock 10 beneath. You’ll be able to see within the following output that the tensor efficiently passes via the complete community, together with the CBAM block we hooked up on the finish of the primary stream (#(1)).
···
The Ultimate CBAM-ized ResNeXt
Because the CBAM module has been hooked up to the primary ResNeXt constructing block, we are able to simply stack these blocks in response to the construction given within the ResNeXt paper. The CBAMResNeXt class in Codeblock 11 is actually copy-pasted from my SENet article [2] because the solely factor we have to do to connect CBAM module to ResNeXt is modifying the Block class again in Codeblock 9.
And now we are able to verify if the complete community works correctly by working the next testing code. Right here I initialize a CBAMResNeXt occasion and move a dummy RGB picture of dimension 224×224 via it.
Beneath is what the ensuing output seems to be like. Right here we are able to see that the mannequin efficiently passes the unique picture via the complete community up till the classification head. This primarily signifies that our CBAM is correctly hooked up, and thus this mannequin is able to be educated for picture classification.
···
Ending
And nicely I feel that’s just about all the things about CBAM and methods to implement it from scratch. You may also discover the code used on this article in my GitHub repository [6]. Please let me know if you happen to discover any errors within the dialogue or within the code. Thanks for studying, I hope you be taught one thing new as we speak. See ya in my subsequent article!
···
References
[1] Sanghyun Woo et al. CBAM: Convolutional Block Consideration Module. Arxiv. https://arxiv.org/abs/1807.06521 [Accessed November 12, 2025].
[2] Muhammad Ardi Putra. SENet Paper Walkthrough: The Channel-Smart Consideration. In the direction of Knowledge Science. https://towardsdatascience.com/the-channel-wise-attention/ [Accessed November 12, 2025]. Additionally accessible at https://medium.com/ai-advances/senet-paper-walkthrough-the-channel-wise-attention-8ac72b9cc252.
[3] Picture initially created by creator.
[4] Muhammad Ardi Putra. ResNeXt Paper Walkthrough: Taking ResNet to the Subsequent Stage. In the direction of Knowledge Science. https://towardsdatascience.com/taking-resnet-to-the-next-level/ [Accessed November 12, 2025]. Additionally accessible at https://medium.com/ai-advances/taking-resnet-to-the-next-level-resnext-77088c245698.
[5] Saining Xie et al. Aggregated Residual Transformations for Deep Neural Networks. Arxiv. https://arxiv.org/abs/1611.05431 [Accessed November 12, 2025].
[6] MuhammadArdiPutra. CBAM. GitHub. https://github.com/MuhammadArdiPutra/medium_articles/blob/principal/Deeppercent20Learningpercent20Frompercent20Scratch/CBAM.ipynb [Accessed November 12, 2025].















