【CV中的Attention机制】CBAM的姊妹篇-BAM模块

  • 1. BAM

BAM全程是bottlenect attention module,与CBAM很相似的起名,还是CBAM的团队完成的作品。

CBAM被ECCV18接受,BAM被BMVC18接收。

CBAM可以看做是通道注意力机制和空间注意力机制的串联(先通道后空间),BAM可以看做两者的并联。

这个模块之所以叫bottlenect是因为这个模块放在DownSample 也就是pooling layer之前,如下图所示:

由于改论文与上一篇:CBAM的理论部分极为相似,下边直接进行实现部分。

2. 通道部分的实现

class Flatten(nn.Module):
    def forward(self, x):
        return x.view(x.size(0), -1)

class ChannelGate(nn.Module):
    def __init__(self, gate_channel, reduction_ratio=16, num_layers=1):
        super(ChannelGate, self).__init__()
        self.gate_c = nn.Sequential()
        self.gate_c.add_module('flatten', Flatten())

        gate_channels = [gate_channel]  # eg 64
        gate_channels += [gate_channel // reduction_ratio] * num_layers  # eg 4
        gate_channels += [gate_channel]  # 64
        # gate_channels: [64, 4, 4]

        for i in range(len(gate_channels) - 2):
            self.gate_c.add_module(
                'gate_c_fc_%d' % i,
                nn.Linear(gate_channels[i], gate_channels[i + 1]))
            self.gate_c.add_module('gate_c_bn_%d' % (i + 1),
                                   nn.BatchNorm1d(gate_channels[i + 1]))
            self.gate_c.add_module('gate_c_relu_%d' % (i + 1), nn.ReLU())

        self.gate_c.add_module('gate_c_fc_final',
                               nn.Linear(gate_channels[-2], gate_channels[-1]))

    def forward(self, x):
        avg_pool = F.avg_pool2d(x, x.size(2), stride=x.size(2))
        return self.gate_c(avg_pool).unsqueeze(2).unsqueeze(3).expand_as(x)

看上去代码要比CBAM中的ChannelAttention模块要多很多,贴上ChannelAttention代码方便对比:

class ChannelAttention(nn.Module):
    def __init__(self, in_planes, rotio=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)

        self.sharedMLP = nn.Sequential(
            nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False), nn.ReLU(),
            nn.Conv2d(in_planes // rotio, in_planes, 1, bias=False))
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avgout = self.sharedMLP(self.avg_pool(x))
        maxout = self.sharedMLP(self.max_pool(x))
        return self.sigmoid(avgout + maxout)

首先讲ChannelGate的处理流程:

  • 使用avg_pool2d测试

    >>> import torch.nn.functional as F
    >>> import torch
    >>> x = torch.ones((12, 8, 64, 64))
    >>> x.shape
    torch.Size([12, 8, 64, 64])
    >>> F.avg_pool2d(x,x.size(2), stride=x.size(2)).shape
    torch.Size([12, 8, 1, 1])
    >>>

    其效果与AdaptiveAvgPool2d(1)是一样的。

  • 然后经过gate_c模块,里边先经过Flatten将其变为[batch size, channel]形状的tensor, 然后后边一大部分都是Linear模块,进行线性变换。(ps:虽然代码看上去多,但是功能也就那样)这个部分与SE模块有一点相似,但是要更丰富一点。
  • 最终按照输入tensor x的形状进行扩展,得到关于通道的注意力。

然后讲一下与CBAM中的区别:

  • CBAM中使用的是卷积实现的通道处理,这里使用的是线性变换Linear,但是背后的数学原理应该是一致的,区别在于计算量上
  • CBAM中激活函数使用sigmoid, BAM中的通道部分使用了ReLU,还添加了BN层

3. 空间注意力机制

class SpatialGate(nn.Module):
    def __init__(self,
                 gate_channel,
                 reduction_ratio=16,
                 dilation_conv_num=2,
                 dilation_val=4):
        super(SpatialGate, self).__init__()
        self.gate_s = nn.Sequential()

        self.gate_s.add_module(
            'gate_s_conv_reduce0',
            nn.Conv2d(gate_channel,
                      gate_channel // reduction_ratio,
                      kernel_size=1))
        self.gate_s.add_module('gate_s_bn_reduce0',
                               nn.BatchNorm2d(gate_channel // reduction_ratio))
        self.gate_s.add_module('gate_s_relu_reduce0', nn.ReLU())

        # 进行多个空洞卷积,丰富感受野
        for i in range(dilation_conv_num):
            self.gate_s.add_module(
                'gate_s_conv_di_%d' % i,
                nn.Conv2d(gate_channel // reduction_ratio,
                          gate_channel // reduction_ratio,
                          kernel_size=3,
                          padding=dilation_val,
                          dilation=dilation_val))
            self.gate_s.add_module(
                'gate_s_bn_di_%d' % i,
                nn.BatchNorm2d(gate_channel // reduction_ratio))
            self.gate_s.add_module('gate_s_relu_di_%d' % i, nn.ReLU())

        self.gate_s.add_module(
            'gate_s_conv_final',
            nn.Conv2d(gate_channel // reduction_ratio, 1, kernel_size=1))

    def forward(self, x):
        return self.gate_s(x).expand_as(x)

这里可以看出,代码量相比CBAM中的spatial attention要大很多,依然进行对比:

class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
        assert kernel_size in (3,7), "kernel size must be 3 or 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 = torch.mean(x, dim=1, keepdim=True)
        maxout, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avgout, maxout], dim=1)
        x = self.conv(x)
        return self.sigmoid(x)

这个部分空间注意力处理就各有特色了,先说一下BAM中的流程:

  • 先经过一个conv+bn+relu模块,通道缩进,信息进行压缩
  • 然后经过了两个dilated conv+bn+relu模块,空洞率设置为4(默认)
  • 最后经过一个卷积,将通道压缩到1
  • 最终将其扩展为tensor x的形状

区别在于:

  • CBAM中通过通道间的max,avg处理成通道数为2的feature, 然后通过卷积+Sigmoid得到最终的map
  • BAM中则全部通过卷积或者空洞卷积完成信息处理,计算量更大一点, 但是融合了多感受野,信息更加丰富。

4. BAM融合

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, x):
        att = 1 + F.sigmoid(self.channel_att(x) * self.spatial_att(x))
        return att * x

最终融合很简单,需要注意的就是两者是相乘的,并且使用了sigmoid进行归一化。


后记:感觉BAM跟CBAM相比有一点点复杂,没有CBAM的那种简洁美。这两篇都是坐着在同一时期进行发表的,所以并没有互相的一个详细的对照,但是大概看了一下,感觉CBAM效果好于BAM。

原文地址:https://www.cnblogs.com/pprp/p/12146720.html

时间: 2024-10-08 23:28:03

【CV中的Attention机制】CBAM的姊妹篇-BAM模块的相关文章

【CV中的Attention机制】易于集成的Convolutional Block Attention Module(CBAM模块)

前言: 这是CV中的Attention机制专栏的第一篇博客,并没有挑选实现起来最简单的SENet作为例子,而是使用了CBAM作为第一个讲解的模块,这是由于其使用的广泛性以及易于集成.目前cv领域借鉴了nlp领域的attention机制以后生产出了很多有用的基于attention机制的论文,attention机制也是在2019年论文中非常火.这篇cbam虽然是在2018年提出的,但是其影响力比较深远,在很多领域都用到了该模块,所以一起来看一下这个模块有什么独到之处,并学着实现它. 1. 什么是注意

【CV中的Attention机制】BiSeNet中的FFM模块与ARM模块

前言:之前介绍过一个语义分割中的注意力机制模块-scSE模块,效果很不错.今天讲的也是语义分割中使用到注意力机制的网络BiSeNet,这个网络有两个模块,分别是FFM模块和ARM模块.其实现也很简单,不过作者对注意力机制模块理解比较深入,提出的FFM模块进行的特征融合方式也很新颖. 1. 简介 语义分割需要丰富的空间信息和相关大的感受野,目前很多语义分割方法为了达到实时推理的速度选择牺牲空间分辨率,这可能会导致比较差的模型表现. BiSeNet(Bilateral Segmentation Ne

【CV中的Attention机制】Selective Kernel Networks(SE进化版)

1. SKNet SKNet是SENet的加强版,结合了SE opetator, Merge-and-Run Mappings以及attention on inception block的产物.其最终提出的也是与SE类似的一个模块,名为SK, 可以自适应调节自身的感受野.据作者说,该模块在超分辨率任务上有很大提升,并且论文中的实验也证实了在分类任务上有很好的表现. 这篇博客重画了SK模块示意图,详见下图,下图中上边的部分是重画的,下边的是论文中的图,虽然比较简洁,但是比较难理解.上边重画的部分分

【从零开始学习YOLOv3】7. 教你在YOLOv3模型中添加Attention机制

前言:[从零开始学习YOLOv3]系列越写越多,本来安排的内容比较少,但是在阅读代码的过程中慢慢发掘了一些新的亮点,所以不断加入到这个系列中.之前都在读YOLOv3中的代码,已经学习了cfg文件.模型构建等内容.本文在之前的基础上,对模型的代码进行修改,将之前Attention系列中的SE模块和CBAM模块集成到YOLOv3中. 1. 规定格式 正如[convolutional],[maxpool],[net],[route]等层在cfg中的定义一样,我们再添加全新的模块的时候,要规定一下cfg

Deep Learning基础--理解LSTM/RNN中的Attention机制

导读 目前采用编码器-解码器 (Encode-Decode) 结构的模型非常热门,是因为它在许多领域较其他的传统模型方法都取得了更好的结果.这种结构的模型通常将输入序列编码成一个固定长度的向量表示,对于长度较短的输入序列而言,该模型能够学习出对应合理的向量表示.然而,这种模型存在的问题在于:当输入序列非常长时,模型难以学到合理的向量表示. 在这篇博文中,我们将探索加入LSTM/RNN模型中的attention机制是如何克服传统编码器-解码器结构存在的问题的. 通过阅读这篇博文,你将会学习到: 传

[NLP/Attention]关于attention机制在nlp中的应用总结

原文链接: https://blog.csdn.net/qq_41058526/article/details/80578932 attention 总结 参考:注意力机制(Attention Mechanism)在自然语言处理中的应用 Attention函数的本质可以被描述为一个查询(query)到一系列(键key-值value)对的映射,如下图. 在计算attention时主要分为三步: 第一步是将query和每个key进行相似度计算得到权重,常用的相似度函数有点积,拼接,感知机等: 第二步

[转] 深度学习中的注意力机制

from: https://zhuanlan.zhihu.com/p/37601161 注意力模型最近几年在深度学习各个领域被广泛使用,无论是图像处理.语音识别还是自然语言处理的各种不同类型的任务中,都很容易遇到注意力模型的身影.所以,了解注意力机制的工作原理对于关注深度学习技术发展的技术人员来说有很大的必要. 人类的视觉注意力 从注意力模型的命名方式看,很明显其借鉴了人类的注意力机制,因此,我们首先简单介绍人类视觉的选择性注意力机制. 图1 人类的视觉注意力 视觉注意力机制是人类视觉所特有的大

注意机制CBAM

这是一种用于前馈卷积神经网络的简单而有效的注意模块. 给定一个中间特征图,我们的模块会沿着两个独立的维度(通道和空间)依次推断注意力图,然后将注意力图乘以输入特征图以进行自适应特征修饰. 由于CBAM是轻量级的通用模块,因此可以以可忽略的开销将其无缝集成到任何CNN架构中,并且可以与基础CNN一起进行端到端训练. 为了实现这一目标,我们依次应用频道和空间关注模块(如图1所示),以便每个分支机构都可以分别学习在频道和空间轴上参与的“内容”和“位置”.结果,我们的模块通过学习要强调或抑制的信息来有效

Multimodal —— 看图说话(Image Caption)任务的论文笔记(三)引入视觉哨兵的自适应attention机制

在此前的两篇博客中所介绍的两个论文,分别介绍了encoder-decoder框架以及引入attention之后在Image Caption任务上的应用. 这篇博客所介绍的文章所考虑的是生成caption时的与视觉信息无关的词的问题,如"the"."of"这些词其实和图片内容是没什么关系的:而且,有些貌似需要视觉特征来生成的词,其实也可以直接通过语言模型来预测出来,例如"taking on a cell"后生成"phone".