BAM
参考
个人理解
- 题外话:看完CBAM然后再看BAM,一个团队在同一天挂的两篇文章,妙啊妙啊,而且结构上也有相似之处,如果读过CBAM(参考CBAM: Convolutional Block Attention Module),那么BAM看看图和公式就可以理解了
- 这个结构分也为两部分,关注下图红框的部分,分别为Channel attention和Spatial attention,与CBAM不同的是这俩是并行的这就比较有意思了,CBAM中的Channel和Spatial结构说是串行比较好,这里的结构说是并行比较好,这点是写的时候突然想到的,还没想明白~~
Channel attention
-
先看Channel attention
-
input是Feature Map,对HxW面做一次全局AvgPool,然后再走MLP(至于MLP的结构看上图中结构大致就知道了就是两个FC中间夹个dropout (C/r)这个样子,或者去看看CBAM: Convolutional Block Attention Module这篇对应部分原理是一样的,只是图不同),最后归一化就是Channel attention了,公式如下:
Spatial attention
-
然后看Spatial attention
-
这个也比较一目了然,先通过1x1减少channel数(同时减少参数),然后走两个conv提Spatial的Feature,再走一个1x1减少channel到1,输出的是channel为1的Feature Map,当然另外两维还是HxW,公式的话就这样:
结构合并
-
合并的时候关注这部分:
-
首先要把这里加起来
-
然后整体点乘加残差
-
起初我还没理解这个加号是啥意思,翻了翻代码,代码上的实现是‘*’,也就是元素点乘:
-
class BAM(nn.Module): def __init__(self, gate_channel): super(BAM, self).__init__() self.channel_att = ChannelGate(gate_channel) self.spatial_att = SpatialGate(gate_channel) def forward(self,in_tensor): att = 1 + F.sigmoid( self.channel_att(in_tensor) * self.spatial_att(in_tensor) ) return att * in_tensor
-
稍微研究一下上面的代码不难发现,
att * in_tensor
是这么个逻辑:F(1+M(F)),因此得出结论上面第一个公式中的加号应该是元素点乘,属于笔误
-
然后我研究了下‘*’这个符号的计算过程,如下所示,如果不同形状的点乘会先得到下面的结果:
如何融入ResBlock中?
- 作者给的图上画着这个是加载block之间的,而CBAM是加载block内部的,但实际上我认为可以任意位置
效果如何?
-
和CBAM的对应实验比较一下就知道这个结构的整体效果不如CBAM
-
结尾可能有点意思的参考文献:42、27、26、9