尽管Ultralytics 推出了最新版本的 YOLOv8 模型。但YOLOv5作为一个anchor base的目标检测的算法,可能比YOLOv8的效果更好。注意力机制是提高模型性能最热门的方法之一,本文给大家带来的教程是多种注意力机制的添加。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
目录
本文不在讲解原理,相关理论在之前的文章有所有提及,感兴趣的同学可以查看相关文章
下方链接点击即可跳转
YOLOv5改进 | 注意力机制 | 理解全局和局部信息的SE注意力机制-CSDN博客
YOLOv5改进 | 注意力机制 | 用于移动端的高效坐标CA注意力机制-CSDN博客
CBAM: YOLOv5改进 | 注意力机制 | 通道和空间的双重作用的CBAM注意力机制-CSDN博客
ECA: YOLOv5改进 | 注意力机制 | 添加高效的通道注意力机制——ECA-CSDN博客
1. 添加C3CA到common.py
关键步骤一:将下面代码复制到. \models\common.py文件中
class CABottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5,ratio=32): # ch_in, ch_out, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
# self.ca=CoordAtt(c1,c2,ratio)
self.pool_h = nn.AdaptiveAvgPool2d((None, 1))
self.pool_w = nn.AdaptiveAvgPool2d((1, None))
mip = max(8, c1 // ratio)
self.conv1 = nn.Conv2d(c1, mip, kernel_size=1, stride=1, padding=0)
self.bn1 = nn.BatchNorm2d(mip)
self.act = h_swish()
self.conv_h = nn.Conv2d(mip, c2, kernel_size=1, stride=1, padding=0)
self.conv_w = nn.Conv2d(mip, c2, kernel_size=1, stride=1, padding=0)
def forward(self, x):
x1=self.cv2(self.cv1(x))
n, c, h, w = x.size()
#c*1*W
x_h = self.pool_h(x1)
#c*H*1
#C*1*h
x_w = self.pool_w(x1).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 = x1 * a_w * a_h
# out=self.ca(x1)*x1
return x + out if self.add else out
class C3CA(C3):
# C3 module with CABottleneck()
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*(CABottleneck(c_, c_,shortcut) for _ in range(n)))
2. 在yolo.py文件中进行注册
关键步骤二:在yolo.py文件中大约260左右进行注册模块
3.增加yaml文件
关键步骤三:在.\models文件夹下新增yolov5_c3ca.yaml文件,并复制下面内容
# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Parameters
nc: 80 # number of classes
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
[[-1, 1, Conv, [64, 6, 2, 2]], # 0-P1/2
[-1, 1, Conv, [128, 3, 2]], # 1-P2/4
[-1, 3, C3CA, [128]],
[-1, 1, Conv, [256, 3, 2]], # 3-P3/8
[-1, 6, C3CA, [256]],
[-1, 1, Conv, [512, 3, 2]], # 5-P4/16
[-1, 9, C3CA, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
[-1, 3, C3CA, [1024]],
[-1, 1, SPPF, [1024, 5]], # 9
]
# YOLOv5 v6.0 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 6], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3, [512, False]], # 13
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 4], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3, [256, False]], # 17 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 14], 1, Concat, [1]], # cat head P4
[-1, 3, C3, [512, False]], # 20 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 10], 1, Concat, [1]], # cat head P5
[-1, 3, C3, [1024, False]], # 23 (P5/32-large)
[[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
我这里面修改的内容是将backbone中的C3模块替换为C3CA模块,这些改进不是单独的替换某个模块或者是添加某些层,只是将C3和CA模块融合到了一起
C3模块是YOLOv5中的一个主要构建模块,它是一个特征提取器。它由卷积层组成,其中包括卷积、批归一化和激活函数。C3模块中的“C3”表示“Cross Stage Partial Connection”,即跨阶段部分连接。这意味着C3模块在不同阶段之间具有部分连接,以促进信息的流动和特征的共享。C3模块的设计旨在通过有效地组合不同尺度的特征图来提高检测性能,从而使模型能够更好地适应各种尺度的目标。
C3CA模块是YOLOv5中引入的改进版本,它在C3模块的基础上添加了注意力机制。 “CA”代表“Channel Attention”,即通道注意力。这个注意力机制有助于模型更加关注重要的特征通道,从而提高了模型的性能和鲁棒性。通过引入注意力机制,C3CA模块可以动态地学习特征图中不同通道的重要性,以更好地捕获目标的关键特征,并进一步提高检测精度。
总的来说,C3模块和C3CA模块都是YOLOv5中用于特征提取和检测的重要模块,而C3CA模块相比于C3模块在设计上引入了通道注意力机制,以提高模型的性能和效果。
温馨提示:因为本文只是对yolov5s基础上添加CBAM模块,如果要对yolov5n/l/m/x进行添加则只需要修改对应的depth_multiple 和 width_multiple。
yolov5n/l/m/x对应的depth_multiple 和 width_multiple如下:
# YOLOv5n
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.25 # layer channel multiple
# YOLOv5l
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # layer channel multiple
# YOLOv5m
depth_multiple: 0.67 # model depth multiple
width_multiple: 0.75 # layer channel multiple
# YOLOv5x
depth_multiple: 1.33 # model depth multiple
width_multiple: 1.25 # layer channel multiple
4. 执行程序
在train.py中,将cfg的参数路径设置为yolov5_c3ca.yaml的路径,如下图所示
建议大家写绝对路径,确保一定能找到
运行程序,如果出现下面的内容则说明添加成功🚀
5. 其他注意力机制
其他的注意力机制我不再单独写了,下面只把代码实现和yaml文件的内容放在这里,其他步骤和修改C3CA一样,只是将模块名称替换即可。当然,如果你还是觉得有困难,我也会在最下面放上我修改后的完整代码,开箱后即可一键运行。
6. C3CBAM代码实现
【yaml文件只需要把上面的yaml文件中的C3CA替换为C3CBAM即可】
class CBAMBottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5,ratio=16,kernel_size=7): # ch_in, ch_out, shortcut, groups, expansion
super(CBAMBottleneck,self).__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
self.channel_attention = ChannelAttention(c2, ratio)
self.spatial_attention = SpatialAttention(kernel_size)
#self.cbam=CBAM(c1,c2,ratio,kernel_size)
def forward(self, x):
x1=self.cv2(self.cv1(x))
out = self.channel_attention(x1) * x1
# print('outchannels:{}'.format(out.shape))
out = self.spatial_attention(out) * out
return x + out if self.add else out
class C3CBAM(C3):
# C3 module with CBAMBottleneck()
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*(CBAMBottleneck(c_, c_,shortcut) for _ in range(n)))
7. C3ECA代码实现
【yaml文件只需要把上面的yaml文件中的C3CA替换为C3CBAM即可】
class ECABottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5,ratio=16,k_size=3): # ch_in, ch_out, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
# self.eca=ECA(c1,c2)
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):
x1=self.cv2(self.cv1(x))
# out=self.eca(x1)*x1
y = self.avg_pool(x1)
y = self.conv(y.squeeze(-1).transpose(-1, -2)).transpose(-1, -2).unsqueeze(-1)
y = self.sigmoid(y)
out=x1 * y.expand_as(x1)
return x + out if self.add else out
class C3ECA(C3):
# C3 module with ECABottleneck()
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*(ECABottleneck(c_, c_,shortcut) for _ in range(n)))
8. C3SE代码实现
【yaml文件只需要把上面的yaml文件中的C3CA替换为C3CBAM即可】
class SEBottleneck(nn.Module):
# Standard bottleneck
def __init__(self, c1, c2, shortcut=True, g=1, e=0.5,ratio=16): # ch_in, ch_out, shortcut, groups, expansion
super().__init__()
c_ = int(c2 * e) # hidden channels
self.cv1 = Conv(c1, c_, 1, 1)
self.cv2 = Conv(c_, c2, 3, 1, g=g)
self.add = shortcut and c1 == c2
# self.se=SE(c1,c2,ratio)
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):
x1=self.cv2(self.cv1(x))
b, c, _, _ = x.size()
y = self.avgpool(x1).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)
out=x1 * y.expand_as(x1)
# out=self.se(x1)*x1
return x + out if self.add else out
class C3SE(C3):
# C3 module with SEBottleneck()
def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5):
super().__init__(c1, c2, n, shortcut, g, e)
c_ = int(c2 * e) # hidden channels
self.m = nn.Sequential(*(SEBottleneck(c_, c_,shortcut) for _ in range(n)))
9.总结
模块 | 描述 |
---|---|
C3CA | YOLOv5 中的特征提取模块,结合了 C3 模块和 CA(Channel Attention)注意力机制。 CA 注意力机制用于调整每个通道的特征图权重,以增强模型对重要特征的关注。 |
C3CBAM | 结合了 C3 模块和 CBAM(Convolutional Block Attention Module)注意力机制。 CBAM 使用通道和空间注意力机制来增强特征提取和检测性能。 通道注意力模块用于调整每个通道的特征图权重,空间注意力模块用于调整不同空间位置的权重。 |
C3ECA | 结合了 C3 模块和 ECA(Efficient Channel Attention)注意力机制。 ECA 使用轻量级的通道注意力机制来增强特征提取能力。 通过对每个通道的特征图应用 ECA 操作,模块可以更有效地捕获重要特征。 |
C3SE | 结合了 C3 模块和 SE(Squeeze-and-Excitation)注意力机制。 SE 使用通道注意力机制动态调整每个通道的重要性权重,以增强模型对重要特征的关注。 通过引入 SE 模块,C3SE 模块可以更好地区分目标和背景,并提高检测精度。 |
10.完整代码
下载后选择你要的yaml文件即可一键执行
链接: 链接: https://pan.baidu.com/s/1-JTd2QwBaRBIQFR2Hq_8qw?pwd=wjiw 提取码: wjiw
💡💡💡其中所有内的修改内容经过验证均可以成功执行 💡💡💡