YOLOV5改进 | 注意力机制 | 一网打尽 C3ECA,C3CA,C3CBAM 等多种注意力机制(小白可轻松上手)

尽管Ultralytics 推出了最新版本的 YOLOv8 模型。但YOLOv5作为一个anchor base的目标检测的算法,可能比YOLOv8的效果更好。注意力机制是提高模型性能最热门的方法之一,本文给大家带来的教程是多种注意力机制的添加。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。


专栏地址YOLOv5改进+入门——持续更新各种有效涨点方法 

目录

1. 添加C3CA到common.py

 2. 在yolo.py文件中进行注册

3.增加yaml文件

4. 执行程序

5. 其他注意力机制

6. C3CBAM代码实现

7. C3ECA代码实现

8. C3SE代码实现

9.总结

10.完整代码


本文不在讲解原理,相关理论在之前的文章有所有提及,感兴趣的同学可以查看相关文章

下方链接点击即可跳转

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/1ZZEBk1hAL0pUd2Pg_cpELg?pwd=iwns 提取码: iwns 

💡💡💡其中所有内的修改内容经过验证均可以成功执行 💡💡💡

  • 26
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值