手把手带你YOLOv5/v7 添加注意力机制(并附上30多种顶会Attention原理图)2023/2/11更新
Posted 迪菲赫尔曼
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手带你YOLOv5/v7 添加注意力机制(并附上30多种顶会Attention原理图)2023/2/11更新相关的知识,希望对你有一定的参考价值。
💡本方法同样适配YOLOv7算法💡
如果感觉有帮助的话请点赞支持下👍📖🌟 ,您的点赞是对我最大的鼓励~
大家好,我是迪菲赫尔曼😁,我最近将本人硕士阶段所有学习的计算机视觉基础知识进行了一个系统性的整理,编写了《目标检测蓝皮书🍀》,共计 10 10 10篇内容,涵盖从基础知识到论文改进的整个时间线,包含第 1 1 1篇机器学习基础、第 2 2 2篇深度学习基础、第 3 3 3篇卷积神经网络、第 4 4 4篇经典热门网络结构、第 5 5 5篇目标检测基础、第 6 6 6篇网络搭建及训练、第 7 7 7篇模型优化方法及思路、第 8 8 8篇模型超参数调整策略、第 9 9 9篇模型改进技巧、第 10 10 10篇模型部署基础等,详细的目录大家可以看我的这篇文章:《目标检测蓝皮书》目录,专栏地址:点击跳转,欢迎大家订阅~
我最近在哔哩哔哩上更新了视频版的讲解,有需要的同学可以关注一下~ 我的哔哩哔哩主页
文章目录
- 注意力机制介绍
- 注意力机制的分类
- 1. SE 注意力模块
- 2. CBAM 注意力模块
- 3. ECA 注意力模块
- 4. CA 注意力模块
- 5. 添加方式💡
- 6. SOCA 注意力模块
- 7. SimAM 注意力模块
- 8. S2-MLPv2 注意力模块
- 9. NAMAttention 注意力模块
- 10. Criss-CrossAttention 注意力模块
- 11. GAMAttention 注意力模块
- 12. Selective Kernel Attention 注意力模块
- 13. ShuffleAttention 注意力模块
- 14. A2-Net 注意力模块🍀
- 15. DANPositional 注意力模块
- 16. DANChannel 注意力模块
- 17. RESNest 注意力模块
- 18. Harmonious 注意力模块
- 19. SpatialAttention 注意力模块
- 19. RANet 注意力模块
- 20. Co-excite 注意力模块
- 21. EfficientAttention 注意力模块
- 22. X-Linear 注意力模块
- 23. SlotAttention 注意力模块
- 24. Axial 注意力模块
- 25. RFA 注意力模块
- 26. Attention-BasedDropout 注意力模块
- 27. ReverseAttention 注意力模块
- 28. CrossAttention 注意力模块
- 29. Perceiver 注意力模块
- 30. Criss-CrossAttention 注意力模块
- 31. BoostedAttention 注意力模块
- 32. Prophet 注意力模块
- 33. S3TA 注意力模块
- 34. Self-CriticAttention 注意力模块
- 35. BayesianAttentionBeliefNetworks 注意力模块
- 36. Expectation-MaximizationAttention 注意力模块
- 37. GaussianAttention 注意力模块
- 本人更多 YOLOv5/v7 实战内容导航🍀🌟🚀
注意力机制介绍
注意力机制(Attention Mechanism)源于对人类视觉的研究。在认知科学中,由于信息处理的瓶颈,人类会选择性地关注所有信息的一部分,同时忽略其他可见的信息。为了合理利用有限的视觉信息处理资源,人类需要选择视觉区域中的特定部分,然后集中关注它。例如,人们在阅读时,通常只有少量要被读取的词会被关注和处理。综上,注意力机制主要有两个方面:决定需要关注输入的哪部分;分配有限的信息处理资源给重要的部分。这几年有关attention的论文与日俱增,下图就显示了在包括CVPR、ICCV、ECCV、NeurIPS、ICML和ICLR在内的顶级会议中,与attention相关的论文数量的增加量。下面我将会分享Yolov5 v6.1如何添加注意力机制;并分享到2022年4月为止,30个顶会上提出的优秀的attention.
注意力机制的分类
1. SE 注意力模块
论文名称:《Squeeze-and-Excitation Networks》
论文地址:https://arxiv.org/pdf/1709.01507.pdf
代码地址: https://github.com/hujie-frank/SENet
1.1 原理
SEnet(Squeeze-and-Excitation Network)
考虑了特征通道之间的关系,在特征通道上加入了注意力机制。
SEnet
通过学习的方式自动获取每个特征通道的重要程度,并且利用得到的重要程度来提升特征并抑制对当前任务不重要的特征。SEnet
通过Squeeze
模块和Exciation
模块实现所述功能。
如图所示,首先作者通过squeeze
操作,对空间维度进行压缩,直白的说就是对每个特征图做全局池化,平均成一个实数值。该实数从某种程度上来说具有全局感受野。作者提到该操作能够使得靠近数据输入的特征也可以具有全局感受野,这一点在很多的任务中是非常有用的。紧接着就是excitaton
操作,由于经过squeeze
操作后,网络输出了
1
∗
1
∗
C
1*1*C
1∗1∗C 大小的特征图,作者利用权重
w
w
w 来学习
C
C
C 个通道直接的相关性。在实际应用时有的框架使用全连接,有的框架使用
1
∗
1
1*1
1∗1 的卷积实现。该过程中作者先对
C
C
C 个通道降维再扩展回
C
C
C 通道。好处就是一方面降低了网络计算量,一方面增加了网络的非线性能力。最后一个操作时将exciation
的输出看作是经过特征选择后的每个通道的重要性,通过乘法加权的方式乘到先前的特征上,从事实现提升重要特征,抑制不重要特征这个功能。
1.2 代码
# SE
class SE(nn.Module):
def __init__(self, c1, c2, ratio=16):
super(SE, self).__init__()
#c*1*1
self.avgpool = nn.AdaptiveAvgPool2d(1)
self.l1 = nn.Linear(c1, c1 // ratio, bias=False)
self.relu = nn.ReLU(inplace=True)
self.l2 = nn.Linear(c1 // ratio, c1, bias=False)
self.sig = nn.Sigmoid()
def forward(self, x):
b, c, _, _ = x.size()
y = self.avgpool(x).view(b, c)
y = self.l1(y)
y = self.relu(y)
y = self.l2(y)
y = self.sig(y)
y = y.view(b, c, 1, 1)
return x * y.expand_as(x)
这里放上我自己做实验的截图,我就是把SE
层加到了第
9
9
9 层的位置;粉红色线条代表添加了SE
注意力机制。
2. CBAM 注意力模块
论文题目:《CBAM: Convolutional Block Attention Module》
论文地址:https://arxiv.org/pdf/1807.06521.pdf
2.1 原理
CBAM(Convolutional Block Attention Module)
结合了特征通道和特征空间两个维度的注意力机制。
CBAM
通过学习的方式自动获取每个特征通道的重要程度,和SEnet
类似。此外还通过类似的学习方式自动获取每个特征空间的重要程度。并且利用得到的重要程度来提升特征并抑制对当前任务不重要的特征。
CBAM
提取特征通道注意力的方式基本和SEnet
类似,如下Channel Attention
中的代码所示,其在SEnet
的基础上增加了max_pool
的特征提取方式,其余步骤是一样的。将通道注意力提取厚的特征作为空间注意力模块的输入。
CBAM
提取特征空间注意力的方式:经过ChannelAttention
后,最终将经过通道重要性选择后的特征图送入特征空间注意力模块,和通道注意力模块类似,空间注意力是以通道为单位进行最大池化和平均池化,并将两者的结果进行concat
,之后再一个卷积降成
1
∗
w
∗
h
1*w*h
1∗w∗h 的特征图空间权重,再将该权重和输入特征进行点积,从而实现空间注意力机制。
2.2 代码
# CBAM
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.f1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)
self.relu = nn.ReLU()
self.f2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
avg_out = self.f2(self.relu(self.f1(self.avg_pool(x))))
max_out = self.f2(self.relu(self.f1(self.max_pool(x))))
out = self.sigmoid(avg_out + max_out)
return out
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
# (特征图的大小-算子的size+2*padding)/步长+1
self.conv = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
# 1*h*w
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)
#2*h*w
x = self.conv(x)
#1*h*w
return self.sigmoid(x)
class CBAM(nn.Module):
def __init__(self, c1, c2, ratio=16, kernel_size=7): # ch_in, ch_out, number, shortcut, groups, expansion
super(CBAM, self).__init__()
self.channel_attention = ChannelAttention(c1, ratio)
self.spatial_attention = SpatialAttention(kernel_size)
def forward(self, x):
out = self.channel_attention(x) * x
# c*h*w
# c*h*w * 1*h*w
out = self.spatial_attention(out) * out
return out
3. ECA 注意力模块
论文名称:《ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks》
论文地址:https://arxiv.org/abs/1910.03151
代码地址:https://github.com/BangguWu/ECANet
3.1 原理
先前的方法大多致力于开发更复杂的注意力模块,以实现更好的性能,这不可避免地增加了模型的复杂性。为了克服性能和复杂性之间的矛盾,作者提出了一种有效的通道关注(ECA
)模块,该模块只增加了少量的参数,却能获得明显的性能增益。
3.2 代码
class ECA(nn.Module):
"""Constructs a ECA module.
Args:
channel: Number of channels of the input feature map
k_size: Adaptive selection of kernel size
"""
def __init__(self, c1,c2, k_size=3):
super(ECA, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.conv = nn.Conv1d(1, 1, kernel_size=k_size, padding=(k_size - 1) // 2, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
# feature descriptor on the global spatial information
y = self.avg_pool(x)
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
# Multi-scale information fusion
y = self.sigmoid(y)
return x * y.expand_as(x)
4. CA 注意力模块
论文名称:《Coordinate Attention for Efficient Mobile Network Design》
论文地址:https://arxiv.org/abs/2103.02907
4.1 原理
先前的轻量级网络的注意力机制大都采用SE
模块,仅考虑了通道间的信息,忽略了位置信息。尽管后来的BAM
和CBAM
尝试在降低通道数后通过卷积来提取位置注意力信息,但卷积只能提取局部关系,缺乏长距离关系提取的能力。为此,论文提出了新的高效注意力机制coordinate attention(CA)
,能够将横向和纵向的位置信息编码到channel attention
中,使得移动网络能够关注大范围的位置信息又不会带来过多的计算量。
coordinate attention
的优势主要有以下几点:
- 不仅获取了通道间信息,还考虑了方向相关的位置信息,有助于模型更好地定位和识别目标;
- 足够灵活和轻量,能够简单地插入移动网络的核心结构中;
- 可以作为预训练模型用于多种任务中,如检测和分割,均有不错的性能提升。
4.2 代码
# CA
class h_sigmoid(nn.Module):
def __init__(self, inplace=True):
super(h_sigmoid, self).__init__()
self.relu = nn.ReLU6(inplace=inplace)
def forward(self, x):
return self.relu(x + 3) / 6
class h_swish(nn.Module):
def __init__(self, inplace=True):
super(h_swish, self).__init__()
self.sigmoid = h_sigmoid(inplace=inplace)
def forward(self, x):
return x * self.sigmoid(x)
class CoordAtt(nn.Module):
def __init__(self, inp, oup, reduction=32):
super(CoordAtt, self).__init__()
self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
self.pool_w = nn.AdaptiveAvgPool2d((1, None))
mip = max(8, inp // reduction)
self.conv1 = nn.Conv2d(inp, mip, kernel_size=1, stride=1, padding=0)
self.bn1 = nn.BatchNorm2d(mip)
self.act = h_swish()
self.conv_h = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)
self.conv_w = nn.Conv2d(mip, oup, kernel_size=1, stride=1, padding=0)
def forward(self, x):
identity = x
n, c, h, w = x.size()
#c*1*W
x_h = self.pool_h(x)
#c*H*1
#C*1*h
x_w = self.pool_w(x).permute(0, 1, 3, 2)
y = torch.cat([x_h, x_w], dim=2)
#C*1*(h+w)
y = self.conv1(y)
y = self.bn1(y)
y = self.act(y)
x_h, x_w = torch.split(y, [h, w], dim=2)
x_w = x_w.permute(0, 1, 3, 2)
a_h = self.conv_h(x_h).sigmoid()
a_w = self.conv_w(x_w).sigmoid()
out = identity * a_w * a_h
return out
5. 添加方式💡
大致的修改方式如下:
在
Y
O
L
O
v
5
YOLOv5
YOLOv5 或
Y
O
L
O
v
7
YOLOv7
YOLOv7 中添加注意力机制可分为如下
5
5
5 步,以在 yolov5s
中添加 SE
注意力机制为例子:
- 在
yolov5/models
文件夹下新建一个yolov5s_SE.yaml
; - 将本文上面提供的
SE
注意力代码添加到common.py
文件末尾; - 将
SE
这个类的名字加入到yolov5/models/yolo.py
中; - 修改
yolov5s_SE.yaml
,将SE
注意力加到你想添加的位置; - 修改
train.py
文件的'--cfg'
默认参数,随后就可以开始训练了。
详细的修改方式如下:
- 第
1
1
1 步:在
yolov5/models
文件夹下新建一个yolov5_SE.yaml
,将yolov5s.yaml
文件内容拷贝粘贴到我们新建的yolov5s_SE.yaml
文件中等待第 4 4 4 步使用; - 第
2
2
2 步:将本文上面提供的
SE
注意力代码添加到yolov5/models/common.py
文件末尾;
class SE(nn.Module):
def __init__(self, c1, c2, ratio=16):
super(SE, self).__init__()
#c*1*1
self.avgpool = nn.AdaptiveAvgPool2d(1)
self.l1 = nn.Linear(c1, c1 // ratio, bias=False)
self.relu = nn.ReLU(inplace=True)
self.l2 = nn.Linear(c1 // ratio, c1, bias=False)
self.sig = nn.Sigmoid()
def forward(self, x):
b, c, _, _ = x.size()
y = self.avgpool(x).view(b, c)
y = self.l1(y)
y = self.relu(y)
y =以上是关于手把手带你YOLOv5/v7 添加注意力机制(并附上30多种顶会Attention原理图)2023/2/11更新的主要内容,如果未能解决你的问题,请参考以下文章
手把手带你Yolov5 (v6.1)添加注意力机制(并附上30多种顶会Attention原理图)
YOLOv5/v7/v8改进最新主干系列BiFormer:顶会CVPR2023即插即用,小目标检测涨点必备,首发原创改进,基于动态查询感知的稀疏注意力机制构建高效金字塔网络架构,打造高精度检测器
Carson带你学Android:手把手带你深入分析事件分发机制!
Android性能优化:手把手带你全面了解 内存泄露 & 解决方案
YOLOv5/v7 进阶实战 | 目录 | 安卓 | PyQt5| 剪枝✂️ | 蒸馏⚗️ | Flask Web | 改进教程