精华内容
下载资源
问答
  • 两篇论文 《CBAM: Convolutional Block Attention Module》2018 ECCV 《BAM: Bottleneck Attention Module》2018 BWVC channel attention 通道注意力 spatial attention 空间注意力
  • CBAM注意力机制.py

    2021-08-05 19:36:11
    keras实现CBAM注意力机制模块
  • SENET与 CBAM 注意力机制

    千次阅读 多人点赞 2020-10-27 09:31:08
    文章目录一、SENETSE的代码实现二、CBAM模块CBAM代码实现 一、SENET SENET是2017年的世界冠军,SE全称Squeeze-and-Excitation是一个模块,将现有的网络嵌入SE模块的话,那么该网络就是SENet,它几乎可以嵌入当前流行...

    一、SENET

    SENET是2017年的世界冠军,SE全称Squeeze-and-Excitation是一个模块,将现有的网络嵌入SE模块的话,那么该网络就是SENet,它几乎可以嵌入当前流行的任何网络,那么为什么会引出这个东西呢,来看下图:

    在这里插入图片描述

    • SE结构
      一个SEblock的过程分为 Squeeze(压缩)Excitation(激发) 两个步骤:
      Squeeze(压缩) 通过在Feature Map层上执行Global Average Pooling,得到当前Feature Map的全局压缩特征量;
      Excitation(激发) 通过两层全连接的bottleneck结构得到Feature Map中每个通道的权值,并将加权后的Feature Map作为下一层网络的输入

    一个feature map经过一系列卷积池化得到的feature map,通常我们认为这个得到的feature map的每个通道都是同样重要的,我们并没有分那个通道重要,那个通道不怎么重要,那么实际上会不会有这种情况呢,就是得到的featurmap 的每个通道的重要性都不一样,比如确实有的图片三个通道,我只有一个通道有用,其它通道没什么用,比如一张包含动物的图片,那么背景肯定不怎么重要,它转化为灰度图后,只有一个通道比较重要,其它的不怎么重要,那么其实实际上我们得到的feature map每个通道的重要程度还是不一样的,也就是说每个通道其实还应该有一个重要性权值才行,然后每个通道的重要性权值乘以每个通道原来的值,就是我们求的真正feature map,这个feature map不同的通道重要性不一样(可能权值大的乘以原来的数要大些)如上面得到最终图,每个通道颜色不一样,也就代表着不同的重要性

    那么每个通道的权值或者重要性怎么来呢,就是上面这块,做法如下:
    在这里插入图片描述
    其实很简单,假入原来feature map 是 h * w * c的,给它做一个global池化(池化窗口就是h * w 得到的就是1 * 1窗口,通道数不变)得到 1 * 1 * c的feature map,然后它再接两个全连接层(第一个全连接层神经元个数是c/16,相当于对c进行了降维,输入是c个特征,第二个全连接层神经元个数为c,相当于又增维回到了c个特征,这样做比直接用一个 Fully Connected 层的好处在于具有更多的非线性,可以更好地拟合通道间复杂的相关性,极大地减少了参数量和计算量),然后再接一个sigmod层(这里采用sigmod应该是通道之间是具有相关性的,所以不能用softmax,softmax的话,最终加起来必须为1),输出1 * 1 * c,
    原来的feature map维度h * w * c,得到的是通道的权值维度1 * 1 * c,然后它们进行相乘,这里是全乘,不是矩阵相乘,然后得到的feature map对应的每个通道重要性就不一样了(可能更重要的它的值要大些)
    那么h * w * c 和1 * 1 * c 是怎么相乘的呢?看一个例子
    在这里插入图片描述
    在这里插入图片描述
    像这样相乘

    这个是一个通道的,看到没它乘的倍率是1,

    这个通道的倍率是乘2

    它就是这么实现不同通道乘以不同的倍率,从而得到不同的重要性的
    相当于是每次乘以一列通道

    注意:对于图片数组,我们来熟悉下:
    在这里插入图片描述
    一行

    一行里面一个像素点对应的一列通道

    一个像素
    注意:
    每个通道的权值都是网路学习出来的,那么怎么学习呢,记住学习,只要有参数和loss就可以,如下
    在这里插入图片描述
    所以它主要学习的是SE模块这两个全连接层的参数,它们学到了,自然最终结果就有了,所用用最终的分类损失去更新这两个全连接层的参数就可以了
    #注意上面采用两层全连接,第一层全连接单元个数为c/16,主要是为了压缩参数的如下,
    c. * c/r + c/r * c = 2c2/r = 2/r * c2
    只用一层全连接参数的话参数个数:
    c * c = c * 2

    实际中可能会用一个比例reduction_ratio
    reduction_ratio = 0.5的话
    那么就是c * 0.5c + 0.5c * c = c2
    reduction_ratio如果 = 0.3的话那么就是c * 0.3c + 0.3c * c = 0.6
    c2
    如果只用一层全连接层的话那么就是
    c * c = c * 2个,显然参数减少了0.4c
    2个

    SE的代码实现

    SE模块实现的 Pytorch版:

    class SELayer(nn.Module):
        def __init__(self, channel, reduction=16):
            super(SELayer, self).__init__()
            self.avg_pool = nn.AdaptiveAvgPool2d(1)
            self.fc = nn.Sequential(
                nn.Linear(channel, channel // reduction, bias=False),
                nn.ReLU(inplace=True),
                nn.Linear(channel // reduction, channel, bias=False),
                nn.Sigmoid()
            )
    
        def forward(self, x):
            b, c, _, _ = x.size()
            y = self.avg_pool(x).view(b, c)
            y = self.fc(y).view(b, c, 1, 1)
            return x * y.expand_as(x)
    12345678910111213141516
    

    SE-ResNet模型的 Pytorch版:

    class SEBottleneck(nn.Module):
            expansion = 4
    
            def __init__(self, inplanes, planes, stride=1, downsample=None, reduction=16):
                super(SEBottleneck, self).__init__()
                self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False)
                self.bn1 = nn.BatchNorm2d(planes)
                self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride,
                                       padding=1, bias=False)
                self.bn2 = nn.BatchNorm2d(planes)
                self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False)
                self.bn3 = nn.BatchNorm2d(planes * 4)
                self.relu = nn.ReLU(inplace=True)
                self.se = SELayer(planes * 4, reduction)
                self.downsample = downsample
                self.stride = stride
    
            def forward(self, x):
                residual = x
    
                out = self.conv1(x)
                out = self.bn1(out)
                out = self.relu(out)
    
                out = self.conv2(out)
                out = self.bn2(out)
                out = self.relu(out)
    
                out = self.conv3(out)
                out = self.bn3(out)
                out = self.se(out)
    
                if self.downsample is not None:
                    residual = self.downsample(x)
    
                out += residual
                out = self.relu(out)
    
                return out
    123456789101112131415161718192021222324252627282930313233343536373839
    

    二、CBAM模块

    CBAM

    它是2018年的分类冠军,它和SE一样也是一个模型,现在任何流行网络都可以嵌入这个模块,那么它的由来是什么呢?
    SE的由来是因为不同通道的像素的重要性可能不一样,那么既然这样,同一个通道的不同位置像素重要性也可能不一样,所以就有了CBAM,既考虑不同通道像素的重要性,又考虑了同一通道不同位置像素的重要性

    • 组成
      该注意力模块( CBAM ),可以在通道和空间维度上进行 Attention 。其包含两个子模块 Channel Attention Module(CAM)Spartial Attention Module(SAM)

    Convolutional Block Attention Module (CBAM) 表示卷积模块的注意力机制模块。是一种结合了空间(spatial)和通道(channel)的注意力机制模块。相比于senet只关注通道(channel)的注意力机制可以取得更好的效果。
    它相对于SE多了一个空间attension,这个空间其实就是宽高对应的方形或者说是一个通道对应的feature map,SE只关注通道,它既关注通道,也关注宽高,
    它的大概流程如下:

    在这里插入图片描述

    • CAM的结构与SE有何区别?
      其结构如上图所示,相比SE,只是多了一个并行的Max Pooling层。那为什么加个并行的呢?结果导向,作者通过实验说明这样的效果好一些,我感觉其好一些的原因应该是多一种信息编码方式,使得获得的信息更加全面了吧,可能再加一些其他并行操作效果会更好?

    先来看通道上的attension:
    在这里插入图片描述
    它这里和SE模块有点区别就是,SE只用了一个池化globalpool(一般是maxpool),而它这里用了两个池化maxpool,avgpool(池化本身是提取高层次特征,不同的池化意味着提取的高层次特征更加丰富),既然是两个那么输出肯定也是两个都是11c,然后将输出两个相加,再进行sigmod,结果也是11c,然后再和原来的feature map相乘
    然后再来看空间上的attension
    在这里插入图片描述
    它的过程也很简单:
    它是原来的feature map先做完通道attension ,然后它在这个基础之上进一步做空间attension的,它先将feature map 进行基于通道的池化,一般的池化都是在长宽的维度,它这个其实就是在列通道的维度池化(取一列通道的最大值,平均值),这就意味着一次池化一列通道变成了一个值就是一个通道了,长宽不变,假如输入feature map是 h * w * c,它这个一次池化后就变成了h * w * 1的feature map了,它进行了两次池化,那就是两个h * w * 1的feature map,然后将它们进行基于通道的拼接,那就变成了 h * w * 2的feature map了,然后对这个feature map用一个7*7的卷积核进行卷积,将通道数压缩成了1(因为只用了一个卷积核),得到一个新的feature map,然后对这个feature map进行sigmod的,得到一个attension feature map,然后将它和最开始的feature map进行相乘,比如下面:
    原先的经过channel attension后的feature map是 h * w * c,那么经过空间attension后,它得到的attension feature map就是 h * w * 1了,那么它们怎么相乘呢,如下:
    b.shape = (2,2,3)
    在这里插入图片描述
    这一列就是一个通道上的像素,显然,他每次乘都是乘以一个通道上的像素,对一个通道上的像素进行增大或者缩小,下一次再乘以另外一个通道的

    最终它这个空间attension feature map肯定也是学习出来的,那么具体是学习什么呢?肯定是参数,它这个过程有哪些参数,其实就是再到数第二步,用一个77的卷积核对输入的2层feature map卷积,那么它学习的就是这个77的卷积核参数

    代码实现

    def cbam_module(inputs,reduction_ratio=0.5,name=""):
        with tf.variable_scope("cbam_"+name, reuse=tf.AUTO_REUSE):
            #假如输入是[batsize,h,w,channel],
            #channel attension 因为要得到batsize * 1 * 1 * channel,它的全连接层第一层
          #隐藏层单元个数是channel / r, 第二层是channel,所以这里把channel赋值给hidden_num
            batch_size,hidden_num=inputs.get_shape().as_list()[0],inputs.get_shape().as_list()[3]
     
           #通道attension
            #全局最大池化,窗口大小为h * w,所以对于这个数据[batsize,h,w,channel],他其实是求每个h * w面积的最大值
          #这里实现是先对h这个维度求最大值,然后对w这个维度求最大值,平均池化也一样
            maxpool_channel=tf.reduce_max(tf.reduce_max(inputs,axis=1,keepdims=True),axis=2,keepdims=True)
            avgpool_channel=tf.reduce_mean(tf.reduce_mean(inputs,axis=1,keepdims=True),axis=2,keepdims=True)
            
            #上面全局池化结果为batsize * 1 * 1 * channel,它这个拉平输入到全连接层
          #这个拉平,它会保留batsize,所以结果是[batsize,channel]
            maxpool_channel = tf.layers.Flatten()(maxpool_channel)
            avgpool_channel = tf.layers.Flatten()(avgpool_channel)
            
            #将上面拉平后结果输入到全连接层,第一个全连接层hiddensize = channel/r = channel * reduction_ratio,
          #第二哥全连接层hiddensize = channel
            mlp_1_max=tf.layers.dense(inputs=maxpool_channel,units=int(hidden_num*reduction_ratio),name="mlp_1",reuse=None,activation=tf.nn.relu)
            mlp_2_max=tf.layers.dense(inputs=mlp_1_max,units=hidden_num,name="mlp_2",reuse=None)
            #全连接层输出结果为[batsize,channel],这里又降它转回到原来维度batsize * 1 * 1 * channel,
           mlp_2_max=tf.reshape(mlp_2_max,[batch_size,1,1,hidden_num])
     
            mlp_1_avg=tf.layers.dense(inputs=avgpool_channel,units=int(hidden_num*reduction_ratio),name="mlp_1",reuse=True,activation=tf.nn.relu)
            mlp_2_avg=tf.layers.dense(inputs=mlp_1_avg,units=hidden_num,name="mlp_2",reuse=True)
            mlp_2_avg=tf.reshape(mlp_2_avg,[batch_size,1,1,hidden_num])
     
            #将平均和最大池化的结果维度都是[batch_size,1,1,channel]相加,然后进行sigmod,维度不变
            channel_attention=tf.nn.sigmoid(mlp_2_max+mlp_2_avg)
             #和最开始的inputs相乘,相当于[batch_size,1,1,channel] * [batch_size,h,w,channel]
           #只有维度一样才能相乘,这里相乘相当于给每个通道作用了不同的权重
            channel_refined_feature=inputs*channel_attention
     
           
            #空间attension
            #上面得到的结果维度依然是[batch_size,h,w,channel],
          #下面要进行全局通道池化,其实就是一条通道里面那个通道的值最大,其实就是对channel这个维度求最大值
          #每个通道池化相当于将通道压缩到了1维,有两个池化,结果为两个[batch_size,h,w,1]feature map
            maxpool_spatial=tf.reduce_max(inputs,axis=3,keepdims=True)
            avgpool_spatial=tf.reduce_mean(inputs,axis=3,keepdims=True)
    
            #将两个[batch_size,h,w,1]的feature map进行通道合并得到[batch_size,h,w,2]的feature map
            max_avg_pool_spatial=tf.concat([maxpool_spatial,avgpool_spatial],axis=3)
    
           #然后对上面的feature map用1个7*7的卷积核进行卷积得到[batch_size,h,w,1]的feature map,因为是用一个卷积核卷的
         #所以将2个输入通道压缩到了1个输出通道
            conv_layer=tf.layers.conv2d(inputs=max_avg_pool_spatial, filters=1, kernel_size=(7, 7), padding="same", activation=None)
          #然后再对上面得到的[batch_size,h,w,1]feature map进行sigmod,这里为什么要用一个卷积核压缩到1个通道,相当于只得到了一个面积的值
         #然后进行sigmod,因为我们要求的就是feature map面积上不同位置像素的中重要性,所以它压缩到了一个通道,然后求sigmod
            spatial_attention=tf.nn.sigmoid(conv_layer)
     
           #上面得到了空间attension feature map [batch_size,h,w,1],然后再用这个和经过空间attension作用的结果相乘得到最终的结果
         #这个结果就是经过通道和空间attension共同作用的结果
            refined_feature=channel_refined_feature*spatial_attention
     
        return refined_feature
    
    • 参考文献
      CV领域常用的注意力机制模块(SE、CBAM)_weixin_42907473的博客-CSDN博客
      https://blog.csdn.net/weixin_42907473/article/details/106525668
      深度学习之卷积网络attention机制SENET、CBAM模块原理总结_weixin_33602281的博客-CSDN博客
      https://blog.csdn.net/weixin_33602281/article/details/85223216
    展开全文
  • 注意力机制使用;卷积神经网络的变体keras实现
  • Attention

    Attention

     在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 注意力机制CBAM实现

    千次阅读 2020-05-11 17:19:50
    提出了一个简单但有效的注意力模块 CBAM,给定一个中间特征图,沿着空间和通道两个维度依次推断出注意力权重,然后与原特征图相乘来对特征进行自适应调整。由于 CBAM 是一个轻量级的通用模块,它可以无缝地集成到...

    1.CBAM简介

    论文:CBAM: Convolutional Block Attention
    Module
    提出了一个简单但有效的注意力模块 CBAM,给定一个中间特征图,沿着空间和通道两个维度依次推断出注意力权重,然后与原特征图相乘来对特征进行自适应调整。由于 CBAM 是一个轻量级的通用模块,它可以无缝地集成到任何 CNN 架构中,额外开销忽略不计,并且可以与基本 CNN 一起进行端到端的训练。在不同的分类和检测数据集上,将 CBAM 集成到不同的模型中后,模型的表现都有了一致的提升,展示了其广泛的可应用性。
    CBAM可以分为两个部分:通道注意力模块和空间注意力模块,如下图所示。
    在这里插入图片描述

    • 通道注意力模块:关注什么(what)的特征有意义
      输入一个特征图F为HWC(实际中可能还有batch,即NHWC),首先进行一个全局空间最大池化和平均池化,得到两个11C的descriptor。再将他们分别送入MLP(含有一个隐藏层),第一层神经元个数为C/r,第二层神经元个数为C。这个神经网络是共享(不太明白,是两个descriptor共享还是两层神经网络共享,应该是后者)。再将两个输出向量运用element-wise加法,经过sigmoid函数得到权重系数Mc。最后拿Mc与原来的特征F相乘得到新特征F‘
    • 空间注意力模块:关注哪里(where)的特征有意义
      输入特征图F’为HWC(同样可能有batch),首先经过通道平均池化和最大池化得到两个HW1的描述子,并按通道拼接。然后经过一个7*7的卷积层和sigmoid激活函数,得到权重系数Ms。最后拿Ms与F‘相乘得到最终注意力特征。

    2.代码实现

    看完上面的过程就很容易理解代码的实现,这里放两份代码。一份是参考这个博主的代码,另外一份是Github:kobiso/CBAM-tensorflow
    代码一:

    def combined_static_and_dynamic_shape(tensor):
        """Returns a list containing static and dynamic values for the dimensions.  Returns a list of static 
        and dynamic values for shape dimensions. This is  useful to preserve static shapes when available in reshape operation.  
        Args:    tensor: A tensor of any type.  
        Returns:    A list of size tensor.shape.ndims containing integers or a scalar tensor.  """
        static_tensor_shape = tensor.shape.as_list()
        dynamic_tensor_shape = tf.shape(tensor)
        combined_shape = []
        for index, dim in enumerate(static_tensor_shape):
            if dim is not None:
                combined_shape.append(dim)
            else:
                combined_shape.append(dynamic_tensor_shape[index])
        return combined_shape
    
    
    def convolutional_block_attention_module(feature_map, index, reduction_ratio = 0.5):
        """CBAM:convolutional block attention module
        Args:
            feature_map:input feature map
            index:the index of the module
            reduction_ratio:output units number of first MLP layer:reduction_ratio * feature map
        Return:
            feature map with channel and spatial attention"""
    
        with tf.variable_scope("cbam_%s" % (index)):
            feature_map_shape = combined_static_and_dynamic_shape(feature_map)
            # channel attention module
            channel_avg_weights = tf.nn.avg_pool(value=feature_map,
                                                 ksize=[1, feature_map_shape[1], feature_map_shape[2], 1],
                                                 strides=[1, 1, 1, 1],
                                                 padding='VALID')  # global average pool
            channel_max_weights = tf.nn.max_pool(value=feature_map,
                                                 ksize=[1, feature_map_shape[1], feature_map_shape[2], 1],
                                                 strides=[1, 1, 1, 1],
                                                 padding='VALID')
            channel_avg_reshape = tf.reshape(channel_avg_weights,
                                             [feature_map_shape[0], 1, feature_map_shape[3]])
            channel_max_reshape = tf.reshape(channel_max_weights,
                                             [feature_map_shape[0], 1, feature_map_shape[3]])
            channel_w_reshape = tf.concat([channel_avg_reshape, channel_max_reshape], axis=1)
    
            fc_1 = tf.layers.dense(inputs=channel_w_reshape,
                                   units=feature_map_shape[3] * reduction_ratio,
                                   name="fc_1",
                                   activation=tf.nn.relu)
            fc_2 = tf.layers.dense(inputs=fc_1,
                                   units=feature_map_shape[3],
                                   name="fc_2",
                                   activation=None)
            channel_attention = tf.reduce_sum(fc_2, axis=1, name="channel_attention_sum")
            channel_attention = tf.nn.sigmoid(channel_attention)
            channel_attention = tf.reshape(channel_attention,
                                           shape=[feature_map_shape[0], 1, 1, feature_map_shape[3]])
            feature_map_with_channel_attention = tf.multiply(feature_map, channel_attention)
            # saptial attention module
            # 通道平均池化,格式NWHC
            channel_wise_avg_pooling = tf.reduce_mean(feature_map_with_channel_attention, axis=3)
            channel_wise_avg_pooling = tf.reshape(channel_wise_avg_pooling,
                                                  shape=[feature_map_shape[0], feature_map_shape[1],
                                                         feature_map_shape[2], 1]) # shape=[batch, H, W, 1]
            # 通道最大池化
            channel_wise_max_pooling = tf.reduce_max(feature_map_with_channel_attention, axis=3)
            channel_wise_max_pooling = tf.reshape(channel_wise_max_pooling,
                                                  shape=[feature_map_shape[0], feature_map_shape[1],
                                                         feature_map_shape[2], 1])
            # 按通道拼接
            channel_wise_pooling = tf.concat([channel_wise_avg_pooling, channel_wise_max_pooling], axis=3)
            spatial_attention = slim.conv2d(channel_wise_pooling, 1, [7, 7],
                                            padding='SAME',
                                            activation_fn=tf.nn.sigmoid,
                                            scope="spatial_attention_conv")
            feature_map_with_attention = tf.multiply(feature_map_with_channel_attention, spatial_attention)
            return feature_map_with_attention

    这个代码在通道注意力模块实现时,是先把两个11C的描述子拼接然后再输入到MLP,而且两个MLP层权重并没有共享,感觉有点问题。另外一份代码由于字数限制,下篇博客再放上。
    我把这个模块放到我的一个手写体MNIST分类四层神经网络中的某一层中,但是感觉没有太多精确度提升,直观上感觉运行更慢了。论文中将CBAM插入到一些大型网络中,我感觉性能提升得也不是特别大。。。

    展开全文
  • CBAM_MNIST.py

    2020-05-15 18:36:10
    构建一个四层神经网络识别手写体数据集MNIST,然后将注意力模块CBAM插入到网络的第一层之后,查看注意力模块的性能。可以改变CBAM模块插入的位置,做到任意插入。
  • Attention.zip文件中总结了几种关于注意力机制的代码,有keras和tensorflow,还有PyTorch框架的
  • 代码:https://github.com/luuuyi/CBAM.PyTorch/issues/8 (最近在看人脸识别的轻量级网络,然后看到了与cbam相关的内容,就想尝试以下...论文的贡献:作者提出了卷积层的注意力模块(Convolutional Block Atten...

    论文链接:https://arxiv.org/abs/1807.06521v2

    代码:https://github.com/luuuyi/CBAM.PyTorch

    (最近在看人脸识别的轻量级网络,然后看到了与cbam相关的内容,就想尝试以下效果,是否有助于提升模型人脸识别的能力;)

    论文的贡献:作者提出了卷积层的注意力模块(Convolutional Block Attention Module,CBAM),这个模块分为两个部分:channel和spatial。通过与输入特征相乘,自适应的对特征进行提纯(refinement)。这种注意力模块的优点就是:1,可以和任何CNN结构一起使用,不会增加额外的开销,并且实现的是端对端的训练。然后作者在分类(ImageNet-1K)和目标检测数据集(MS COCO, VOC2007)上做实验,效果都还很不错。

    作者提出的CBAM框图:

    通过作者提出的CBAM模块,让卷积网络可以学习“what”和“where”是关注的焦点;

    作者新想法的来源是两篇参考文献,文中是参考文献【28】的channel-wise attention和参考文献【29】spatial attention;

    CBAM介绍

    中间特征:F\epsilon R^{^{C\times H\times W}}

    1Dchannel attention map:M_{c}\epsilon R^{^{C\times 1\times 1}}

    2Dspatial attention map:M_{s}\epsilon R^{^{1\times H\times W}}

    整个注意力过程:

    \otimes表示点乘(element-wise multiplication) 

    channel attention module

    首先对于输入特征先进行平均尺化(average-pooling)和最大尺化(max-pooling )产生两个两个空间信息描述:Favg和Fmax。这两个描述子进入共享网络产生channel attention map:,这个共享网络包括一个隐藏层的多层感知机。为了减少参数,隐藏激活尺寸设定为,这里r就是减少率。然后通过元素求和合并两个输出。所以通道注意力计算:

    查看代码:W1和W0是两个卷积层,同时W0后面还跟了一个relu激活,\sigma是sigmoid函数;

    class ChannelAttention(nn.Module):
        def __init__(self, in_planes, ratio=16):
            super(ChannelAttention, self).__init__()
            self.avg_pool = nn.AdaptiveAvgPool2d(1)
            self.max_pool = nn.AdaptiveMaxPool2d(1)
    
            self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)
            self.relu1 = nn.ReLU()
            self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)
    
            self.sigmoid = nn.Sigmoid()
    
        def forward(self, x):
            avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))
            max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))
            out = avg_out + max_out
            return self.sigmoid(out)

    Spatial attention module

    对于特征图的channel information使用两个尺化操作产生两个2维的特征,

    然后经过concat后,进入卷积操作;

    简言之,spatial attention 计算:

     代表是卷积核是7*7的卷积操作;

    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.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
            self.sigmoid = nn.Sigmoid()
            self.tanh = nn.Tanh()
    
        def forward(self, x):
            avg_out = torch.mean(x, dim=1, keepdim=True)#每一行的均值;
            max_out, _ = torch.max(x, dim=1, keepdim=True)#每一行的最大值;
            x = torch.cat([avg_out, max_out], dim=1)
            x = self.conv1(x)
            return self.tanh(x) + 1
    #         return self.sigmoid(x) #ori

    对于注意力机制模块的安排

    1)按照串联顺序链接;

    2)channel-first 会比spatial-first好;

    实验:

    实验部分,我很感兴趣的是SE模块和CBAM模块的对比,结果是无论是分类还是目标检测加入CBAM模块的的结果完胜;

    扩展阅读:通道注意力SE模块 https://blog.csdn.net/qq_22764813/article/details/95051082

     

     

    展开全文
  • 注意力机制CBAM详解

    万次阅读 多人点赞 2021-03-10 20:57:03
    论文题目:《CBAM: Convolutional Block Attention...论文(2018年)提出了一种轻量的注意力模块( CBAM,Convolutional Block Attention Module ),可以在通道和空间维度上进行 Attention 。论文在 ResNet 和 MobileNet
  • 文章目录摘要1 介绍2 相关工作3 卷积块注意模块(CBAM)4 实验4.1 消融研究4.2 在ImageNet-1K的图像分类4.3 使用Grad-CAM进行网络可视化4.4 MS COCO目标检测4.5 VOC 2007目标检测5 结论 摘要   CBAM:    本文...
  • 注意力机制模块——SE、CBAM

    千次阅读 2020-08-09 20:55:21
    https注意力机制模块SENetCBAM SENet SE全称Squeeze-and-Excitation,它注重通道信息。 SE的出现是为了解决在卷积池化过程中feature map的不同通道所占的重要性不同带来的损失问题。在传统的卷积池化过程中,默认...
  • 注意力机制 SENet、CBAM

    千次阅读 2020-02-06 20:35:02
    注意力机制 SENet、CBAM 机器翻译 MXNet(使用含注意力机制的编码器—解码器,即 Encoder编码器-Decoder解码器框架 + Attention注意力机制) nltk 处理文本 卷积神经网络 处理文本:word2vec、TF-IDF、TextRank、...
  • CBAM(Convolutional Block Attention Module)一种轻量的注意力模块,可以在空间和通道上进行注意力机制,沿着通道和空间两个维度推断出注意力权重系数,然后再与feature map相乘,CBAM的结构如下: 包含两个模块:...
  • 深度学习 | 双重注意力机制CBAM

    千次阅读 2019-11-08 18:33:51
    上图为整个CBAM的示意图,先是通过注意力机制模块,然后是空间注意力模块,对于两个模块先后顺序对模型性能的影响,本文作者也给出了实验的数据对比,先通道再空间要比先空间再通道以及通道和空间注意力模块并行的...
  • Keras复现CBAM注意力模块

    千次阅读 热门讨论 2020-09-23 17:52:04
    CBAM注意力机制模块介绍2.模块复现2.1 TensorFlow 2.0 卷积神经网络实战书上的代码(tf与keras混合的代码)2.2 Keras代码复现2.3 测试3. 知识点补充3.1 全局平均/最大池化3.2 Keras构建模型 1. CBAM注意力机制模块...
  •   论文地址:CBAM: Convolutional Block Attention Module   代码地址:github 文章目录1. 简介2. 结构2.1 CBAM结构2.1.1 Channel-Wise Attention2.1.2 Spatial ...  本文提出了一个CBAM注意力机制模块,和SE...
  • CBAM: Convolutional Block Attention Module PDF: https://arxiv.org/pdf/1807.06521.pdf PyTorch代码: https://github.com/shanglianlm0525/PyTorch-Networks PyTorch代码:
  • 汇总了自Non-local和SENet之后的十几篇发表于CVPR/ICCV的经典的注意力方法,包括cbam、a2net、psanet、danet、apcnet、sknet、ccnet、gcnet、annnet、ocrnet、sanet、ecanet
  • 07-CBAM_block注意力机制

    2020-02-07 10:14:51
    实现用于CNN的注意力机制的模块 """ def cbam(inputs, reduction=8): """ 变量重用,我们使用的是 tf.AUTO_REUSE :param inputs: 输入的tensor格式为: [N, H, W, C] :param reduction: :retur...
  • 注意力机制大概分为以下,Spatial domain,Channel domain,Mixed domain以及Self-attention。接下来简单介绍这部分方法。 SE-Net: Squeeze-and-Excitation Networks SE-Net应用比较多,其基本原理是对于每个输出...
  • 用matlab实现注意力机制模块
  • 文章目录主要工作methodchannel attention modulespatial attention module如何结合spatial ...提出了一种具有注意力机制的前馈卷积神经网络——Convolutional Block Attention Module(CBAM) method 注意力机...
  • 我们提出了卷积-块-注意力-模块(CBAM),这是一种用于前馈卷积神经网络的简单而有效的注意力模块。 给定一个中间特征图,我们的模块会沿着两个独立的维度(通道和空间)依次推断注意力图,然后将注意力图与输入特征...
  • 首先是结构:CBAM不仅包含senet的channel注意力机制也包含spatial注意力模块 两个attention模块都是使用sigmoid来缩放到[0,1]之间。 更详细的结构:也就是说channel和spatial的注意力机制都用了两个不同的pool。...
  • 注意力机制BAM和CBAM详细解析(附代码)

    万次阅读 多人点赞 2020-04-26 00:17:41
    论文题目①:BAM: Bottleneck Attention Module 论文题目②:CBAMCBAM: Convolutional Block Attention Module Bottlenet attention Module(BAM...因此,作者提出了BAM注意力机制,仿照人的眼睛聚焦在图像几个重...
  • 注意力机制CBAM代码实现(续篇)

    千次阅读 2020-05-11 22:17:01
    下面这个代码是再通道注意力模块时,将平均和最大池化后得到得描述子分别输入MLP,从代码中也可以看到连个描述子得MLP权重共享。 def cbam_block(input_feature, index, reduction_ratio=8): with tf.variable_...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 884
精华内容 353
关键字:

cbam注意力机制