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

news2024/12/24 2:08:23

962f7cb1b48f44e29d9beb1d499d0530.gif【YOLOv5改进系列】前期回顾:

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

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

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

 


目录

 🚀一、CA注意力机制原理

1.1 SE和CBAM方法的不足

1.2 Coordinate Attention Block

1.2.1 Coordinate Information Embedding:Coordinate信息嵌入

1.2.2 Coordinate Attention Generation :Coordinate Attention生成

1.3 CA的优势

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

2.1 添加顺序 

2.2 具体添加步骤 

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

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

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

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

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

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

第①步:在common.py中添加CABottleneck和C3_CA模块

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

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

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

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

🌟本人YOLOv5系列导航

 🚀一、CA注意力机制原理

论文题目:《Coordinate Attention for Efficient Mobile Network Design》

论文地址:https://arxiv.org/abs/2103.02907

代码实现: https://github.com/Andrew- Qibin/CoordAttention 

1.1 SE和CBAM方法的不足

  • SE(Squeeze-and-Excitation):SE注意力机制在编码过程中只考虑编码通道间信息而忽略了位置信息的重要性
  • CBAM(CBAM: Convolutional Block Attention Module):使用卷积计算空间注意力来利用位置信息,但卷积只能捕获局部关系,而无法捕捉的长距离依赖关系。

1.2 Coordinate Attention Block

Coordinate Attention通过精确的位置信息对通道关系和长期依赖性进行编码,具体操作分为 Coordinate信息嵌入 和 Coordinate Attention生成 2个步骤。


1.2.1 Coordinate Information Embedding:Coordinate信息嵌入

CxHxW 形状的输入特征图逐通道进行平均池化,使用(H,1)(1,W)的池化核分别按XY轴方向进行池化,产生 CxHx1 Cx1xW 形状的特征图。

通过这种方式所产生的一对方法感知特征图,可以使 CA 注意力能够在一个通道内捕获长距离的依赖关系,并且还有助于保留精确的位置信息,使网络能够更加准确的定位对象。


1.2.2 Coordinate Attention Generation :Coordinate Attention生成

(1)将上述所提取到的特征图按空间维度进行拼接,拼接成 \frac{C}{r}x1x(W+H) 形状的特征图,其中 r 用于控制块的减小率和SE中的作用相同。

(2)再将特征图经过F1卷积变换函数(1x1卷积)和非线性激活函数产生 f 中间特征图。然后将 f 按空间维度拆分成两个张量 fhfw ,形状分别为\frac{C}{r}xH 和 \frac{C}{r}xW,接着分别进行 FhFw 卷积变换函数(1x1卷积)和 Sigmoid 激活函数,得到 gh 和 gw 坐标注意力

(3)最后将gh gw 与原输入进行相乘,得到与输入相同形状的输出


1.3 CA的优势

  • 不仅考虑了通道信息,还考虑了方向相关的位置信息。
  • 足够的灵活和轻量,能够简单的插入到轻量级网络的核心模块中。 
  • 可以作为预训练模型用于多种任务中,如检测和分割,均有不错的性能提升。

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

2.1 添加顺序 

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

(2)     models/yolo.py       -->  设定网络结构的传参细节,将CA(CoordAtt

)类名加入其中。(当新的自定义模块中存在输入输出维度时,要使用qw调整输出维度)
(3) models/yolov5*.yaml  -->  新建一个文件夹,如yolov5s_CA.yaml,修改现有模型结构配置文件。(当引入新的层时,要修改后续的结构中的from参数)
(4)         train.py                -->  修改‘--cfg’默认参数,训练时指定模型结构配置文件 


2.2 具体添加步骤 

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

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

# 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

 如下图所示:


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

首先找到yolo.py里面parse_model函数的这一行

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


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

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

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

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

在这里我是用第一种:将 [-1,1,CA,[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_CA.yaml 

  然后运行yolo.py 

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


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

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


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

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

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

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

第①步:在common.py中添加CABottleneck和C3_CA模块

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

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

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

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


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

按照上面的步骤创建yolov5s_C3_CA.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_CA, [128]],
   [-1, 1, Conv, [256, 3, 2]],  # 3-P3/8
   [-1, 6, C3_CA, [256]],
   [-1, 1, Conv, [512, 3, 2]],  # 5-P4/16
   [-1, 3, C3_CA, [512]],
   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32
   [-1, 3, C3_CA, [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_CA.yaml,然后运行

这样就OK啦~


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

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

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


PS:今天训练的结果和比昨天CBAM的mAP增长了1.1,说明CA效果还是很不错的~


🌟本人YOLOv5系列导航

962f7cb1b48f44e29d9beb1d499d0530.gif​   🍀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

962f7cb1b48f44e29d9beb1d499d0530.gif​​   🍀YOLOv5入门实践系列:  

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

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

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

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

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


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

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

CSDN: CVPR 2021 | 即插即用! CA:新注意力机制,助力分类/检测/分割涨点!_Amusi(CVer)的博客-CSDN博客

手把手带你YOLOv5 (v6.1)添加注意力机制(二)(在C3模块中加入注意力机制)_迪菲赫尔曼的博客-CSDN博客 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/514869.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】Redis高可用概述1(RDB和AOF的备份恢复)

在web服务器中,高可用是指服务器可以正常访问的时间,衡量的标准是在多长时间内可以提供正常服务 (99.9%、99.99%、99.999% 等等)。 但是在Redis语境中,高可用的含义似乎要宽泛一些,除了保证提供正常服 务(如…

优惠卷秒杀——分布式锁

在集群的模式下,有多个jvm,每个jvm内部有他自己的锁,导致并行执行存在线程安全问题 分布式锁:满足分布式系统或集群模式下多线程可见并且互斥的锁 基于Redis实现分布式锁 基于redis锁的初级版本 public interface ILock {/*** …

第十四届蓝桥杯C++--A组题解(更新中)

本来考场上做完想着这回图一乐,打打暴力混个省奖得了,看完民间题解感觉跟自己估计的差不多,应该挺寄的,没想到出分捡了个省一,喜提弱省省一倒数 这篇博客把自己会的题先放上来,其他的题慢慢补,好…

干翻Mybatis源码系列之第八篇:Mybatis提供的缓存方案细节注意

前言 Mybatis缓存设计成了两层的体系,第一层叫做一级缓存,第二层叫做二级缓存(全局缓存)。我们从这里可以看到Mybatis的缓存方案是有两种处理方式的。 一级缓存(默认开启) 一级缓存默认开启的&#xff0c…

[天翼杯 2021]esay_eval

[天翼杯 2021]esay_eval <?php class A{ #定义一个名为A的类public $code ""; #定义一个公共属性code function __call($method,$args){ #call魔术方法 当调用一个不存在的成员方法的时候触发eval($this->code); #将code的值以php代码执行 }function __w…

c高级day3作业

#!/bin/bash # 脚本名称:myfirstshell echo hello hostname ls -a .. echo $PATH echo $HOME df -h id -g hostname echo goodbye #!/bin/bash a(ls -l /etc | grep "^-" ) #/etc文件中普通文件 b(ls -l /etc | grep "^d" ) #/etc文件中一级目录文件 …

一篇了解智慧网关

智慧网关是指基于互联网技术的智能网关&#xff0c;能够连接不同的物联网设备和传感器&#xff0c;实现数据采集、信息传递、远程控制、通信管理等功能。作为物联网架构中的核心设备之一&#xff0c;智慧网关在智能家居、智慧城市、智能制造、智能交通、智能农业等领域得到了广…

solidworks三维建模竞赛练习题

solidworks三维建模竞赛练习题&#xff1a;3D01‐ 01 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 02 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 03 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 04 solidworks三维建模竞赛练习题&#xff1a;3D01‐ 05 solidw…

windows docker 创建mysql主从 容器创建mysql主从

1. docker命令新建mysql-master&#xff0c;只是简单测试&#xff0c;没有设置映射&#xff0c;只是验证主从连接&#xff0c;需要可自行添加 docker run --restartalways --name mysql-master --privilegedtrue -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD123456 mysql:8.0 2.…

Linux - 第11节 - 网络入门

目录 1.计算机网络背景 1.1.网络发展 1.2.认识 "协议" 2.网络协议初识 2.1.协议分层 2.2.OSI七层模型 2.3.TCP/IP五层&#xff08;或四层&#xff09;模型 3.网络传输基本流程 3.1.同局域网的两台主机通信 3.2.跨网络的两台主机通信 1.计算机网络背景 1.1…

spring事务报错Transaction rolled back because it has been marked as rollback-only

之前经常报"Transaction rolled back because it has been marked as rollback-only"这个异常 字面意思是"事务回滚了&#xff0c;因为它被标记了必须回滚"&#xff0c;最开始完全不懂事务的嵌套&#xff0c;每次出现这个错误都想知道为什么&#xff0c;但…

套接字类型和协议设置

创建套接字 成功返回文件描述符&#xff0c;失败返回-1 int socket (int __domain, int __type, int __protocol) ;__domain&#xff1a;套接字中使用的协议族信息 一般使用PF_INET&#xff08;IPv4互联网协议族&#xff09;&#xff0c;其它协议族不常使用或尚未普及。另外&a…

算法设计与分析:大整数的加减乘除运算

目录 任务描述 相关知识 大整数的思想 大整数加法 大整数减法 大整数与整数的乘法 大整数乘法 大整数与整数的除法 n的阶乘求解思路 编程要求 测试说明 任务描述 本关任务&#xff1a;掌握大整数的基本思想&#xff0c;并运用大整数的基本运算计算出常规整数n的阶乘…

seaweedfs服务启动参数及翻译(seaweed参数、seaweed命令、weed参数、weed命令)(在单个容器同时启动master、volume、filer服务)

文章目录 weed命令翻译weed server命令翻译 weed filer命令 docker容器运行示例&#xff08;docker run命令&#xff09;以下是一个在单个容器启动master、volume、filer服务的示例 weed server 容器debug 版本&#xff1a;3.47从官方镜像docker容器里扒下来的&#xff0c;只扒…

【多线程】单例模式

目录 饿汉模式 懒汉模式-单线程版 懒汉模式-多线程版 懒汉模式-多线程版(改进) 单例是一种设计模式。 啥是设计模式 ? 设计模式好比象棋中的 " 棋谱 ". 红方当头炮 , 黑方马来跳 . 针对红方的一些走法 , 黑方应招的时候有一些固定的套路. 按照套路来走局势…

5.11 C高级作业

编写一个名为myfirstshell.sh的脚本&#xff0c;它包括以下内容。 1、包含一段注释&#xff0c;列出您的姓名、脚本的名称和编写这个脚本的目的 2、和当前用户说“hello 用户名” 3、显示您的机器名 hostname 4、显示上一级目录中的所有文件的列表 5、显示变量PATH和HOME的…

高性能网络 SIG 月度动态:长期投入得到业界认可,新增一位 virtio reviewer

高性能网络 SIG&#xff08;Special Interest Group&#xff09; &#xff1a;在云计算时代&#xff0c;软硬件高速发展&#xff0c;云原生、微服务等新的应用形态兴起&#xff0c;让更多的数据在进程之间流动&#xff0c;而网络则成为了这些数据流的载体&#xff0c;在整个云时…

Hive概述和安装

hive简介 Hive&#xff1a;由Facebook开源用于解决海量结构化日志的数据统计工具。 Hive是基于Hadoop的一个数据仓库工具&#xff0c;将结构化的数据文件映射为一张表&#xff0c;并提供类SQL(HQL)查询功能。 Hive本质&#xff1a;将HQL转化成MapReduce程序 &#xff08;1&am…

无锁队列实现及使用场景

写在前面 在看无锁队列之前&#xff0c;我们先来看看看队列的操作。队列是一种非常重要的数据结构&#xff0c;其特性是先进先出&#xff08;FIFO&#xff09;&#xff0c;符合流水线业务流程。在进程间通信、网络通信间经常采用队列做缓存&#xff0c;缓解数据处理压力。根据…

device_node转换成platform_device

device_node转换成platform_device 文章目录 device_node转换成platform_device转换规则主要核心函数of_default_bus_match_tablearmarm64of_platform_register_reconfig_notifier Linux内核是如何将device_node转换成platform_deviceof_platform_populate函数处理根节点下的子…