YOLOv8改进 | 主干篇 | 利用SENetV2改进网络结构 (全网首发改进)

news2024/9/29 7:16:56

一、本文介绍

本文给大家带来的改进机制是SENetV2,其是2023.11月的最新机制(所以大家想要发论文的可以在上面下点功夫),其是一种通过调整卷积网络中的通道关系来提升性能的网络结构。SENet并不是一个独立的网络模型,而是一个可以和现有的任何一个模型相结合的模块(可以看作是一种通道型的注意力机制但是相对于SENetV1来说V2又在全局的角度进行了考虑)。在SENet中,所谓的挤压和激励(Squeeze-and-Excitation)操作是作为一个单元添加到传统的卷积网络结构中,如残差单元中(后面我会把修改好的残差单元给大家大家直接复制粘贴即可使用)亲测大中小三中目标检测上都有一定程度的涨点效果。

推荐指数:⭐⭐⭐⭐⭐

涨点效果:⭐⭐⭐⭐⭐

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备    

训练结果对比图->  

后面我会将这个机制SENetV1和SENetV2添加到多个网络结构中进行融合涨点,同时将其融合到检测头里将模型发布给大家使用。

(我对于SENetV1和SENetV2各提供了两个版本的yaml文件,我分别尝试了其中的两种,这个SENetV2的实验yaml文件可能不如我没实验的yaml文件二大家可以都尝试一下。)

目录

一、本文介绍

 二、SENetV2框架原理

三、SENetV2核心代码

四、手把手教你添加SENetV2模块

 4.1 SENetV2添加步骤

4.1.1 步骤一

4.1.2 步骤二

4.1.3 步骤三

4.2 SENetV2的yaml文件和训练截图

4.2.1 SENetV2的yaml版本一

4.2.2 SENetV2的yaml版本二

4.3 推荐SENetV2可添加的位置 

4.4 SENetV2的训练过程截图 

五、本文总结


 二、SENetV2框架原理

论文地址:官方论文地址点击即可跳转

代码地址:官方代码地址点击即可跳转


SENetV2介绍了一种改进的SENet架构,该架构通过引入一种称为Squeeze aggregated excitation(SaE)的新模块来提升网络的表征能力。这个模块结合了挤压和激励(SENetV1)操作,通过多分支全连接层增强了网络的全局表示学习。在基准数据集上的实验结果证明了SENetV2模型相较于现有模型在分类精度上的显著提升。这一架构尤其强调在仅略微增加模型参数的情况下,如何有效地提高模型的性能。 

挤压和激励模块大家可以看我发的SENetV1文章里面有介绍。

图中展示了三种不同的神经网络模块对比:

a) ResNeXt模块:采用多分支CNN结构,不同分支的特征图通过卷积操作处理后合并(concatenate),再进行额外的卷积操作。

b) SENet模块:标准卷积操作后,利用全局平均池化来挤压特征,然后通过两个尺寸为1x1的全连接层(FC)和Sigmoid激活函数来获取通道权重,最后对卷积特征进行缩放(Scale)。

c) SENetV2模块:结合了ResNeXt和SENet的特点,采用多分支全连接层(FC)来挤压和激励操作,最后进行特征缩放。

其中SENetV2的设计旨在通过多分支结构进一步提升特征表达的精细度和全局信息的整合能力。

前面我们提到了SaE,就是SENetV2相对于SENetV1的主要改进机制,下面的图片介绍了其内部工作原理。

SENet V2中所提出的SaE(Squeeze-and-Excitation)模块的内部工作机制。挤压输出后,被输入到多分支的全连接(FC)层,然后进行激励过程。分割的输入在最后被传递以恢复其原始形状。这种设计能够让网络更有效地学习到输入数据的不同特征,并且在进行特征转换时考虑到不同通道之间的相互依赖性。 


三、SENetV2核心代码

下面的代码是MSDA的核心代码,我们将其复制导'ultralytics/nn/modules'目录下,在其中创建一个文件,我这里起名为Dilation然后粘贴进去,其余使用方式看章节四。

import torch
import torch.nn as nn
from .conv import Conv
# 定义SE模块
class SELayer(nn.Module):
    def __init__(self, channel, reduction=16):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // reduction, bias=False),
            nn.ReLU(inplace=True),
            nn.Linear(channel // reduction, channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y = self.fc(y).view(b, c, 1, 1)
        return x * y.expand_as(x)

# 定义SaE模块
class SELayerV2(nn.Module):
    def __init__(self, in_channel, reduction=32):
        super(SELayerV2, self).__init__()
        assert in_channel>=reduction and in_channel%reduction==0,'invalid in_channel in SaElayer'
        self.reduction = reduction
        self.cardinality=4
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        #cardinality 1
        self.fc1 = nn.Sequential(
            nn.Linear(in_channel,in_channel//self.reduction, bias=False),
            nn.ReLU(inplace=True)
        )
        # cardinality 2
        self.fc2 = nn.Sequential(
            nn.Linear(in_channel, in_channel // self.reduction, bias=False),
            nn.ReLU(inplace=True)
        )
        # cardinality 3
        self.fc3 = nn.Sequential(
            nn.Linear(in_channel, in_channel // self.reduction, bias=False),
            nn.ReLU(inplace=True)
        )
        # cardinality 4
        self.fc4 = nn.Sequential(
            nn.Linear(in_channel, in_channel // self.reduction, bias=False),
            nn.ReLU(inplace=True)
        )

        self.fc = nn.Sequential(
            nn.Linear(in_channel//self.reduction*self.cardinality, in_channel, bias=False),
            nn.Sigmoid()
        )

    def forward(self, x):
        b, c, _, _ = x.size()
        y = self.avg_pool(x).view(b, c)
        y1 = self.fc1(y)
        y2 = self.fc2(y)
        y3 = self.fc3(y)
        y4 = self.fc4(y)
        y_concate = torch.cat([y1,y2,y3,y4],dim=1)
        y_ex_dim = self.fc(y_concate).view(b,c,1,1)

        return x * y_ex_dim.expand_as(x)



class Bottleneck(nn.Module):
    """Standard bottleneck."""

    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):
        """Initializes a bottleneck module with given input/output channels, shortcut option, group, kernels, and
        expansion.
        """
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = Conv(c_, c2, k[1], 1, g=g)
        self.SEV2 = SELayerV2(c2)
        self.add = shortcut and c1 == c2

    def forward(self, x):
        """'forward()' applies the YOLO FPN to input data."""
        return x + self.SEV2(self.cv2(self.cv1(x))) if self.add else self.SEV2(self.cv2(self.cv1(x)))


class C2f_SENetV2(nn.Module):
    """Faster Implementation of CSP Bottleneck with 2 convolutions."""

    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):
        """Initialize CSP bottleneck layer with two convolutions with arguments ch_in, ch_out, number, shortcut, groups,
        expansion.
        """
        super().__init__()
        self.c = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, 2 * self.c, 1, 1)
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.ModuleList(Bottleneck(self.c, self.c, shortcut, g, k=((3, 3), (3, 3)), e=1.0) for _ in range(n))

    def forward(self, x):
        """Forward pass through C2f layer."""
        y = list(self.cv1(x).chunk(2, 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

    def forward_split(self, x):
        """Forward pass using split() instead of chunk()."""
        y = list(self.cv1(x).split((self.c, self.c), 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))


# import ipdb
#
# se_v2 = SaELayer(64)
# # 示例输入
# input = torch.randn(3, 64, 224, 224)
# output = se_v2(input)
#
# print(output.shape)#torch.Size([3, 64, 224, 224])


四、手把手教你添加SENetV2模块

 4.1 SENetV2添加步骤

4.1.1 步骤一

首先我们找到如下的目录'ultralytics/nn/modules',然后在这个目录下创建一个py文件,名字为你也可以根据你自己的习惯起即可,然后将核心代码复制进去。

4.1.2 步骤二

之后我们找到'ultralytics/nn/tasks.py'文件,在其中注册我们的模块。

首先我们需要在文件的开头导入我们的模块,如下图所示->

4.1.3 步骤三

我们找到parse_model这个方法,可以用搜索也可以自己手动找,大概在六百多行吧。 我们找到如下的地方,然后将模块按照我的方法添加进去即可,模仿我添加即可,其中另外的模块,你没有删除即可,添加红框的内容即可。

到此我们就注册成功了,可以修改yaml文件使用我们添加的模块了。


4.2 SENetV2的yaml文件和训练截图

下面推荐几个版本的yaml文件给大家,大家可以复制进行训练,但是组合用很多具体那种最有效果都不一定,针对不同的数据集效果也不一样,我不可每一种都做实验,所以我下面推荐了几种我自己认为可能有效果的配合方式,你也可以自己进行组合。


4.2.1 SENetV2的yaml版本一

这个是我尝试的版本,和上一篇SENetV1做了个对比反过来尝试一下。

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f_SENetV2, [256]]  # 15 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f_SENetV2, [512]]  # 18 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f_SENetV2, [1024]]  # 21 (P5/32-large)

  - [[11, 14, 17], 1, Detect, [nc]]  # Detect(P3, P4, P5)

4.2.2 SENetV2的yaml版本二

下面的版本我在大中小三个检测层的输出部分添加了SENetV2,大家可以根据自己的需求,减少SENetV2比如你做的小目标检测,那么可以把另外两个去去掉,但是别忘了修改检测通道数,要不然会报错。 

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect

# Parameters
nc: 80  # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov8n.yaml' will call yolov8.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.33, 0.25, 1024]  # YOLOv8n summary: 225 layers,  3157200 parameters,  3157184 gradients,   8.9 GFLOPs
  s: [0.33, 0.50, 1024]  # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients,  28.8 GFLOPs
  m: [0.67, 0.75, 768]   # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients,  79.3 GFLOPs
  l: [1.00, 1.00, 512]   # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
  x: [1.00, 1.25, 512]   # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOP

# YOLOv8.0n backbone
backbone:
  # [from, repeats, module, args]
  - [-1, 1, Conv, [64, 3, 2]]  # 0-P1/2
  - [-1, 1, Conv, [128, 3, 2]]  # 1-P2/4
  - [-1, 3, C2f, [128, True]]
  - [-1, 1, Conv, [256, 3, 2]]  # 3-P3/8
  - [-1, 6, C2f, [256, True]]
  - [-1, 1, Conv, [512, 3, 2]]  # 5-P4/16
  - [-1, 6, C2f, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]]  # 7-P5/32
  - [-1, 3, C2f, [1024, True]]
  - [-1, 1, SPPF, [1024, 5]]  # 9

# YOLOv8.0n head
head:
  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 6], 1, Concat, [1]]  # cat backbone P4
  - [-1, 3, C2f, [512]]  # 12

  - [-1, 1, nn.Upsample, [None, 2, 'nearest']]
  - [[-1, 4], 1, Concat, [1]]  # cat backbone P3
  - [-1, 3, C2f, [256]]  # 15 (P3/8-small)
  - [-1, 1, SELayerV2, []]  # 16

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 12], 1, Concat, [1]]  # cat head P4
  - [-1, 3, C2f, [512]]  # 19 (P4/16-medium)
  - [-1, 1, SELayerV2, []]  # 20

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 9], 1, Concat, [1]]  # cat head P5
  - [-1, 3, C2f, [1024]]  # 23 (P5/32-large)
  - [-1, 1, SELayerV2, []]  # 24

  - [[16, 20, 24], 1, Detect, [nc]]  # Detect(P3, P4, P5)

4.3 推荐SENetV2可添加的位置 

SENetV2是一种即插即用的可替换卷积的模块,其可以添加的位置有很多,添加的位置不同效果也不同,所以我下面推荐几个添加的位,置大家可以进行参考,当然不一定要按照我推荐的地方添加。

  1. 残差连接中:在残差网络的残差连接中加入SENetV2

  2. Neck部分:YOLOv8的Neck部分负责特征融合,这里添加SENetV2可以帮助模型更有效地融合不同层次的特征。

  3. 能添加的位置很多:一篇文章很难全部介绍到,后期我会发文件里面集成上百种的改进机制,然后还有许多融合模块,给大家。


4.4 SENetV2的训练过程截图 

下面是添加了SENetV2的训练截图。

大家可以看下面的运行结果和添加的位置所以不存在我发的代码不全或者运行不了的问题大家有问题也可以在评论区评论我看到都会为大家解答(我知道的)。

​​​​​​


五、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,目前本专栏免费阅读(暂时,大家尽早关注不迷路~),如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

专栏回顾:YOLOv8改进系列专栏——本专栏持续复习各种顶会内容——科研必备

​​​

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

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

相关文章

ubuntuxu双系统安装+git/g++/vim+pytorch+opencv+yolo+sitl相关学习

multirotor The first day ——12.10 1.install vmware-workstation and ubuntu swap sources and 换输入法 2.learn git github关联远程仓库 3.install and use Typora Git codemeaningmkdir test创建目录cd test进入目录git init初始化仓库ls ;ls -ah查看目…

CGAL的三维点集

CGAL提供了几种处理点集的算法,从形状检测到通过标准点集处理工具进行的表面重建。 虽然这些算法不强制使用特定的数据结构,但该软件包提供了一个3D点集结构,使用户更容易处理附加属性,如法向量、颜色、标签,并在其上调…

ES的安装和RestClient的操作

目录 初识elasticsearch 什么是elasticsearch elasticsearch的发展 Lucene的优缺点 elasticsearch的优势 倒排索引 es与mysql的概念对比 文档 索引 概念对比 架构 安装es 安装kibana 安装ik分词器 分词器 安装ik分词器 ik分词器的拓展和停用词典 操作索引库…

【文本处理】正则表达式

一、简介 正则表达式,又称规则表达式,(Regular Expression,在代码中常简写为regex、regexp或RE),是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符&…

工具系列:PyCaret介绍_编写和训练自定义机器学习模型

文章目录 PyCaret安装PyCaret👉 让我们开始吧👉 数据集👉 数据准备PyCaret中的设置函数👉 可用模型👉 模型训练与选择👉 编写和训练自定义模型👉 GPLearn模型👉 NGBoost 模型&#x…

半导体晶圆制造SAP:助力推动新时代科技创新

随着科技的迅猛发展,半导体行业成为了推动各行各业进步的重要力量。而半导体晶圆制造作为半导体产业链的核心环节,其效率和质量的提升对于整个行业的发展起着决定性的作用。在这个高度竞争的行业中,如何提升制造过程的效率、降低成本&#xf…

Bellman_Ford算法总结

知识概览 Bellman_Ford算法适合解决存在负权边的最短路问题,时间复杂度为O(nm)。在存在负权边的最短路问题中,Bellman_Ford算法的效率虽然不如SPFA算法,但是Bellman_Ford算法能解决SPFA算法不能解决的经过不超过k条边的最短路问题。 例题展示…

RPN网络在图像处理中的应用

RPN(Region Proposal Network,区域建议网络)是深度学习中用于目标检测的关键组件之一,它通常与后续的目标检测网络(如Fast R-CNN、Faster R-CNN等)结合使用。RPN的主要作用是生成候选目标区域,从…

OpenGL 绘制Mesh数据(Qt)

文章目录 一、简介二、实现代码三、实现效果一、简介 Mesh数据的结构主要就是点与三角面片,因此本质上仍然是对三角面片进行绘制。这里我们借助VCG这个库实现对Mesh数据的读取,这个库相对简单轻巧,很方便使用。 二、实现代码 由于修改的部分很多,我们逐一进行解释一下: --…

快速入门学习定时任务框架-xxljob

定时任务框架-xxljob 简介 主要用于分布式任务调度,可以将任务调度和执行分布在多个节点上。它提供了一个集中式的管理平台,支持动态添加、修改、删除任务,以及任务的分片执行,确保任务在分布式环境中的高可用性的一个框架 spr…

【刷题篇】动态规划(八)

文章目录 1、最长定差子序列2、 最长的斐波那契子序列的长度3、最长等差数列4、等差数列划分 II - 子序列5、回文子串6、最长回文子串 1、最长定差子序列 给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序…

Python爬虫中文乱码处理实例代码解析

更多Python学习内容:ipengtao.com 大家好,我是彭涛,今天为大家分享 Python爬虫中文乱码处理实例代码解析。全文2800字,阅读大约8分钟 在进行网络数据抓取时,常常会遇到中文乱码的问题,这可能导致数据无法正…

编程规范:长函数的思考

在工作,我们应该都不想看到非常的长函数。对于一个运行5年左右的项目,极有可能出现这种情况。由于长函数的长、if/else嵌套,导致代码的可读性非常差,这对于项目的维护和开发带来了极大的困难。所以我们应该避免写长函数&#xff0…

基于稀疏表示的小波变换多光谱图像融合算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 小波变换融合 PCA融合 基于稀疏表示的小波变换多光谱图像融合算法 性能指标对比 2.算法运行软件版本 matlab2022a 3.部分核心程序 ...........…

Redis相关的那些事(一)

背景 目前工作所负责的工作主要是投放业务,属于读高并发场景,记录一下之前碰到的redis相关的问题。 热点大值Key&缓存击穿问题 问题表现 在某次流量峰值过程中,redis的CPU突然飙升,从监控看起来就是CPU飙升到一定程度&…

微信小程序(uniapp)api讲解

Uniapp是一个基于Vue.js的跨平台开发框架,可以同时开发微信小程序、H5、App等多个平台的应用。下面是Uniapp常用的API讲解: Vue.js的API Uniapp采用了Vue.js框架,因此可以直接使用Vue.js的API。例如:v-show、v-if、v-for、comput…

基于HC-SR04传感器的避障机器人设计与实现

本文介绍了如何设计和实现一个基于HC-SR04超声波传感器的避障机器人。我们将详细讨论硬件和电路连接,并提供完整的Arduino代码。该机器人可以利用超声波传感器检测周围的障碍物,并采取相应的动作进行避障,实现自主导航。 引言: 避…

微服务架构<2>

在电商项目中,我们针对一些核心业务,比较复杂的业务需要做一些设计以及优化的过程首先我们针对于订单的模块拆分了2个子模块1.order-curr实时下单业务 2.order-his 做一些历史的订单归档我们的订单业务 >商品添加至购物车 >购物车结算--> 订单…

sklearn 逻辑回归Demo

逻辑回归案例 假设表示 基于上述情况,要使分类器的输出在[0,1]之间,可以采用假设表示的方法。 设 h θ ( x ) g ( θ T x ) h_θ (x)g(θ^T x) hθ​(x)g(θTx), 其中 g ( z ) 1 ( 1 e − z ) g(z)\frac{1}{(1e^{−z} )} g(z)(1e−z)1​…

Go语言中的`sync`包同步原语

通过sync包掌握Go语言的并发 并发是现代软件开发的基本方面,而Go(也称为Golang)为并发编程提供了一套强大的工具。在Go中用于管理并发的基本包之一是sync包。在本文中,我们将概述sync包,并深入探讨其最关键的同步原语…