YOLOv5改进 | 模块缝合 | C3融合多尺度表征学习模块 【含OD、Seg等yaml文件】

秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转


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


专栏目录: 《YOLOv5入门 + 改进涨点》专栏介绍 & 专栏目录 |目前已有70+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进


本文介绍的Multi-Scale是基于不同核大小的卷积如何影响不同尺度对象的检测性能研究。其成果是一种新策略,可以显著增强实时目标检测器在多尺度特征表示上的能力。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。 

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

目录

1. 原理 

2. 将C3_MSBlock添加到yolov5网络中

2.1 C3_MSBlock代码实现

2.2 C3_MSBlock的神经网络模块代码解析

2.3 新增yaml文件

2.4 注册模块

2.5 执行程序

3. 完整代码分享

4. GFLOPs

5. 进阶

6. 总结


1. 原理 

论文地址:YOLO-MS: Rethinking Multi-Scale Representation Learning for Real-time Object Detection——点击即可跳转

官方代码:官方代码仓库——点击即可跳转

多尺度块(MS-Block)是增强实时物体检测中多尺度特征表示能力的关键组件。以下是其主要原理的分解:

  1. 分层特征融合:MS-Block 采用受 Res2Net 模型启发的分层特征融合策略。它将输入特征图分成多个组,每个组单独处理。第一组不做任何修改就通过,而后续组则通过倒置瓶颈层处理,这些层涉及具有不同内核大小的深度卷积。这使网络能够有效地捕获多尺度特征。

  2. 带深度卷积的倒置瓶颈:MS-Block 使用带深度卷积的倒置瓶颈结构,而不是标准卷积。这种方法可以有效地使用大内核,从而增强了块捕获不同尺度特征的能力,而不会产生过多的计算成本。

  3. 通道交互:经过反向瓶颈层处理后,特征图被连接起来并通过 1x1 卷积。这最后一步促进了前面步骤中提取的不同尺度特征之间的交互,确保输出特征图包含丰富的多尺度表示。

  4. 多尺度表示效率:MS-Block 旨在平衡计算效率和捕获多尺度特征的能力。通过调整深度卷积中使用的分支数量和内核大小,可以优化该块以在对象检测任务中实现速度和准确性之间的更好权衡。

MS在实时对象检测中特别有用,因为速度和准确性都至关重要,因为它允许模型有效地学习和表示多个尺度的特征,同时保持较高的推理速度。

2. 将C3_MSBlock添加到yolov5网络中

2.1 C3_MSBlock代码实现

关键步骤一将下面的代码粘贴到\yolov5\models\common.py中


class MSBlockLayer(nn.Module):
    def __init__(self, inc, ouc, k) -> None:
        super().__init__()
        
        self.in_conv = Conv(inc, ouc, 1)
        self.mid_conv = Conv(ouc, ouc, k, g=ouc)
        self.out_conv = Conv(ouc, inc, 1)
    
    def forward(self, x):
        return self.out_conv(self.mid_conv(self.in_conv(x)))

class MSBlock(nn.Module):
    def __init__(self, inc, ouc, kernel_sizes, in_expand_ratio=3., mid_expand_ratio=2., layers_num=3, in_down_ratio=2.) -> None:
        super().__init__()
        
        in_channel = int(inc * in_expand_ratio // in_down_ratio)
        self.mid_channel = in_channel // len(kernel_sizes)
        groups = int(self.mid_channel * mid_expand_ratio)
        self.in_conv = Conv(inc, in_channel)
        
        self.mid_convs = []
        for kernel_size in kernel_sizes:
            if kernel_size == 1:
                self.mid_convs.append(nn.Identity())
                continue
            mid_convs = [MSBlockLayer(self.mid_channel, groups, k=kernel_size) for _ in range(int(layers_num))]
            self.mid_convs.append(nn.Sequential(*mid_convs))
        self.mid_convs = nn.ModuleList(self.mid_convs)
        self.out_conv = Conv(in_channel, ouc, 1)
        
        self.attention = None
    
    def forward(self, x):
        out = self.in_conv(x)
        channels = []
        for i,mid_conv in enumerate(self.mid_convs):
            channel = out[:,i * self.mid_channel:(i+1) * self.mid_channel,...]
            if i >= 1:
                channel = channel + channels[i-1]
            channel = mid_conv(channel)
            channels.append(channel)
        out = torch.cat(channels, dim=1)
        out = self.out_conv(out)
        if self.attention is not None:
            out = self.attention(out)  
        return out

class C3_MSBlock(C3):
    def __init__(self, c1, c2, n=1, kernel_sizes=[1, 3, 3], in_expand_ratio=3., mid_expand_ratio=2., layers_num=3, in_down_ratio=2., shortcut=False, g=1, e=0.5):
        super().__init__(c1, c2, n, shortcut, g, e)
        c_ = int(c2 * e)  # hidden channels
        self.m = nn.Sequential(*(MSBlock(c_, c_, kernel_sizes, in_expand_ratio, mid_expand_ratio, layers_num, in_down_ratio) for _ in range(n)))

2.2 C3_MSBlock的神经网络模块代码解析

这段代码实现了一个多尺度特征提取模块,分为三个主要类:MSBlockLayerMSBlockC3_MSBlock。以下是每个类的详细解释:

1. MSBlockLayer

  • 功能: 实现一个基本的卷积层序列,用于处理特定尺度的特征图。

  • 构造函数参数:

    • inc: 输入通道数。

    • ouc: 输出通道数。

    • k: 卷积核大小。

  • 构造函数内容:

    • self.in_conv: 1x1卷积,用于调整输入通道数。

    • self.mid_conv: 使用深度可分离卷积(group convolution)的中间卷积层,卷积核大小为k

    • self.out_conv: 1x1卷积,将通道数还原为输入通道数。

  • forward函数: 顺序执行in_convmid_convout_conv,返回处理后的特征图。

2. MSBlock

  • 功能: 实现一个多尺度特征块,包含多个 MSBlockLayer 组成的分支,每个分支对应不同的卷积核大小。

  • 构造函数参数:

    • inc: 输入通道数。

    • ouc: 输出通道数。

    • kernel_sizes: 卷积核大小的列表,用于指定每个分支的卷积核大小。

    • in_expand_ratio: 输入通道扩展倍率。

    • mid_expand_ratio: 中间通道扩展倍率。

    • layers_num: 每个分支中MSBlockLayer的层数。

    • in_down_ratio: 输入通道缩减倍率。

  • 构造函数内容:

    • in_channel: 计算扩展后的输入通道数。

    • self.mid_channel: 每个分支的通道数。

    • groups: 深度卷积的组数(与通道数有关)。

    • self.in_conv: 用于调整输入特征图通道数的卷积层。

    • self.mid_convs: 一个包含多个分支的模块列表,每个分支使用不同的卷积核大小。

    • self.out_conv: 用于将多分支输出融合成最终输出的1x1卷积。

    • self.attention: 暂时未使用的注意力机制模块。

  • forward函数: 先通过in_conv处理输入,然后在各个分支中进行特征提取,最后通过拼接和卷积生成输出。如果定义了注意力机制,还会对输出进行进一步处理。

3. C3_MSBlock

  • 功能: 继承自 C3 类,是一个容器类,用于在其中集成多个 MSBlock

  • 构造函数参数:

    • c1: 输入通道数。

    • c2: 输出通道数。

    • n: MSBlock 的数量。

    • kernel_sizes: 卷积核大小的列表。

    • 其他参数 (in_expand_ratio, mid_expand_ratio, layers_num, in_down_ratio, shortcut, g, e): 用于配置 MSBlockC3 类的各种特性。

  • 构造函数内容:

    • self.m: 包含多个 MSBlock 的模块列表,每个 MSBlock 按照指定参数进行初始化。

总结

这个代码通过 MSBlockLayer 实现了基础的多尺度特征提取单元,再通过 MSBlock 将这些单元组合成多分支模块,每个分支负责提取不同尺度的特征。最后,C3_MSBlock 类将多个 MSBlock 组合在一起,用于构建更复杂的多尺度特征提取网络。这种设计能够有效地捕捉图像中不同尺度的特征,提高模型的检测能力。

2.3 新增yaml文件

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

  • 目标检测yaml文件 
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # 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_MSBlock, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_MSBlock, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_MSBlock, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_MSBlock, [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)
  ]
  • 语义分割yaml文件
# Ultralytics YOLOv5 🚀, AGPL-3.0 license

# Parameters
nc: 80 # number of classes
depth_multiple: 1.0 # model depth multiple
width_multiple: 1.0 # 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_MSBlock, [128]],
    [-1, 1, Conv, [256, 3, 2]], # 3-P3/8
    [-1, 6, C3_MSBlock, [256]],
    [-1, 1, Conv, [512, 3, 2]], # 5-P4/16
    [-1, 9, C3_MSBlock, [512]],
    [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32
    [-1, 3, C3_MSBlock, [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, Segment, [nc, anchors, 32, 256]], # Segment (P3, P4, P5)
  ]

温馨提示:本文只是对yolov5基础上添加模块,如果要对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.4 注册模块

关键步骤三在yolo.py的parse_model函数替换添加C3_MSBlock

2.5 执行程序

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

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

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

                 from  n    params  module                                  arguments
  0                -1  1      7040  models.common.Conv                      [3, 64, 6, 2, 2]
  1                -1  1     73984  models.common.Conv                      [64, 128, 3, 2]
  2                -1  3    160960  models.common.C3_MSBlock                [128, 128, 3]
  3                -1  1    295424  models.common.Conv                      [128, 256, 3, 2]
  4                -1  6   1085184  models.common.C3_MSBlock                [256, 256, 6]
  5                -1  1   1180672  models.common.Conv                      [256, 512, 3, 2]
  6                -1  9   6039808  models.common.C3_MSBlock                [512, 512, 9]
  7                -1  1   4720640  models.common.Conv                      [512, 1024, 3, 2]
  8                -1  3   9315840  models.common.C3_MSBlock                [1024, 1024, 3]
  9                -1  1   2624512  models.common.SPPF                      [1024, 1024, 5]
 10                -1  1    525312  models.common.Conv                      [1024, 512, 1, 1]
 11                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 12           [-1, 6]  1         0  models.common.Concat                    [1]
 13                -1  3   2757632  models.common.C3                        [1024, 512, 3, False]
 14                -1  1    131584  models.common.Conv                      [512, 256, 1, 1]
 15                -1  1         0  torch.nn.modules.upsampling.Upsample    [None, 2, 'nearest']
 16           [-1, 4]  1         0  models.common.Concat                    [1]
 17                -1  3    690688  models.common.C3                        [512, 256, 3, False]
 18                -1  1    590336  models.common.Conv                      [256, 256, 3, 2]
 19          [-1, 14]  1         0  models.common.Concat                    [1]
 20                -1  3   2495488  models.common.C3                        [512, 512, 3, False]
 21                -1  1   2360320  models.common.Conv                      [512, 512, 3, 2]
 22          [-1, 10]  1         0  models.common.Concat                    [1]
 23                -1  3   9971712  models.common.C3                        [1024, 1024, 3, False]        
 24      [17, 20, 23]  1    457725  Detect                                  [80, [[10, 13, 16, 30, 33, 23], [30, 61, 62, 45, 59, 119], [116, 90, 156, 198, 373, 326]], [256, 512, 1024]]
YOLOv5_C3_MSBlock summary: 1712 layers, 45484861 parameters, 45484861 gradients, 108.5 GFLOPs

3. 完整代码分享

https://pan.baidu.com/s/1i0GmxIL0w5HJ3H4h35frLw?pwd=ivax

 提取码: ivax 

4. GFLOPs

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

未改进的GFLOPs

img

改进后的GFLOPs

5. 进阶

可以结合损失函数或者卷积模块进行多重改进

YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转

6. 总结

Multi-Scale Block (MS-Block) 是一种旨在增强实时目标检测中多尺度特征表示能力的核心组件。它通过分层特征融合策略,将输入特征图分成多个分支,并利用倒置瓶颈结构中的深度可分离卷积对不同分支进行处理。每个分支采用不同大小的卷积核,以有效捕捉不同尺度的特征,同时控制计算开销。之后,这些分支的输出会被拼接,并通过一个1x1卷积层进行通道间的交互,从而整合多尺度信息,生成具有丰富特征表示的输出特征图。MS-Block的设计重点在于在保持计算效率的同时,显著提高多尺度特征的捕捉能力,从而在实时目标检测中实现速度与精度的平衡。

  • 21
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kay_545

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值