不定期读一篇Paper之CBAM
前言
本论文针对先前对通道注意力或者空间注意力机制,提出了一个简单又有效的注意力机制模块,该模块既注意关注通道方面,使得网络知道“what”,又针对空间方面,使得网络知道"where",两面进行调整。此外,CBAM是一个轻量化且通用的模块,它可以被整合到任何CNN架构的网络中,并且可以进行端对端的训练。
框架
CBAM有两个注意力模块:通道和空间,它们按照次序通道->空间,当然理论上也可以平行或空间->通道的连接方法,但是,作者在实验上证明通道->空间的次序连接的性能较好。下图是连接关系图:
下面首先针对通道和空间子模块进行分析。
-
通道注意力模块(what)
首先,由于特征图中,不同通道feature map刻画特征不同,所以,通道注意力机制关注对于一张图片中有意义的"what"。在计算方面,输入一个特征图F,分别在空间上进行最大池化和平均池化,保持通道维度不变,然后分别送入一个共享的全连接网络,,最后把通过共享全连接两个模块相加后,送入Sigmoid函数中,得到通道注意力模块。
Pytorch代码:
class ChannelAttention(nn.Module): def __init__(self, in_planes, rotio = 16): """ in_planes : 输入通道 rotio : 缩减率 """ super(ChannelAttention, self).__init__() self.avg_pool = nn.AdaptiveAvgPool2d(1) self.max_pool = nn.AdaptiveMaxPool2d(1) self.shareMLP = nn.Sequential( # 通过缩减,减少优化参数 nn.Conv2d(in_planes, in_planes//16, 1, bias=False), nn.ReLU(), # 返回原来的大小 nn.Conv2d(in_planes//16, in_planes, 1, bias=False) ) self.Sigmoid = nn.Sigmoid() def forward(self, x): avgout = self.shareMLP(self.avg_pool(x)) maxout = self.shareMLP(self.max_pool(x)) return self.Sigmoid(avgout + maxout)
可视化模块结构:
---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ AdaptiveAvgPool2d-1 [1, 256, 1, 1] 0 Conv2d-2 [1, 16, 1, 1] 4,096 ReLU-3 [1, 16, 1, 1] 0 Conv2d-4 [1, 256, 1, 1] 4,096 AdaptiveMaxPool2d-5 [1, 256, 1, 1] 0 Conv2d-6 [1, 16, 1, 1] 4,096 ReLU-7 [1, 16, 1, 1] 0 Conv2d-8 [1, 256, 1, 1] 4,096 Sigmoid-9 [1, 256, 1, 1] 0 ================================================================
-
空间注意力模块(where)
为了与通道注意力互补,空间注意力模块主要关注“where”的部分。为了计算首先,使用了全局最大池化和全局平均池化在保持H和W不变的情况下,针对通道进行池化,让后,把两个结果拼接后,送入一个标准的卷积层,最后,通过sigmoid函数,得到空间注意力模块。
Pytorch代码:
class SpatialAttention(nn.Module): def __init__(self, kernel_size = 7): super(SpatialAttention, self).__init__() assert kernel_size in (3, 7) padding = 3 if kernel_size == 7 else 1 self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False) self.sigmoid = nn.Sigmoid() def forward(self, x): # 平均池化(在通道上进行均值,且保持四个维度) avgout = t.mean(x, dim = 1, keepdim = True) # 最大池化(在通道上进行最大值,且保持四个维度) maxout, _ = t.max(x, dim = 1, keepdim = True) # 拼接 x = t.cat([avgout, maxout], dim=1) x = self.conv(x) return self.sigmoid(x)
可视化模块结构:
---------------------------------------------------------------- Layer (type) Output Shape Param # ================================================================ Conv2d-1 [1, 1, 224, 224] 98 Sigmoid-2 [1, 1, 224, 224] 0 ===============================================================
实验
作者在不同的网络中加入了CBAM模块,都证明其能有效的提升网络的性能和准确率,下图是作者在ResNet50加入SE模块和CBAM模块,进行Grad-CAM可视化的结果,其中p值代表所输入图像中的目标在最后的softmax中判别为该类的可能性。由下图,可以看出,加入CBAM模块后,网络注意力更加的全面,并且其判别准确率显著的提升。
结论
CBAM是一个非常好的注意力模块,融合空间和通道信息,使我们让网络关注输入图像的“what”和“where”两个方面的信息,当然由于其通用性,其可以嵌入任何CNN网络中,且效果明显,所以个人认为这是一篇不错的paper。最后,本文在表述上难免有不准确的地方,建议感兴趣的可以读原文。
参考
【CV中的Attention机制】易于集成的Convolutional Block Attention Module(CBAM模块)