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

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

### YOLOv5 中 `C3CBAM` 属性错误分析 在 YOLOv5 的模型定义文件中,如果遇到 `AttributeError: module 'models.common' has no attribute 'C3CBAM'` 错误,这通常表明自定义模块未被正确加载到项目环境中。以下是可能的原因以及解决方案: #### 可能原因 1. **缺少自定义模块实现** 如果尝试使用名为 `C3CBAM` 的组件而该组件并未存在于项目的 `models/common.py` 文件中,则会触发此错误。 2. **路径配置不正确** 自定义模块所在的目录未能正确加入 Python 的搜索路径,导致无法识别新引入的类或函数。 3. **拼写错误** 类名可能存在大小写或其他字符上的输入差异,例如实际名称可能是 `c3cbam` 或其他形式。 --- ### 解决方法 #### 方法一:确认并添加缺失的模块 检查 `models/common.py` 是否已包含 `C3CBAM` 定义。如果没有,请手动将其添加至该文件中。以下是一个典型的 CBAM 实现示例[^1]: ```python import torch.nn as nn 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 // ratio, 1, bias=False) self.relu1 = nn.ReLU() self.fc2 = nn.Conv2d(in_planes // ratio, 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) 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() 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.sigmoid(x) class C3CBAM(nn.Module): def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): super(C3CBAM, self).__init__() c_ = int(c2 * e) # hidden channels self.cv1 = Conv(c1, c_, 1, 1) self.cv2 = Conv(c1, c_, 1, 1) self.cv3 = Conv(2 * c_, c2, 1) # optional act=FReLU(c2) self.m = nn.Sequential(*[Bottleneck(c_, c_, shortcut, g, e=1.0) for _ in range(n)]) # Add CBAM components here self.ca = ChannelAttention(c_) self.sa = SpatialAttention() def forward(self, x): y1 = self.m(self.cv1(x)) y2 = self.cv2(x) fused_y = torch.cat((self.ca(y1) * y1, y2), dim=1) output = self.cv3(fused_y) return self.sa(output) * output ``` 上述代码实现了基于通道注意力和空间注意力机制的 `C3CBAM` 模块,并确保其可以无缝集成到现有的 YOLOv5 架构中。 --- #### 方法二:更新环境变量 如果已经存在对应的模块但仍然报错,需验证当前运行脚本的工作目录是否能够访问到 `models/common.py` 所处位置。可以通过以下方式调整路径设置: ```python import sys sys.path.append('D:/yolov/yolov5-master') # 替换为实际路径 from models.common import * ``` 通过显式指定模块所在路径,可有效避免因路径问题引发的异常行为。 --- #### 方法三:重新安装依赖项 有时第三方库版本冲突也可能引起此类问题。建议按照官方文档中的说明重置虚拟环境并重新安装所需依赖包[^2]: ```bash pip install -r requirements.txt ``` 完成后再次执行训练命令测试效果: ```bash python train.py --data coco.yaml --epochs 300 --weights '' --cfg yolov5n.yaml --batch-size 128 ``` --- ### 验证流程 完成以上操作后,重启 IDE 并重新导入相关模块以检验修复情况。若仍存在问题,请进一步排查是否存在语法错误或者与其他部分逻辑交互产生的干扰因素。 ---
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

kay_545

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

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

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

打赏作者

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

抵扣说明:

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

余额充值