您的当前位置:首页正文

YOLO11改进 | SPPF | 双通道特征处理的池化结构——SPPFCSPC【全网独家】

2024-11-08 来源:个人技术集锦

秋招面试专栏推荐 :


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


本文介绍了一种新的池化结构SPPFCSPC,它将特征向量分为2个通道进行处理。一个通道使用分组1×1卷积进行处理,而另一个通道主要使用具有相同并行结构(5×5 MaxPool)的多个滤波器。此外,该分支(Group-Conv)中串联了多个1×1和3×3分组卷积,以提取图像中更复杂的特征。最后,将这两部分连接(Concat)在一起,每个卷积层Conv分为4组,以减少模型中的计算量。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。


1.原理

SPPFCSPC(Spatial Pyramid Pooling Faster Cross Stage Partial Channel)是一个旨在增强卷积神经网络能力的模块,特别是在物体检测任务中。以下是 SPPFCSPC 的关键原理和组件,详见提供的文档:

经典 SPP 结构

  • SPP(Spatial Pyramid Pooling)用于提高模型对空间布局和物体变化的鲁棒性。它接受任意大小的输入图像,并通过一组池化操作提取空间特征信息以形成固定大小的特征图。然后可以将该特征图输入到全连接层中。

  • 核心操作涉及多个具有不同感受野(5×5、9×9、13×13)的最大池化层。

SPPF(Spatial Pyramid Pooling Faster)

  • 该结构是经典 SPP 的增强。 SPPF 使用较小的核心结构进行池化,从而产生二次池化以实现更丰富的特征融合。这通过将大内核尺寸替换为较小的内核尺寸,同时连接三个相同的较小池化组件,减少了计算负荷并提高了模型速度。

SimSPPF:

  • 此简化版本的 SPPF 将激活函数 (SiLU) 替换为 ReLU,而不进行其他结构调整。

SPPCSPC (SPP Cross Stage Partial Channel):

  • 由与最大池化层连接的多个卷积块 (CBS 模块) 组成的串行结构。这些最大池化层的感知范围设置为特定大小 (5×5、9×9、13×13)。

SPPFCSPC-G (SPPF Cross Stage Partial Channel-Group):

  • 这是本文中提出的结构,将分组卷积块与经典的 SPP 方法相结合。

  • 它结合了多个分组卷积块(包括 1×1 和 3×3 卷积)和三个具有相同感受野的串行最大池化层。

  • 分组卷积将输入特征图分成几组(例如四组),并在每组内执行独立的卷积操作。通过将计算分布在不同组中,这减少了计算负载(FLOPS)和参数数量。

分组卷积

  • 分组卷积将输入通道分成多个组,通过仅在每组内独立执行卷积来减少操作数量。

  • 这既降低了计算成本,又减少了参数数量,同时保持甚至增强了模型的表达能力。

性能和优势

  • 参数效率:与其他变体(SPP、SPPF 等)相比,SPPFCSPC-G 模型的参数更少,使其在保持高性能的同时更高效。

  • 计算负荷:使用分组卷积显著降低了计算负荷(以 GFLOPS 为单位),从而缩短了推理时间。

  • 模型准确度:尽管参数和计算负荷减少,但 SPPFCSPC-G 在水稻病害识别任务中的准确度和其他性能指标方面仍优于其他模型。

结论

SPPFCSPC-G 模块通过集成分组卷积增强了传统的 SPP 方法,有效地平衡了模型复杂性和性能之间的权衡。这使其非常适合需要高效和准确特征提取的任务,例如图像中的物体检测。

2. 将SPPFCSPC添加到YOLO11中

2.1 SPPFCSPC代码实现

关键步骤一:将下面代码粘贴到在/ultralytics/ultralytics/nn/modules/block.py中,并在该文件的__all__中添加“SPPFCSPC”

class SPPFCSPC(nn.Module):
    
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5, k=5):
        super(SPPFCSPC, self).__init__()
        c_ = int(2 * c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, 1, 1)
        self.cv2 = Conv(c1, c_, 1, 1)
        self.cv3 = Conv(c_, c_, 3, 1)
        self.cv4 = Conv(c_, c_, 1, 1)
        self.m = nn.MaxPool2d(kernel_size=k, stride=1, padding=k // 2)
        self.cv5 = Conv(4 * c_, c_, 1, 1)
        self.cv6 = Conv(c_, c_, 3, 1)
        self.cv7 = Conv(2 * c_, c2, 1, 1)

    def forward(self, x):
        x1 = self.cv4(self.cv3(self.cv1(x)))
        x2 = self.m(x1)
        x3 = self.m(x2)
        y1 = self.cv6(self.cv5(torch.cat((x1, x2, x3, self.m(x3)), 1)))
        y2 = self.cv2(x)
        return self.cv7(torch.cat((y1, y2), dim=1))

SPPFCSPC(Spatial Pyramid Pooling Faster Cross Stage Partial Channel)的主要操作步骤可以分为以下几个阶段:

1. 数据输入和预处理

  • 数据输入:输入预处理和增强后的图像数据。

  • 数据预处理:包括调整图像大小、归一化、数据增强(如旋转、缩放、颜色变换等)。

2. 初始卷积层

  • 卷积操作:初始卷积层对输入图像进行特征提取,生成特征图。这些层通常包含卷积、批量归一化和激活函数。

  • 池化操作:对特征图进行池化操作(如最大池化),以减少特征图的尺寸和计算量。

3. SPP模块

  • 空间金字塔池化(SPP):使用不同大小的池化核(如5x5、9x9、13x13)对特征图进行多尺度池化,生成固定尺寸的特征向量。SPP可以捕捉不同尺度的空间信息,使得模型对不同大小和比例的对象具有鲁棒性。

4. SPPF模块

  • 快速空间金字塔池化(SPPF):通过多个小型的池化层(如三层3x3的最大池化)代替单个大核的池化操作,进一步丰富特征信息并减少计算开销。

5. Cross Stage Partial Network(CSPNet)

  • CSPNet模块:将特征图分成两部分,其中一部分直接通过残差连接到后续层,另一部分经过卷积操作后再合并。这样可以减少冗余梯度信息,提升梯度流动和特征复用能力。

6. SPPFCSPC模块

  • SPPFCSPC结构:结合SPPF和CSPNet的优势,采用分组卷积操作对特征图进行处理。分组卷积将输入特征图分成多个组,分别进行卷积操作,降低计算成本和参数量,同时保持高效特征提取。

  • 多尺度特征融合:通过多尺度池化和分组卷积,实现多尺度特征融合,增强模型对不同尺度目标的检测能力。

7. 输出层

  • 全连接层:将特征图展平并输入到全连接层,用于分类或回归任务。

  • 分类器或回归器:根据具体任务(如图像分类或目标检测),采用相应的输出层进行预测。

通过以上步骤,SPPFCSPC模块能够高效提取多尺度特征,提高模型的检测精度和速度,适用于各种图像识别和检测任务。

2.2 更改init.py文件

关键步骤二:修改modules文件夹下的__init__.py文件,先导入函数

然后在下面的__all__中声明函数

2.3 新增yaml文件

关键步骤三:在 \ultralytics\ultralytics\cfg\models\11下新建文件 yolo11_SPPFCSPC.yaml并将下面代码复制进去

  • 目标检测 
# Ultralytics YOLO ?, AGPL-3.0 license
# YOLO11 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=yolo11n.yaml' will call yolo11.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPs
  s: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs
  m: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs
  l: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs
  x: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs

# YOLO11n 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, 2, C3k2, [256, False, 0.25]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2, [512, False, 0.25]]
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2, [1024, True]]
  - [-1, 1, SPPFCSPC, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

# YOLO11n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 2, C3k2, [512, False]] # 13

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 4], 1, Concat, [1]] # cat backbone P3
  - [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P4
  - [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 10], 1, Concat, [1]] # cat head P5
  - [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)

  - [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)
  • OBB
# Ultralytics YOLO ?, AGPL-3.0 license
# YOLO11 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=yolo11n.yaml' will call yolo11.yaml with scale 'n'
  # [depth, width, max_channels]
  n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPs
  s: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPs
  m: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPs
  l: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPs
  x: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs

# YOLO11n 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, 2, C3k2, [256, False, 0.25]]
  - [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
  - [-1, 2, C3k2, [512, False, 0.25]]
  - [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
  - [-1, 2, C3k2, [512, True]]
  - [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
  - [-1, 2, C3k2, [1024, True]]
  - [-1, 1, SPPFCSPC, [1024, 5]] # 9
  - [-1, 2, C2PSA, [1024]] # 10

# YOLO11n head
head:
  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 6], 1, Concat, [1]] # cat backbone P4
  - [-1, 2, C3k2, [512, False]] # 13

  - [-1, 1, nn.Upsample, [None, 2, "nearest"]]
  - [[-1, 4], 1, Concat, [1]] # cat backbone P3
  - [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)

  - [-1, 1, Conv, [256, 3, 2]]
  - [[-1, 13], 1, Concat, [1]] # cat head P4
  - [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)

  - [-1, 1, Conv, [512, 3, 2]]
  - [[-1, 10], 1, Concat, [1]] # cat head P5
  - [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)

  - [[16, 19, 22], 1, OBB, [nc, 1]] # Detect(P3, P4, P5)

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


# YOLO11n
depth_multiple: 0.50  # model depth multiple
width_multiple: 0.25  # layer channel multiple
max_channel:1024
 
# YOLO11s
depth_multiple: 0.50  # model depth multiple
width_multiple: 0.50  # layer channel multiple
max_channel:1024
 
# YOLO11m
depth_multiple: 0.50  # model depth multiple
width_multiple: 1.00  # layer channel multiple
max_channel:512
 
# YOLO11l 
depth_multiple: 1.00  # model depth multiple
width_multiple: 1.00  # layer channel multiple
max_channel:512 
 
# YOLO11x
depth_multiple: 1.00  # model depth multiple
width_multiple: 1.50 # layer channel multiple
max_channel:512

2.4 注册模块

关键步骤四:在parse_model函数中进行注册,添加SPPFCSPC,

2.5 执行程序

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

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

from ultralytics import YOLO
import warnings
warnings.filterwarnings('ignore')
from pathlib import Path
 
if __name__ == '__main__':
 
 
    # 加载模型
    model = YOLO("ultralytics/cfg/11/yolo11.yaml")  # 你要选择的模型yaml文件地址
    # Use the model
    results = model.train(data=r"你的数据集的yaml文件地址",
                          epochs=100, batch=16, imgsz=640, workers=4, name=Path(model.cfg).stem)  # 训练模型

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

                   from  n    params  module                                       arguments
  0                  -1  1       464  ultralytics.nn.modules.conv.Conv             [3, 16, 3, 2]
  1                  -1  1      4672  ultralytics.nn.modules.conv.Conv             [16, 32, 3, 2]
  2                  -1  1      6640  ultralytics.nn.modules.block.C3k2            [32, 64, 1, False, 0.25]      
  3                  -1  1     36992  ultralytics.nn.modules.conv.Conv             [64, 64, 3, 2]
  4                  -1  1     26080  ultralytics.nn.modules.block.C3k2            [64, 128, 1, False, 0.25]     
  5                  -1  1    147712  ultralytics.nn.modules.conv.Conv             [128, 128, 3, 2]
  6                  -1  1     87040  ultralytics.nn.modules.block.C3k2            [128, 128, 1, True]
  7                  -1  1    295424  ultralytics.nn.modules.conv.Conv             [128, 256, 3, 2]
  8                  -1  1    346112  ultralytics.nn.modules.block.C3k2            [256, 256, 1, True]
  9                  -1  1   1773056  ultralytics.nn.modules.block.SPPFCSPC        [256, 256, 5]
 10                  -1  1    249728  ultralytics.nn.modules.block.C2PSA           [256, 256, 1]
 11                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']
 12             [-1, 6]  1         0  ultralytics.nn.modules.conv.Concat           [1]
 13                  -1  1    111296  ultralytics.nn.modules.block.C3k2            [384, 128, 1, False]
 14                  -1  1         0  torch.nn.modules.upsampling.Upsample         [None, 2, 'nearest']
 15             [-1, 4]  1         0  ultralytics.nn.modules.conv.Concat           [1]
 16                  -1  1     32096  ultralytics.nn.modules.block.C3k2            [256, 64, 1, False]
 17                  -1  1     36992  ultralytics.nn.modules.conv.Conv             [64, 64, 3, 2]
 18            [-1, 13]  1         0  ultralytics.nn.modules.conv.Concat           [1]
 19                  -1  1     86720  ultralytics.nn.modules.block.C3k2            [192, 128, 1, False]
 20                  -1  1    147712  ultralytics.nn.modules.conv.Conv             [128, 128, 3, 2]
 21            [-1, 10]  1         0  ultralytics.nn.modules.conv.Concat           [1]
 22                  -1  1    378880  ultralytics.nn.modules.block.C3k2            [384, 256, 1, True]
 23        [16, 19, 22]  1    464912  ultralytics.nn.modules.head.Detect           [80, [64, 128, 256]]
YOLO11_SPPFCSPC summary: 334 layers, 4,232,528 parameters, 4,232,512 gradients, 7.9 GFLOPs

3.修改后的网络结构图

4. 完整代码分享

pan.bai【删掉】du.【删掉】com/s/1rV3Qhdmm32vnMDE0-bJiRA?pwd=2djd

提取码: 2djd 

5. GFLOPs

关于GFLOPs的计算方式可以查看

未改进的YOLO11n GFLOPs

改进后的GFLOPs 

6. 进阶

可以与其他的注意力机制或者损失函数等结合,进一步提升检测效果

7.总结

SPPFCSPC(Spatial Pyramid Pooling Faster Cross Stage Partial Channel)模块的主要原理是通过结合多尺度空间金字塔池化(SPP)和改进的跨阶段部分网络(CSPNet)结构来增强卷积神经网络的特征提取能力。SPPFCSPC首先通过不同大小的池化核进行多尺度池化,捕捉图像中的多尺度信息,然后利用快速空间金字塔池化(SPPF)模块,通过多个小型池化操作丰富特征表达,同时降低计算成本。接着,模块采用分组卷积将特征图分成多个组,分别进行卷积操作,以减少参数量和计算开销。最后,通过CSPNet的部分跨阶段连接,有效提升梯度流动和特征复用能力,进一步增强模型的性能。总体而言,SPPFCSPC模块通过多尺度特征融合和高效的特征提取,显著提高了图像识别和检测任务的准确性和效率。

显示全文