YOLOv5改进系列(4)——添加ECA注意力机制

简介: YOLOv5改进系列(4)——添加ECA注意力机制

【YOLOv5改进系列】前期回顾:

YOLOv5改进系列(0)——重要性能指标与训练结果评价及分析

YOLOv5改进系列(1)——添加SE注意力机制

YOLOv5改进系列(2)——添加CBAM注意力机制

YOLOv5改进系列(3)——添加CA注意力机制



🚀一、ECA注意力机制原理

论文题目:《ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks

原文地址:ECA-Net

代码实现:ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 开源代码GitHub - BangguWu/ECANet: Code for ECA-Net: Efficient Channel Attention for Deep Convolutional Neural NetworksECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks 开源代码

1.1 ECA方法介绍

ECA是通道注意力机制的一种实现形式,是基于SE的扩展。

作者认为SE block的两个FC层之间的降维是不利于channel attention的权重学习的,并且捕获所有通道之间的依存关系是效率不高且是不必要的。权重学习的过程应该直接一一对应。

ECA 注意力机制模块直接在全局平均池化层之后使用1x1卷积层,去除了全连接层。该模块避免了维度缩减,并有效捕获了跨通道交互。并且ECA只涉及少数参数就能达到很好的效果

ECA通过一维卷积 layers.Conv1D来完成跨通道间的信息交互,卷积核的大小通过一个函数来自适应变化,使得通道数较大的层可以更多地进行跨通道交互。

自适应函数为: ,其中


1.2 SE和ECA网络结构的对比

SEblock网络结构 ECA模块网络结构
(1)global avg pooling产生1 ∗ 1 ∗ C 大小的feature maps (1)global avg pooling产生1 ∗ 1 ∗ C 大小的feature maps
(2)两个fc层(中间有维度缩减)来产生每个channel的weight (2)计算得到自适应的kernel_size
(3)应用kernel_size于一维卷积中,得到每个channel的weight

1.3 ECA实现过程

(1)将输入特征图经过全局平均池化,特征图从 [h,w,c] 的矩阵变成 [1,1,c] 的向量

(2)根据特征图的通道数计算得到自适应的一维卷积核大小 kernel_size

(3)将 kernel_size 用于一维卷积中,得到对于特征图的每个通道的权重

(4)将归一化权重原输入特征图逐通道相乘,生成加权后的特征图


🚀二、添加ECA注意力机制方法(单独加)

2.1 添加顺序

(1)models/common.py    --> 加入新增的网络结构

(2)     models/yolo.py       --> 设定网络结构的传参细节,将ECA类名加入其中。(当新的自定义模块中存在输入输出维度时,要使用qw调整输出维度)

(3) models/yolov5*.yaml  -->  新建一个文件夹,如yolov5s_ECA.yaml,修改现有模型结构配置文件。(当引入新的层时,要修改后续的结构中的from参数)

(4)         train.py                --> 修改‘--cfg’默认参数,训练时指定模型结构配置文件


2.2 具体添加步骤

第①步:在common.py中添加ECA模块

将下面的ECA代码复制粘贴到common.py文件的末尾

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)

如下图所示:


第②步:在yolo.py文件里的parse_model函数加入类名

首先找到yolo.pyparse_model函数的这一行

然后把刚才加入的类ECA添加到这个注册表里面


第③步:创建自定义的yaml文件 

首先在models文件夹下复制yolov5s.yaml文件,粘贴并重命名为 yolov5s_ECA.yaml

接着修改  yolov5s_ECA.yaml ,将ECA模块加到我们想添加的位置。

注意力机制可以添加在backbone,Neck,Head等部分,常见的有两种:一是在主干的 SPPF 前添加一层二是将Backbone中的C3全部替换

在这里我是用第一种:将 [-1,1,ECA,[1024]]添加到 SPPF 的上一层,下一节使用第二种。即下图中所示位置:

同样的下面的head也得修改,p4,p5以及最后detect的总层数都得+1

 这里我们要把后面两个Concat的from系数分别由[ − 1 , 14 ][ − 1 , 10 ]改为[ − 1 , 15 ][ − 1 , 11 ]。然后将Detect原始的from系数[ 17 , 20 , 23 ]要改为[ 18 , 21 , 24 ]


第④步:验证是否加入成功

yolo.py 文件里面配置改为我们刚才自定义的yolov5s_ECA.yaml

然后运行yolo.py

找到ECA这一层,就说明我们添加成功啦!

可以看到params参数这里只有3,说明参数量真的很少呀。


第⑤步:修改train.py中 ‘--cfg’默认参数

我们先找到 train.py 文件的parse_opt函数,然后将第二行‘--cfg’default改为'models/yolov5s_ECA.yaml',然后就可以开始训练啦~


🚀三、添加C3_CA注意力机制方法(在C3模块中添加)

上面是单独加注意力层,接下来的方法是在C3模块中加入注意力层。

刚才也提到了,这个策略是将CA注意力机制添加到Bottleneck,替换Backbone中的所有C3模块。

(因为步骤和上面相同,所以接下来只放重要步骤噢~)

第①步:在common.py中添加ECABottleneck和C3_ECA模块

将下面的代码复制粘贴到common.py文件的末尾

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 C3_ECA(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, g, e=1.0) for _ in range(n)))

第②步:在yolo.py文件里的parse_model函数加入类名

yolo.pyparse_model函数中,加入ECABottleneckC3_ECA这两个模块


第③步:创建自定义的yaml文件 

按照上面的步骤创建yolov5s_C3_ECA.yaml文件

替换4个C3模块,如下图所示

代码如下:

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Parameters
nc: 80  # number of classes
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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, C3_ECA, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3_ECA, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 3, C3_ECA, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3_ECA, [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)
  ]

第④步:验证是否加入成功

yolo.py 文件里面配置改为我们刚才自定义的yolov5s_C3_ECA.yaml,然后运行

这样就OK啦~


第⑤步:修改train.py中 ‘--cfg’默认参数

接下来的训练就和上面一样,不再叙述啦~

完结~撒花✿✿ヽ(°▽°)ノ✿


PS:今天训练了一下,我的评价是,ECA不如昨天的CA,mAP降了0.3


🌟本人YOLOv5系列导航

  🍀YOLOv5源码详解系列:  

YOLOv5源码逐行超详细注释与解读(1)——项目目录结构解析

YOLOv5源码逐行超详细注释与解读(2)——推理部分detect.py

YOLOv5源码逐行超详细注释与解读(3)——训练部分train.py

YOLOv5源码逐行超详细注释与解读(4)——验证部分val(test).py

YOLOv5源码逐行超详细注释与解读(5)——配置文件yolov5s.yaml

YOLOv5源码逐行超详细注释与解读(6)——网络结构(1)yolo.py

YOLOv5源码逐行超详细注释与解读(7)——网络结构(2)common.py

  🍀YOLOv5入门实践系列:  

YOLOv5入门实践(1)——手把手带你环境配置搭建

YOLOv5入门实践(2)——手把手教你利用labelimg标注数据集

YOLOv5入门实践(3)——手把手教你划分自己的数据集

YOLOv5入门实践(4)——手把手教你训练自己的数据集

YOLOv5入门实践(5)——从零开始,手把手教你训练自己的目标检测模型(包含pyqt5界面)

本文参考(感谢大佬们):

b站:【YOLOv5 v6.1添加SE,CA,CBAM,ECA注意力机制教学,即插即用】

CSDN: 【深度学习】(1) CNN中的注意力机制(SE、ECA、CBAM)

手把手带你YOLOv5 (v6.1)添加注意力机制(二)(在C3模块中加入注意力机制)_yolov5添加注意力机制_迪菲赫尔曼的博客-CSDN博客手把手带你YOLOv5/v7 添加注意力机制(并附上30多种顶会Attention原理图)2023/2/11更新_yolov5添加注意力机制_迪菲赫尔曼的博客-CSDN博客

相关文章
|
4天前
|
机器学习/深度学习 计算机视觉 网络架构
改进YOLOv8:添加CBAM注意力机制(涨点明显)
改进YOLOv8:添加CBAM注意力机制(涨点明显)
1546 1
|
4天前
|
机器学习/深度学习
YOLOv5改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
YOLOv5改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
174 0
|
4天前
|
机器学习/深度学习 Ruby
YOLOv5改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
YOLOv5改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
140 0
|
4天前
|
机器学习/深度学习
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
YOLOv8改进 | 2023注意力篇 | MLCA混合局部通道注意力(轻量化注意力机制)
139 1
|
4天前
|
机器学习/深度学习 Ruby
YOLOv8改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
YOLOv8改进 | 2023注意力篇 | iRMB倒置残差块注意力机制(轻量化注意力机制)
223 0
|
4天前
|
机器学习/深度学习
YOLOv8改进 | 注意力篇 | ACmix自注意力与卷积混合模型(提高FPS+检测效率)
YOLOv8改进 | 注意力篇 | ACmix自注意力与卷积混合模型(提高FPS+检测效率)
169 0
|
4天前
|
机器学习/深度学习
YOLOv5改进 | DAttention (DAT)注意力机制实现极限涨点
YOLOv5改进 | DAttention (DAT)注意力机制实现极限涨点
171 0
|
4天前
|
机器学习/深度学习 计算机视觉
YOLOv8改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
YOLOv8改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
325 0
|
4天前
|
机器学习/深度学习 自然语言处理 数据处理
Transformer模型中的Attention机制是什么?
Google研究团队为解决机器翻译准确性问题,推出了Transformer模型,核心是Attention机制。Transformer摒弃RNN和CNN,利用Attention处理全局依赖,提高长文本处理效率。模型包含编码器-解码器与自Attention,多头Attention增强信息捕获,位置编码处理顺序信息。虽在翻译质量和速度上有显著提升,但面临泛化能力、长距离依赖处理和计算复杂度等问题,仍有优化空间。
18 0
Transformer模型中的Attention机制是什么?
|
4天前
|
机器学习/深度学习 计算机视觉
YOLOv5改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
YOLOv5改进 | 2023注意力篇 | EMAttention注意力机制(附多个可添加位置)
271 0

相关实验场景

更多