YOLOv5改进---添加注意力机制之SE

一、注意力机制

人类视觉注意力

      视觉注意力机制是人类大脑的一种天生的能力。当我们看到一幅图片时,先是快速扫过图片,然后锁定需要重点关注的目标区域。试想,如果每个局部信息都不放过,那么必然耗费很多精力,不利于人类的生存进化。同样地,在深度学习网络中引入类似的机制,可以简化模型,加速计算

       当我们用深度 CNN 模型识别图像时,一般是通过卷积核去提取图像的局部信息,然而,每个局部信息对图像能否被正确识别的影响力是不同的,如何让模型知道图像中不同局部信息的重要性呢?答案就是注意力机制。

作用

  • 1.提高模型的准确性: 注意力机制可以帮助模型更好地关注重要的信息,从而提高模型的准确性。
  • 2.模型解释性更强: 注意力机制可以让模型更好地解释其决策过程,从而提高模型的可解释性。
  • 3.可以处理不定长的序列数据: 注意力机制可以处理不定长的序列数据,比如文本数据、语音数据等。

不足

  • 1.计算量大:注意力机制需要计算每个位置的权重,因此计算量较大,训练时间较长。
  • 2.可能出现过拟合: 如果注意力机制的权重过于复杂,可能会导致过拟合的问题。
  • 3.可能需要更多的数据: 注意力机制需要更多的数据来训练和优化,否则可能会出现欠拟合的问题。

二、常用注意力机制

1.1 SE注意力机制

        SE注意力机制(Squeeze-and-Excitation Networks)在通道维度增加注意力机制,关键操作是squeeze和excitation。

        通过自动学习的方式,使用另外一个新的神经网络,获取到特征图的每个通道的重要程度,然后用这个重要程度去给每个特征赋予一个权重值,从而让神经网络重点关注某些特征通道。提升对当前任务有用的特征图的通道,并抑制对当前任务用处不大的特征通道。

如下图所示,在输入SE注意力机制之前(左侧图C),特征图的每个通道的重要程度都是一样的,通过SENet之后(右侧彩图C),不同颜色代表不同的权重,使每个特征通道的重要性变得不一样了,使神经网络重点关注某些权重值大的通道。

SE注意力机制的实现步骤如下:

(1)Squeeze:通过全局平均池化,将每个通道的二维特征(H*W)压缩为1个实数,将特征图从 [h, w, c] ==> [1,1,c]

(2)excitation:给每个特征通道生成一个权重值,论文中通过两个全连接层构建通道间的相关性,输出的权重值数目和输入特征图的通道数相同。[1,1,c] ==> [1,1,c]

(3)Scale:将前面得到的归一化权重加权到每个通道的特征上。论文中使用的是乘法,逐通道乘以权重系数。[h,w,c]*[1,1,c] ==> [h,w,c]

小节:
(1)SENet的核心思想是通过全连接网络根据loss损失来自动学习特征权重,而不是直接根据特征通道的数值分配来判断,使有效的特征通道的权重大。当然SE注意力机制不可避免的增加了一些参数和计算量,但性价比还是挺高的。

(2)论文认为excitation操作中使用两个全连接层相比直接使用一个全连接层,它的好处在于,具有更多的非线性,可以更好地拟合通道间的复杂关联。                   
原文链接:https://blog.csdn.net/dgvv4/article/details/125112972

1.2 YOLOv5添加SE注意力机制方法

      在介绍方法前我们先来回顾一下YOLOv5内一会儿要修改的文件:

models/common.py:这个文件存放着YOLOv5网络搭建常见的通用模块。如果我们需要修改某一模块,那么就需要修改这个文件中对应模块的定义。

models/yolo.py:这是YOLO的特定模块,和网络构建有关。这个文件主要由三个部分:parse_model函数、Detect类和Model类组成。其中parse_model方法是对网络结构进行整体搭建,同时起到注册common.py中各类模块的作用。

models/yolov5s.yaml(以s结构为例):网络的配置文件,models/yolo.py依据这个配置文件中的信息对整体网络进行构建。YOLOv5s网络是YOLOv5系列中深度最小,特征图的宽度最小的网络。其他的三种都是在此基础上不断加深,不断加宽。      

1.3 添加顺序

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

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

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

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

  1.4 具体步骤

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

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

class SE(nn.Module):
    def __init__(self, c1, c2, r=16):
        super(SE, self).__init__()
        self.avgpool = nn.AdaptiveAvgPool2d(1)
        self.l1 = nn.Linear(c1, c1 // r, bias=False)
        self.relu = nn.ReLU(inplace=True)
        self.l2 = nn.Linear(c1 // r, c1, bias=False)
        self.sig = nn.Sigmoid()
    def forward(self, x):
        print(x.size())
        b, c, _, _ = x.size()
        y = self.avgpool(x).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)
        return x * y.expand_as(x)

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

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

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

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

接着修改 yolov5s_SE.yaml ,将 SE加到我们想添加的位置。

注意力机制可以添加在backbone,Neck,Head等部分, 常见的有两种:一是在主干的 SPPF 前添加一层;二是将backbone中的C3全部替换。不同的位置效果可能不同,需要我们用数据集反复测试,“调参大师”就是这样诞生的~

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

image

1.5 C3模块中添加SE

代码:

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)))

添加方法与上面一样。


原文链接:YOLOv5改进系列(1)——添加SE注意力机制-阿里云开发者社区 (aliyun.com)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值