YOLOv5改进 | 主干网络 | 用SimRepCSP作为主干网络提取特征【全网独家 + 降本增效】

💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡

SimRepCSP 类似于 YOLOv7的主干网络,由卷积模块和重参数化卷积(RepConv)模块组合而成,以 Cross Stage Partial(CSP)网络作为模块之间的连接。通过将 SimRepCSP 作为替代主干纳入 YOLOv5,本文介绍了一种简单而有效的替代模块SimRepCSP 。在本文中,给大家带来的教程是在原来的主干网络修改为SimRepCSP 。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。

专栏地址 YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转

目录

1. 原理

2. SimRepCSP的代码实现

2.1 将SimRepCSP添加到YOLOv5中

SimRepCSP 主要流程:

2.2 新增yaml文件

2.3 注册模块

 2.4 执行程序

3. 完整代码分享

4. GFLOPs

5.总结


1. 原理

官方论文Modified YOLO Model for Small Platform Application using SimRepCSP Module with Case Study——点击即可跳转

SimRepCSP 是一种针对 YOLO 模型的改进背骨模块,其设计旨在提高训练效率和模型性能,同时降低成本。以下是 SimRepCSP 的主要原理及其应用:

SimRepCSP 主要原理

  1. 模块组合

    • 卷积模块:SimRepCSP 集成了标准的卷积模块。

    • 重新参数化卷积模块(RepConv):这些是专门设计的卷积层,通过增加模型参数来提高性能,而不会显著增加计算成本。

    • 跨阶段部分网络(CSP):该网络结构连接不同的模块,增强特征传播和网络学习能力。

  2. 结构和效率

    • SimRepCSP 通过组合三个卷积模块、一个 RepConv 模块和一个连接到 CSP 网络的级联模块构建而成。

    • 这些模块排列的目的是最大化特征提取和重用,从而在减少参数数量的情况下提升性能。

    • 每个卷积模块都包含批量归一化和 SiLU 激活函数。

  3. 与 YOLO 的集成

    • SimRepCSP 可以作为替代背骨集成到 YOLOv8 模型中,分别称为 SimRepCSPv1 和 SimRepCSPv2。这种集成旨在提升模型性能指标,相较于原始的 YOLOv8 背骨。

    • SimRepCSP 的架构包括一个焦点层、多层 SimRepCSP 模块和一个 SPPF(快速空间金字塔池化)模块,用于多尺度特征聚合。

  4. 实验结果

    • 在 GlobalWheat2020 数据集上进行的实验表明,带有 SimRepCSP 模块(SimRepCSPv1 和 SimRepCSPv2)的模型在减少训练和应用成本的同时,实现了更高的性能指标。

    • 主要改进包括减少了 FLOPS(每秒浮点运算次数)、GPU 内存使用量和整体模型重量,同时保持或提高了目标检测的准确性。

  5. 目标和优势

    • 降低计算成本:通过减少所需操作次数,SimRepCSP 旨在使模型更加高效。

    • 增强参数性能:通过微调和优化参数来提高模型的准确性和有效性。

    • 降低 GPU 内存成本:最小化内存需求以允许更大的批处理大小和更高效的训练。

    • 减少模型重量:创建一个轻量级模型,便于部署而不影响性能。

总结

SimRepCSP 通过优化网络架构、减少计算和内存成本以及增强特征提取和参数调优,显著提高了 YOLO 模型的效率和性能。

2. SimRepCSP的代码实现

2.1 将SimRepCSP添加到YOLOv5中

关键步骤一: 将下面代码粘贴到/projects/yolov5-6.1/models/common.py文件中

*注:代码过长,请查看完整代码 

class RepConv(nn.Module):
    # Represented convolution
    # https://arxiv.org/abs/2101.03697

    def __init__(self, c1, c2, k=3, s=1, p=None, g=1, act=True, deploy=False):
        super(RepConv, self).__init__()

        self.deploy = deploy
        self.groups = g
        self.in_channels = c1
        self.out_channels = c2

        assert k == 3
        assert autopad(k, p) == 1

        padding_11 = autopad(k, p) - k // 2

        self.act = nn.SiLU() if act is True else (act if isinstance(act, nn.Module) else nn.Identity()) #

        if deploy:
            self.rbr_reparam = nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=True)

        else:
            self.rbr_identity = (nn.BatchNorm2d(num_features=c1) if c2 == c1 and s == 1 else None)

            self.rbr_dense = nn.Sequential(
                nn.Conv2d(c1, c2, k, s, autopad(k, p), groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )

            self.rbr_1x1 = nn.Sequential(
                nn.Conv2d( c1, c2, 1, s, padding_11, groups=g, bias=False),
                nn.BatchNorm2d(num_features=c2),
            )

    def forward(self, inputs):
        if hasattr(self, "rbr_reparam"):
            return self.act(self.rbr_reparam(inputs))

        if self.rbr_identity is None:
            id_out = 0
        else:
            id_out = self.rbr_identity(inputs)

        return self.act(self.rbr_dense(inputs) + self.rbr_1x1(inputs) + id_out)
    
    def get_equivalent_kernel_bias(self):
        kernel3x3, bias3x3 = self._fuse_bn_tensor(self.rbr_dense)
        kernel1x1, bias1x1 = self._fuse_bn_tensor(self.rbr_1x1)
        kernelid, biasid = self._fuse_bn_tensor(self.rbr_identity)
        return (
            kernel3x3 + self._pad_1x1_to_3x3_tensor(kernel1x1) + kernelid,
            bias3x3 + bias1x1 + biasid,
        )

    def _pad_1x1_to_3x3_tensor(self, kernel1x1):
        if kernel1x1 is None:
            return 0
        else:
            return nn.functional.pad(kernel1x1, [1, 1, 1, 1])

    def _fuse_bn_tensor(self, branch):
        if branch is None:
            return 0, 0
        if isinstance(branch, nn.Sequential):
            kernel = branch[0].weight
            running_mean = branch[1].running_mean
            running_var = branch[1].running_var
            gamma = branch[1].weight
            beta = branch[1].bias
            eps = branch[1].eps
        else:
            assert isinstance(branch, nn.BatchNorm2d)
            if not hasattr(self, "id_tensor"):
                input_dim = self.in_channels // self.groups
                kernel_value = np.zeros(
                    (self.in_channels, input_dim, 3, 3), dtype=np.float32
                )
                for i in range(self.in_channels):
                    kernel_value[i, i % input_dim, 1, 1] = 1

SimRepCSP 主要流程:

  1. 输入图片预处理

    • 图片读取:从存储介质或摄像头读取输入图片。

    • 图片缩放:将图片缩放到模型所需的输入尺寸(例如,YOLOv8 通常使用 640x640 像素的输入大小)。

    • 归一化处理:将图片像素值归一化到 [0, 1] 区间。

  2. 特征提取(通过 SimRepCSP 模块)

    • 初始卷积和下采样:输入图片首先通过一个初始卷积层和下采样层,这有助于减少图片的空间尺寸并提取基本特征。

    • CSP 模块处理:图片特征进入多个 SimRepCSP 模块,每个模块由标准卷积、RepConv 和 CSP 网络组成。具体流程如下:

      • 标准卷积:标准卷积层提取局部特征。

      • RepConv:重新参数化卷积层在训练期间增强模型的表示能力。

      • CSP 网络:跨阶段部分网络将特征进行跨层传递和整合,进一步丰富特征表示。

  3. 多尺度特征提取

    • 特征金字塔网络(FPN):SimRepCSP 结合特征金字塔网络,提取不同尺度的特征以应对不同尺寸的目标物体。

    • 空间金字塔池化(SPPF):在 SimRepCSPv1 和 SimRepCSPv2 中引入 SPPF 模块,用于多尺度特征的聚合和增强。

  4. 特征融合与预测

    • 特征融合:将不同尺度的特征融合,生成最终的特征图。

    • 检测头:最终特征图传递给检测头,进行目标的分类和定位预测。检测头包括一系列的卷积层和激活函数,用于输出目标的类别和边界框坐标。

    2.2 新增yaml文件

    关键步骤二在下/projects/yolov5-6.1/models下新建文件 yolov5_SimRepCSP.yaml并将下面代码复制进去

# YOLOv5 🚀 by Ultralytics, GPL-3.0 license
# Parameters
nc: 80  # number of classes
depth_multiple: 1  # model depth multiple
width_multiple: 1  # 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 1-P2/4
   
   [-1, 1, Conv, [64, 1, 1]], #2

   [-1, 1, RepConv, [64, 3, 1]], #3
   [[-1,-2], 1, Concat, [1]], #4
   [-1, 1, Conv, [128, 1, 1]], #5

   [-1, 1, Conv, [256, 3, 2]],  #6/ 3-P3/8
   
   [-1, 1, Conv, [128, 1, 1]], #7

   [-1, 1, RepConv, [128, 3, 1]], #8
   [[-1,-2], 1, Concat, [1]], #9
   [-1, 1, Conv, [256, 1, 1]],  #10 -P4/16 

   [-1, 1, Conv, [512, 3, 2]], #11
   [-1, 1, Conv, [256, 1, 1]], #12

   [-1, 1, RepConv, [256, 3, 1]], #13
   [[-1,-2], 1, Concat, [1]], #14
   [-1, 1, Conv, [512, 1, 1]], #15

   [-1, 1, Conv, [1024, 3, 2]],  # 7-P5/32 16

   [-1, 1, Conv, [512, 1, 1]], #17

   [-1, 1, RepConv, [512, 3, 1]], #18
   [[-1,-2], 1, Concat, [1]], #19
   [-1, 1, Conv, [1024, 1, 1]], #20

   [-1, 1, SPPF, [1024, 5]],  # 21
  ]


# YOLOv5 v6.0 head
head:
   [[-1, 1, Conv, [512, 1, 1]], #22
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 11], 1, Concat, [1]],  # cat backbone P4
   [-1, 3, C3, [512, False]],  # 25


   [-1, 1, Conv, [256, 1, 1]], #26
   [-1, 1, nn.Upsample, [None, 2, 'nearest']],
   [[-1, 6], 1, Concat, [1]],  #28 cat backbone P3
   [-1, 3, C3, [256, False]],  # 29 (P3/8-small)


   [-1, 1, Conv, [256, 3, 2]],
   [[-1,26], 1, Concat, [1]],  # 31 cat head P4
   [-1, 3, C3, [512, False]],  # 32 (P4/16-medium)


   [-1, 1, Conv, [512, 3, 2]],
   [[-1, 22], 1, Concat, [1]],  #34 cat head P5
   [-1, 3, C3, [1024, False]],  #35 (P5/32-large)


   [[29, 32, 35], 1, Detect, [nc, anchors]],  # Detect(P3, P4, P5)
  ]

温馨提示:本文只是对yolov5l基础上添加模块,如果要对yolov5n/l/m/x进行添加则只需要指定对应的depth_multiple 和 width_multiple。


# YOLOv5n
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.25  # layer channel multiple
 
# YOLOv5s
depth_multiple: 0.33  # model depth multiple
width_multiple: 0.50  # 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

2.3 注册模块

关键步骤三:在yolo.py中注册, 大概在260行左右添加 ‘RepConv’

 2.4 执行程序

在train.py中,将cfg的参数路径设置为yolov5_SimRepCSP.yaml的路径

建议大家写绝对路径,确保一定能找到

🚀运行程序,如果出现下面的内容则说明添加成功🚀

3. 完整代码分享

https://pan.baidu.com/s/17lq0bRONXbtMRgAalj77gA?pwd=39uq

 提取码: 39uq  

4. GFLOPs

关于GFLOPs的计算方式可以查看百面算法工程师 | 卷积基础知识——Convolution

未改进的GFLOPs

改进后的GFLOPs

5.总结

SimRepCSP 是一种针对 YOLO 模型的改进backbone模块,其设计旨在提高训练效率和模型性能,同时降低成本。它通过集成标准卷积模块、重新参数化卷积模块(RepConv)和跨阶段部分网络(CSP)来增强特征传播和网络学习能力。SimRepCSP 的结构包括三个卷积模块、一个 RepConv 模块和一个连接到 CSP 网络的级联模块,这些模块的排列旨在最大化特征提取和重用,从而在减少参数数量的情况下提升性能。每个卷积模块都包含批量归一化和 SiLU 激活函数。SimRepCSP 可以作为替代backbone集成到 YOLOv5 模型中,分别称为 SimRepCSPv1 和 SimRepCSPv2,这种集成旨在提升模型性能指标,相较于原始的backbone。SimRepCSP 的架构包括一个焦点层、多层 SimRepCSP 模块和一个 SPPF(快速空间金字塔池化)模块,用于多尺度特征聚合。带有 SimRepCSP 模块的模型在减少训练和应用成本的同时,实现了更高的性能指标,主要改进包括减少了 FLOPS(每秒浮点运算次数)、GPU 内存使用量和整体模型重量,同时保持或提高了目标检测的准确性。SimRepCSP 的目标和优势在于通过减少所需操作次数降低计算成本,通过微调和优化参数增强参数性能,最小化内存需求以允许更大的批处理大小和更高效的训练,并创建一个轻量级模型,便于部署而不影响性能。总体而言,SimRepCSP 通过优化网络架构、减少计算和内存成本以及增强特征提取和参数调优,显著提高了 YOLO 模型的效率和性能。

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-07 13:44:02       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-07 13:44:02       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-07 13:44:02       87 阅读
  4. Python语言-面向对象

    2024-06-07 13:44:02       96 阅读

热门阅读

  1. Android 跳转系统Settings各界面的ACTION及示例

    2024-06-07 13:44:02       31 阅读
  2. 【chatgpt】学术翻译和英文润色prompt

    2024-06-07 13:44:02       34 阅读
  3. NLP--词袋模型

    2024-06-07 13:44:02       28 阅读
  4. 【力扣】合并k个升序链表

    2024-06-07 13:44:02       29 阅读
  5. python-NLP常用数据集0.1.012

    2024-06-07 13:44:02       34 阅读
  6. 知识蒸馏——讨论区

    2024-06-07 13:44:02       31 阅读
  7. stm32 h5 串口采用DMA循环BUFF接收数据

    2024-06-07 13:44:02       25 阅读
  8. 用 Sentence Transformers v3 训练和微调嵌入模型

    2024-06-07 13:44:02       24 阅读
  9. 解决跨域问题

    2024-06-07 13:44:02       29 阅读
  10. 供应链管理是什么?能解决什么问题?

    2024-06-07 13:44:02       28 阅读
  11. 分布式防止重复请求或者高并发防止重复提交

    2024-06-07 13:44:02       21 阅读
  12. Flutter与iOS原生混合开发 iOS项目集成Flutter

    2024-06-07 13:44:02       35 阅读
  13. KNN算法实例_电影类型判断

    2024-06-07 13:44:02       31 阅读
  14. C++中为什么尽量使用using 代替 typedef

    2024-06-07 13:44:02       29 阅读