当前位置:   article > 正文

注意力模块

注意力模块

 目前主流的注意力机制可以分为以下三种:通道注意力、空间注意力以及自注意力(Self-attention)

  • 通道域旨在显示的建模出不同通道之间的相关性,通过网络学习的方式来自动获取到每个特征通道的重要程度,最后再为每个通道赋予不同的权重系数,从而来强化重要的特征抑制非重要的特征。
  • 空间域旨在提升关键区域的特征表达,本质上是将原始图片中的空间信息通过空间转换模块,变换到另一个空间中并保留关键信息,为每个位置生成权重掩膜(mask)并加权输出,从而增强感兴趣的特定目标区域同时弱化不相关的背景区域。(以CBAM代表)
  • 混合域主要是共同结合了通道域、空间域等注意力的形式来形成一种更加综合的特征注意力方法。

一、ECA 注意力模块
ECA 注意力模块,它是一种通道注意力模块;常常被应用与视觉模型中。支持即插即用,即:它能对输入特征图进行通道特征加强,而且最终ECA模块输出,不改变输入特征图的大小。

背景:ECA-Net认为:SENet中采用的降维操作会对通道注意力的预测产生负面影响;同时获取所有通道的依赖关系是低效的,而且不必要的;
设计:ECA在SE模块的基础上,把SE中使用全连接层FC学习通道注意信息,改为1*1卷积学习通道注意信息;通过 一维卷积 layers.Conv1D 来完成跨通道间的信息交互,卷积核的大小通过一个函数来自适应变化,使得通道数较大的层可以更多地进行跨通道交互。
作用:使用1*1卷积捕获不同通道之间的信息,避免在学习通道注意力信息时,通道维度减缩;降低参数量;(FC具有较大参数量;1*1卷积只有较小的参数量)
模块的结构:

 ECA模型的流程思路如下:

  • 首先输入特征图,它的维度是H*W*C;
  • 对输入特征图进行空间特征压缩;实现:在空间维度,使用全局平均池化GAP,得到1*1*C的特征图;
  • 对压缩后的特征图,进行通道特征学习;实现:通过1*1卷积,学习不同通道之间的重要性,此时输出的维度还是1*1*C;
  • 最后是通道注意力结合,将通道注意力的特征图1*1*C、原始输入特征图H*W*C,进行逐通道乘,最终输出具有通道注意力的特征图。

FC全连接层时,对输入的通道特征图处理,是进行全局学习的;

如果使用1*1卷积,只能学习到局部的通道之间的信息

在做卷积操作时,它的卷积核大小,会影响到感受野;为解决不同输入特征图,提取不同范围的特征时,ECA使用了动态的卷积核,来做1*1卷积,学习不同通道之间的重要性。

  • 动态卷积核是指:卷积核的大小通过一个函数来自适应变化;
  • 在通道数较大的层,使用较大的卷积核,做1*1卷积,使得更多地进行跨通道交互;
  • 在通道数较小的层,使用较小的卷积核,做1*1卷积,使得较少地进行跨通道交互;
     

 卷积和自适应函数,定义如下:

  其中k表示卷积核大小;C表示通道数;| |odd表示k只能取奇数;\gamma和b表示在论文中设置为2和1,用于改变通道数C和卷积核大小和之间的比例。

  1. # --------------------------------------------------------- #
  2. #(2)ECANet 通道注意力机制
  3. # 使用1D卷积代替SE注意力机制中的全连接层
  4. # --------------------------------------------------------- #
  5. import torch
  6. from torch import nn
  7. import math
  8. from torchstat import stat # 查看网络参数
  9. # 定义ECANet的类
  10. class eca_block(nn.Module):
  11. # 初始化, in_channel代表特征图的输入通道数, b和gama代表公式中的两个系数
  12. def __init__(self, in_channel, b=1, gama=2):
  13. # 继承父类初始化
  14. super(eca_block, self).__init__()
  15. # 根据输入通道数自适应调整卷积核大小
  16. kernel_size = int(abs((math.log(in_channel, 2)+b)/gama))
  17. # 如果卷积核大小是奇数,就使用它
  18. if kernel_size % 2:
  19. kernel_size = kernel_size
  20. # 如果卷积核大小是偶数,就把它变成奇数
  21. else:
  22. kernel_size = kernel_size
  23. # 卷积时,为例保证卷积前后的size不变,需要0填充的数量
  24. padding = kernel_size // 2
  25. # 全局平均池化,输出的特征图的宽高=1
  26. self.avg_pool = nn.AdaptiveAvgPool2d(output_size=1)
  27. # 1D卷积,输入和输出通道数都=1,卷积核大小是自适应的
  28. self.conv = nn.Conv1d(in_channels=1, out_channels=1, kernel_size=kernel_size,
  29. bias=False, padding=padding)
  30. # sigmoid激活函数,权值归一化
  31. self.sigmoid = nn.Sigmoid()
  32. # 前向传播
  33. def forward(self, inputs):
  34. # 获得输入图像的shape
  35. b, c, h, w = inputs.shape
  36. # 全局平均池化 [b,c,h,w]==>[b,c,1,1]
  37. x = self.avg_pool(inputs)
  38. # 维度调整,变成序列形式 [b,c,1,1]==>[b,1,c]
  39. x = x.view([b,1,c])
  40. # 1D卷积 [b,1,c]==>[b,1,c]
  41. x = self.conv(x)
  42. # 权值归一化
  43. x = self.sigmoid(x)
  44. # 维度调整 [b,1,c]==>[b,c,1,1]
  45. x = x.view([b,c,1,1])
  46. # 将输入特征图和通道权重相乘[b,c,h,w]*[b,c,1,1]==>[b,c,h,w]
  47. outputs = x * inputs
  48. return outputs

二 、SENet
SE注意力机制(Squeeze-and-Excitation Networks)在通道维度增加注意力机制,关键操作是squeeze和excitation。

通过自动学习的方式,使用另外一个新的神经网络,获取到特征图的每个通道的重要程度,然后用这个重要程度去给每个特征赋予一个权重值,从而让神经网络重点关注某些特征通道。提升对当前任务有用的特征图的通道,并抑制对当前任务用处不大的特征通道。

如下图所示,在输入SE注意力机制之前(左侧图C),特征图的每个通道的重要程度都是一样的,通过SENet之后(右侧彩图C),不同颜色代表不同的权重,使每个特征通道的重要性变得不一样了,使神经网络重点关注某些权重值大的通道。


SE注意力机制的实现步骤如下:

  • (1)Squeeze:通过全局平均池化,将每个通道的二维特征(H*W)压缩为1个实数,将特征图从 [h, w, c] ==> [1,1,c]
  • (2)excitation:给每个特征通道生成一个权重值,论文中通过两个全连接层构建通道间的相关性,输出的权重值数目和输入特征图的通道数相同。[1,1,c] ==> [1,1,c]
  • (3)Scale:将前面得到的归一化权重加权到每个通道的特征上。论文中使用的是乘法,逐通道乘以权重系数。[h,w,c]*[1,1,c] ==> [h,w,c]

 总结:

  1. SENet的核心思想是通过全连接网络根据loss损失来自动学习特征权重,而不是直接根据特征通道的数值分配来判断,使有效的特征通道的权重大。当然SE注意力机制不可避免的增加了一些参数和计算量,但性价比还是挺高的。
  2. 论文认为excitation操作中使用两个全连接层相比直接使用一个全连接层,它的好处在于,具有更多的非线性,可以更好地拟合通道间的复杂关联。
  1. # -------------------------------------------- #
  2. #(1)SE 通道注意力机制
  3. # -------------------------------------------- #
  4. import torch
  5. from torch import nn
  6. from torchstat import stat # 查看网络参数
  7. # 定义SE注意力机制的类
  8. class se_block(nn.Module):
  9. # 初始化, in_channel代表输入特征图的通道数, ratio代表第一个全连接下降通道的倍数
  10. def __init__(self, in_channel, ratio=4):
  11. # 继承父类初始化方法
  12. super(se_block, self).__init__()
  13. # 属性分配
  14. # 全局平均池化,输出的特征图的宽高=1
  15. self.avg_pool = nn.AdaptiveAvgPool2d(output_size=1)
  16. # 第一个全连接层将特征图的通道数下降4
  17. self.fc1 = nn.Linear(in_features=in_channel, out_features=in_channel//ratio, bias=False)
  18. # relu激活
  19. self.relu = nn.ReLU()
  20. # 第二个全连接层恢复通道数
  21. self.fc2 = nn.Linear(in_features=in_channel//ratio, out_features=in_channel, bias=False)
  22. # sigmoid激活函数,将权值归一化到0-1
  23. self.sigmoid = nn.Sigmoid()
  24. # 前向传播
  25. def forward(self, inputs): # inputs 代表输入特征图
  26. # 获取输入特征图的shape
  27. b, c, h, w = inputs.shape
  28. # 全局平均池化 [b,c,h,w]==>[b,c,1,1]
  29. x = self.avg_pool(inputs)
  30. # 维度调整 [b,c,1,1]==>[b,c]
  31. x = x.view([b,c])
  32. # 第一个全连接下降通道 [b,c]==>[b,c//4]
  33. x = self.fc1(x)
  34. x = self.relu(x)
  35. # 第二个全连接上升通道 [b,c//4]==>[b,c]
  36. x = self.fc2(x)
  37. # 对通道权重归一化处理
  38. x = self.sigmoid(x)
  39. # 调整维度 [b,c]==>[b,c,1,1]
  40. x = x.view([b,c,1,1])
  41. # 将输入特征图和通道权重相乘
  42. outputs = x * inputs
  43. return outputs

 构造输入层,查看一次前向传播的输出结果,打印网络结构

  1. # 构造输入层shape==[4,32,16,16] #4维tensor,各参数含义:[width, height, channels, kernel_nums]
  2. inputs = torch.rand(4,32,16,16)
  3. # 获取输入通道数
  4. in_channel = inputs.shape[1]
  5. # 模型实例化
  6. model = se_block(in_channel=in_channel)
  7. # 前向传播查看输出结果
  8. outputs = model(inputs)
  9. print(outputs.shape) # [4,32,16,16])
  10. print(model) # 查看模型结构
  11. stat(model, input_size=[32,16,16]) # 查看参数,不需要指定batch维度

三.空洞卷积

 普通的卷积:

在这里插入图片描述

 空洞卷积:

在这里插入图片描述

 空洞卷积(Atrous Convolution)是 DeepLab 模型的关键之一,它可以在不改变特征图大小的同时控制感受野,这有利于提取多尺度信息。空洞卷积如下图所示,其中rate(r)控制着感受野的大小,r 越大感受野越大。通常的 CNN 分类网络的 output_stride=32,若希望 DilatedFCN 的 output_stride=16,只需要将最后一个下采样层的 stride 设置为1,并且后面所有卷积层的 r 设置为 2,这样保证感受野没有发生变化。对于 output_stride=8,需要将最后的两个下采样层的 stride 改为 1,并且后面对应的卷积层的 rate 分别设为 2 和 4。另外一点,DeepLabv3 中提到了采用 multi-grid 方法,针对 ResNet 网络,最后的 3 个级联 block 采用不同 rate,若 output_stride=16 且 multi_grid = (1, 2, 4), 那么最后的 3 个 block 的 rate= 2 · (1, 2, 4) = (2, 4, 8)。这比直接采用 (1, 1, 1) 要更有效一些,不过结果相差不是太大。


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/空白诗007/article/detail/757419
推荐阅读
相关标签
  

闽ICP备14008679号