BAM: Bottleneck Attention Module

BAM

参考

个人理解

  • 题外话:看完CBAM然后再看BAM,一个团队在同一天挂的两篇文章,妙啊妙啊,而且结构上也有相似之处,如果读过CBAM(参考CBAM: Convolutional Block Attention Module),那么BAM看看图和公式就可以理解了
  • 这个结构分也为两部分,关注下图红框的部分,分别为Channel attention和Spatial attention,与CBAM不同的是这俩是并行的这就比较有意思了,CBAM中的Channel和Spatial结构说是串行比较好,这里的结构说是并行比较好,这点是写的时候突然想到的,还没想明白~~

Channel attention

  • 先看Channel attention

    • image-20211014145113144
  • input是Feature Map,对HxW面做一次全局AvgPool,然后再走MLP(至于MLP的结构看上图中结构大致就知道了就是两个FC中间夹个dropout (C/r)这个样子,或者去看看CBAM: Convolutional Block Attention Module这篇对应部分原理是一样的,只是图不同),最后归一化就是Channel attention了,公式如下:

    • image-20211014145316063

Spatial attention

  • 然后看Spatial attention

  • 这个也比较一目了然,先通过1x1减少channel数(同时减少参数),然后走两个conv提Spatial的Feature,再走一个1x1减少channel到1,输出的是channel为1的Feature Map,当然另外两维还是HxW,公式的话就这样:

    • image-20211014150135637

结构合并

  • 合并的时候关注这部分:

  • 首先要把这里加起来

    • image-20211014152020379
    • 然后整体点乘加残差

    • image-20211014152734408
    • 起初我还没理解这个加号是啥意思,翻了翻代码,代码上的实现是‘*’,也就是元素点乘:

    • 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

猜你喜欢

转载自blog.csdn.net/symuamua/article/details/120772782
BAM