• Home
  • About Us
  • Contact Us
  • Disclaimer
  • Privacy Policy
Monday, September 21, 2026
newsaiworld
  • Home
  • Artificial Intelligence
  • ChatGPT
  • Data Science
  • Machine Learning
  • Crypto Coins
  • Contact Us
No Result
View All Result
  • Home
  • Artificial Intelligence
  • ChatGPT
  • Data Science
  • Machine Learning
  • Crypto Coins
  • Contact Us
No Result
View All Result
Morning News
No Result
View All Result
Home Artificial Intelligence

CBAM Paper Walkthrough: The Double-Consideration Mechanism

Admin by Admin
September 21, 2026
in Artificial Intelligence
0
1789357494559 enki42.jpg
0
SHARES
0
VIEWS
Share on FacebookShare on Twitter

READ ALSO

GraphRAG: A Practitioner’s Information to six Superior Architectural Patterns

One Vendor, 4 Spellings: How Deterministic Phases Beat Similarity Scores


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.

Determine 1. The high-level view of the CBAM structure [1].

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.

Determine 2. The construction of the channel consideration module [1].

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.

Determine 3. The formal mathematical expression of the channel consideration module [1].

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.

Determine 4. The construction of the spatial consideration module [1].

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.

Determine 5. The mathematical definition of the spatial consideration module [1].

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.

Determine 6. Find out how to combine CBAM into any spine mannequin [1].

···

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.

Determine 7. Ablation examine on the usage of common and maximum-pooling operations within the CAM [1].

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.

Determine 8. Ablation examine on the configuration of the SAM [1].

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.

Determine 9. Ablation examine on how the CAM and SAM are organized [1].

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.

Determine 10. How CBAM performs on totally different spine CNN fashions [1][3].

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.

Determine 11. Consideration heatmap obtained by Grad-CAM [1].

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.

# Codeblock 1import torchimport torch.nn as nn

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.

# Codeblock 2R            = 16CARDINALITY  = 32NUM_CHANNELS = [3, 64, 256, 512, 1024, 2048]NUM_BLOCKS   = [3, 4, 6, 3]NUM_CLASSES  = 1000

···

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.

# Codeblock 3class CAM(nn.Module):    def __init__(self, num_channels, r=16):        tremendous().__init__()                self.maxpool = nn.AdaptiveMaxPool2d(output_size=(1,1))  #(1)        self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))  #(2)                self.mlp = nn.Sequential(            nn.Linear(in_features=num_channels,                      out_features=num_channels//r,   #(3)                      bias=False),                        nn.ReLU(inplace=True),                    #(4)                        nn.Linear(in_features=num_channels//r,    #(5)                      out_features=num_channels,                       bias=False)        )                self.sigmoid = nn.Sigmoid()                   #(6)            def ahead(self, x):         #(7)        authentic = x        print(f'originaltt: {x.dimension()}n')                        x_max = self.maxpool(x)   #(8)        print(f'x after maxpool (x_max)t: {x_max.dimension()}')                x_avg = self.avgpool(x)   #(9)        print(f'x after avgpool (x_avg)t: {x_avg.dimension()}n')                        x_max = torch.flatten(x_max, start_dim=1)    #(10)        print(f'x_max after flattent: {x_max.dimension()}')                x_avg = torch.flatten(x_avg, start_dim=1)    #(11)        print(f'x_avg after flattent: {x_avg.dimension()}n')                        x_max = self.mlp(x_max)   #(12)        print(f'x_max after mlptt: {x_max.dimension()}')                x_avg = self.mlp(x_avg)   #(13)        print(f'x_avg after mlptt: {x_avg.dimension()}n')                        x = x_max + x_avg         #(14)        print(f'after sumtt: {x.dimension()}')                x = self.sigmoid(x)       #(15)        print(f'after sigmoidtt: {x.dimension()}')                x = x[:, :, None, None]   #(16)        print(f'after reshapett: {x.dimension()}')                x = x * authentic          #(17)                   print(f'after multiplytt: {x.dimension()}')                return x

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.

# Codeblock 4cam = CAM(num_channels=512, r=16)x = torch.randn(1, 512, 28, 28)out = cam(x)

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.

# Codeblock 4 Outputauthentic                : torch.Dimension([1, 512, 28, 28])x after maxpool (x_max) : torch.Dimension([1, 512, 1, 1])x after avgpool (x_avg) : torch.Dimension([1, 512, 1, 1])x_max after flatten     : torch.Dimension([1, 512])x_avg after flatten     : torch.Dimension([1, 512])x_max after mlp         : torch.Dimension([1, 512])    #(1)x_avg after mlp         : torch.Dimension([1, 512])    #(2)after sum               : torch.Dimension([1, 512])after sigmoid           : torch.Dimension([1, 512])after reshape           : torch.Dimension([1, 512, 1, 1])    #(3)after multiply          : torch.Dimension([1, 512, 28, 28])  #(4)

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))

# Codeblock 5class SAM(nn.Module):    def __init__(self):        tremendous().__init__()                self.conv = nn.Conv2d(in_channels=2,     #(1)                              out_channels=1,                               kernel_size=7,                               padding=3,                               bias=False)        self.sigmoid = nn.Sigmoid()              #(2)        def ahead(self, x):        authentic = x      #(3)        print(f'originaltt: {x.dimension()}n')                        x_max, _ = torch.max(x,  dim=1, keepdim=True)    #(4)        print(f'x after maxpool (x_max)t: {x_max.dimension()}')                x_avg    = torch.imply(x, dim=1, keepdim=True)    #(5)        print(f'x after avgpool (x_avg)t: {x_avg.dimension()}n')                        x = torch.cat([x_max, x_avg], dim=1)             #(6)        print(f'after concatenatet: {x.dimension()}')                x = self.conv(x)                                 #(7)        print(f'after convtt: {x.dimension()}')                x = self.sigmoid(x)                              #(8)        print(f'after sigmoidtt: {x.dimension()}')                x = x * authentic                                 #(9)        print(f'after multiplytt: {x.dimension()}')                return x

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.

# Codeblock 6sam = SAM()x = torch.randn(1, 512, 28, 28)out = sam(x)

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)).

# Codeblock 6 Outputauthentic                : torch.Dimension([1, 512, 28, 28])x after maxpool (x_max) : torch.Dimension([1, 1, 28, 28])    #(1)x after avgpool (x_avg) : torch.Dimension([1, 1, 28, 28])    #(2)after concatenate       : torch.Dimension([1, 2, 28, 28])    #(3)after conv              : torch.Dimension([1, 1, 28, 28])    #(4)after sigmoid           : torch.Dimension([1, 1, 28, 28])after multiply          : torch.Dimension([1, 512, 28, 28])  #(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.

# Codeblock 7class CBAM(nn.Module):    def __init__(self, num_channels):    #(1)        tremendous().__init__()                self.cam = CAM(num_channels=num_channels)        self.sam = SAM()            def ahead(self, x):        print(f'originaltt: {x.dimension()}')                x = self.cam(x)        print(f'after camtt: {x.dimension()}')                x = self.sam(x)        print(f'after samtt: {x.dimension()}')                return x

Once more, simply to make sure that this class works correctly, let’s move a dummy tensor via it utilizing the Codeblock 8 beneath.

# Codeblock 8cbam = CBAM(num_channels=512)x = torch.randn(1, 512, 28, 28)out = cbam(x)
# Codeblock 8 Outputauthentic   : torch.Dimension([1, 512, 28, 28])after cam  : torch.Dimension([1, 512, 28, 28])after sam  : torch.Dimension([1, 512, 28, 28])

···

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).

# Codeblock 9class Block(nn.Module):    def __init__(self,                  in_channels,                 add_channel=False,                 channel_multiplier=2,                 downsample=False):        tremendous().__init__()        self.add_channel = add_channel        self.channel_multiplier = channel_multiplier        self.downsample = downsample                        if self.add_channel:            out_channels = in_channels*self.channel_multiplier        else:            out_channels = in_channels                mid_channels = out_channels//2                        if self.downsample:            stride = 2        else:            stride = 1        if self.add_channel or self.downsample:            self.projection = nn.Conv2d(in_channels=in_channels,                                        out_channels=out_channels,                                         kernel_size=1,                                         stride=stride,                                         padding=0,                                         bias=False)            nn.init.kaiming_normal_(self.projection.weight, nonlinearity='relu')            self.bn_proj = nn.BatchNorm2d(num_features=out_channels)        self.conv0 = nn.Conv2d(in_channels=in_channels,                               out_channels=mid_channels,                               kernel_size=1,                                stride=1,                                padding=0,                                bias=False)        nn.init.kaiming_normal_(self.conv0.weight, nonlinearity='relu')        self.bn0 = nn.BatchNorm2d(num_features=mid_channels)        self.conv1 = nn.Conv2d(in_channels=mid_channels,                               out_channels=mid_channels,                                kernel_size=3,                                stride=stride,                               padding=1,                                bias=False,                                teams=CARDINALITY)        nn.init.kaiming_normal_(self.conv1.weight, nonlinearity='relu')        self.bn1 = nn.BatchNorm2d(num_features=mid_channels)        self.conv2 = nn.Conv2d(in_channels=mid_channels,                               out_channels=out_channels,                               kernel_size=1,                                stride=1,                                padding=0,                                bias=False)        nn.init.kaiming_normal_(self.conv2.weight, nonlinearity='relu')        self.bn2 = nn.BatchNorm2d(num_features=out_channels)                self.relu = nn.ReLU()                self.cbam = CBAM(num_channels=out_channels)               #(1)            def ahead(self, x):        print(f'originaltt: {x.dimension()}')                if self.add_channel or self.downsample:            residual = self.bn_proj(self.projection(x))            print(f'after projectiont: {residual.dimension()}')        else:            residual = x            print(f'no projectiontt: {residual.dimension()}')                x = self.conv0(x)        x = self.bn0(x)        x = self.relu(x)        print(f'after conv0-bn0-relut: {x.dimension()}')        x = self.conv1(x)        x = self.bn1(x)        x = self.relu(x)        print(f'after conv1-bn1-relut: {x.dimension()}')                x = self.conv2(x)        x = self.bn2(x)        print(f'after conv2-bn2tt: {x.dimension()}')                x = self.cbam(x)                                          #(2)        print(f'after cbamtt: {x.dimension()}')                x = x + residual        x = self.relu(x)        print(f'after summationtt: {x.dimension()}')                return x

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)).

# Codeblock 10block = Block(in_channels=512, add_channel=False, downsample=False)x = torch.randn(1, 512, 28, 28)out = block(x)
# Codeblock 10 Outputauthentic             : torch.Dimension([1, 512, 28, 28])no projection        : torch.Dimension([1, 512, 28, 28])after conv0-bn0-relu : torch.Dimension([1, 256, 28, 28])after conv1-bn1-relu : torch.Dimension([1, 256, 28, 28])after conv2-bn2      : torch.Dimension([1, 512, 28, 28])after cbam           : torch.Dimension([1, 512, 28, 28])    #(1)after summation      : torch.Dimension([1, 512, 28, 28])

···

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.

# Codeblock 11class CBAMResNeXt(nn.Module):    def __init__(self):        tremendous().__init__()        # conv1 stage        self.resnext_conv1 = nn.Conv2d(in_channels=NUM_CHANNELS[0],                                       out_channels=NUM_CHANNELS[1],                                       kernel_size=7,                                       stride=2,                                       padding=3,                                        bias=False)        nn.init.kaiming_normal_(self.resnext_conv1.weight,                                 nonlinearity='relu')        self.resnext_bn1 = nn.BatchNorm2d(num_features=NUM_CHANNELS[1])        self.relu = nn.ReLU()        self.resnext_maxpool1 = nn.MaxPool2d(kernel_size=3,                                             stride=2,                                              padding=1)        # conv2 stage        self.resnext_conv2 = nn.ModuleList([            Block(in_channels=NUM_CHANNELS[1],                  add_channel=True,                  channel_multiplier=4,                  downsample=False)        ])        for _ in vary(NUM_BLOCKS[0]-1):            self.resnext_conv2.append(Block(in_channels=NUM_CHANNELS[2]))        # conv3 stage        self.resnext_conv3 = nn.ModuleList([Block(in_channels=NUM_CHANNELS[2],                                                  add_channel=True,                                                   downsample=True)])        for _ in vary(NUM_BLOCKS[1]-1):            self.resnext_conv3.append(Block(in_channels=NUM_CHANNELS[3]))                                # conv4 stage        self.resnext_conv4 = nn.ModuleList([Block(in_channels=NUM_CHANNELS[3],                                                  add_channel=True,                                                   downsample=True)])                for _ in vary(NUM_BLOCKS[2]-1):            self.resnext_conv4.append(Block(in_channels=NUM_CHANNELS[4]))                                # conv5 stage        self.resnext_conv5 = nn.ModuleList([Block(in_channels=NUM_CHANNELS[4],                                                  add_channel=True,                                                   downsample=True)])                for _ in vary(NUM_BLOCKS[3]-1):            self.resnext_conv5.append(Block(in_channels=NUM_CHANNELS[5]))                self.avgpool = nn.AdaptiveAvgPool2d(output_size=(1,1))        self.fc = nn.Linear(in_features=NUM_CHANNELS[5],                            out_features=NUM_CLASSES)    def ahead(self, x):        print(f'originaltt: {x.dimension()}')                x = self.relu(self.resnext_bn1(self.resnext_conv1(x)))        print(f'after resnext_conv1t: {x.dimension()}')                x = self.resnext_maxpool1(x)        print(f'after resnext_maxpool1t: {x.dimension()}')                for i, block in enumerate(self.resnext_conv2):            x = block(x)            print(f'after resnext_conv2 #{i}t: {x.dimension()}')                    for i, block in enumerate(self.resnext_conv3):            x = block(x)            print(f'after resnext_conv3 #{i}t: {x.dimension()}')                    for i, block in enumerate(self.resnext_conv4):            x = block(x)            print(f'after resnext_conv4 #{i}t: {x.dimension()}')                    for i, block in enumerate(self.resnext_conv5):            x = block(x)            print(f'after resnext_conv5 #{i}t: {x.dimension()}')                x = self.avgpool(x)        print(f'after avgpooltt: {x.dimension()}')                x = torch.flatten(x, start_dim=1)        print(f'after flattentt: {x.dimension()}')                x = self.fc(x)        print(f'after fctt: {x.dimension()}')                return x

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.

# Codeblock 12cbamresnext = CBAMResNeXt()x = torch.randn(1, 3, 224, 224)out = cbamresnext(x)

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. 

# Codeblock 12 Outputauthentic               : torch.Dimension([1, 3, 224, 224])after resnext_conv1    : torch.Dimension([1, 64, 112, 112])after resnext_maxpool1 : torch.Dimension([1, 64, 56, 56])after resnext_conv2 #0 : torch.Dimension([1, 256, 56, 56])after resnext_conv2 #1 : torch.Dimension([1, 256, 56, 56])after resnext_conv2 #2 : torch.Dimension([1, 256, 56, 56])after resnext_conv3 #0 : torch.Dimension([1, 512, 28, 28])after resnext_conv3 #1 : torch.Dimension([1, 512, 28, 28])after resnext_conv3 #2 : torch.Dimension([1, 512, 28, 28])after resnext_conv3 #3 : torch.Dimension([1, 512, 28, 28])after resnext_conv4 #0 : torch.Dimension([1, 1024, 14, 14])after resnext_conv4 #1 : torch.Dimension([1, 1024, 14, 14])after resnext_conv4 #2 : torch.Dimension([1, 1024, 14, 14])after resnext_conv4 #3 : torch.Dimension([1, 1024, 14, 14])after resnext_conv4 #4 : torch.Dimension([1, 1024, 14, 14])after resnext_conv4 #5 : torch.Dimension([1, 1024, 14, 14])after resnext_conv5 #0 : torch.Dimension([1, 2048, 7, 7])after resnext_conv5 #1 : torch.Dimension([1, 2048, 7, 7])after resnext_conv5 #2 : torch.Dimension([1, 2048, 7, 7])after avgpool          : torch.Dimension([1, 2048, 1, 1])after flatten          : torch.Dimension([1, 2048])after fc               : torch.Dimension([1, 1000])

···

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].

Tags: CBAMDoubleAttentionMechanismPaperWalkthrough

Related Posts

1789481785421 ubs6xz.webp.webp
Artificial Intelligence

GraphRAG: A Practitioner’s Information to six Superior Architectural Patterns

September 20, 2026
1789283071488 524xny.png
Artificial Intelligence

One Vendor, 4 Spellings: How Deterministic Phases Beat Similarity Scores

September 20, 2026
1789483180988 pmmj7o.jpg
Artificial Intelligence

Beginning a Profession in Information Science within the Age of AI

September 19, 2026
1789578264712 cov179.jpeg
Artificial Intelligence

Coding Brokers Preserve Delivery Silent Failures — Right here Is The best way to Catch Them

September 18, 2026
Codex Image 7 Aug 2026 21 16 18.png
Artificial Intelligence

Constructing a Information Lakehouse with DuckDB and DuckLake

September 18, 2026
1789330856875 qybhsj.webp.webp
Artificial Intelligence

The KV Cache Tax: Why Inference Servers Run Out of Reminiscence Earlier than Compute

September 17, 2026

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

POPULAR NEWS

Gemini 2.0 Fash Vs Gpt 4o.webp.webp

Gemini 2.0 Flash vs GPT 4o: Which is Higher?

January 19, 2025
Chainlink Link And Cardano Ada Dominate The Crypto Coin Development Chart.jpg

Chainlink’s Run to $20 Beneficial properties Steam Amid LINK Taking the Helm because the High Creating DeFi Challenge ⋆ ZyCrypto

May 17, 2025
Image 100 1024x683.png

Easy methods to Use LLMs for Highly effective Computerized Evaluations

August 13, 2025
Blog.png

XMN is accessible for buying and selling!

October 10, 2025
0 3.png

College endowments be a part of crypto rush, boosting meme cash like Meme Index

February 10, 2025

EDITOR'S PICK

Image 37.jpg

Easy methods to Use GPT-5 Successfully

November 9, 2025
Py spy article image.jpg

Why Is My Code So Gradual? A Information to Py-Spy Python Profiling

February 6, 2026
Bitcoin Iran.jpg

Will Bitcoin Pay the Value Once more?

July 15, 2026
Gpt 5 6 first impressions cover.jpg

The right way to Get the Most Out of Claude Fable 5

July 16, 2026

About Us

Welcome to News AI World, your go-to source for the latest in artificial intelligence news and developments. Our mission is to deliver comprehensive and insightful coverage of the rapidly evolving AI landscape, keeping you informed about breakthroughs, trends, and the transformative impact of AI technologies across industries.

Categories

  • Artificial Intelligence
  • ChatGPT
  • Crypto Coins
  • Data Science
  • Machine Learning

Recent Posts

  • CBAM Paper Walkthrough: The Double-Consideration Mechanism
  • North Korean Pretend Recruiters Steal $10.7M in Crypto
  • GraphRAG: A Practitioner’s Information to six Superior Architectural Patterns
  • Home
  • About Us
  • Contact Us
  • Disclaimer
  • Privacy Policy

© 2024 Newsaiworld.com. All rights reserved.

No Result
View All Result
  • Home
  • Artificial Intelligence
  • ChatGPT
  • Data Science
  • Machine Learning
  • Crypto Coins
  • Contact Us

© 2024 Newsaiworld.com. All rights reserved.

Are you sure want to unlock this post?
Unlock left : 0
Are you sure want to cancel subscription?