秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
专栏目录 :《YOLOv5入门 + 改进涨点》专栏介绍 & 专栏目录 | 目前已有90+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进
本文介绍一种新的自校准卷积方法,无需改变网络架构,即可增强CNN的表征能力。该方法通过内部通信扩展卷积层的视野,自适应建立长距离的空间和跨通道依赖,从而丰富特征输出。文章在介绍主要的原理后,将手把手教学如何进行模块的代码添加和修改,并将修改后的完整代码放在文章的最后,方便大家一键运行,小白也可轻松上手实践。以帮助您更好地学习深度学习目标检测YOLO系列的挑战。
专栏地址: YOLOv5改进+入门——持续更新各种有效涨点方法 点击即可跳转
目录
1. 原理
2. 将C3_SCConv添加到yolov5网络中
2.1 C3_SCConv代码实现
2.2 C3_SCConv的神经网络模块代码解析
2.3 新增yaml文件
2.4 注册模块
2.5 执行程序
3. 完整代码分享
4. GFLOPs
5. 进阶
6. 总结
1. 原理
论文地址:Improving Convolutional Networks with Self-Calibrated Convolutions——点击即可跳转
官方代码:官方代码仓库——点击即可跳转
SCConv(自校准卷积)旨在通过扩大视野并整合更丰富的空间和通道信息来改进传统卷积,而无需修改整体架构或增加复杂性。
SCConv 的关键原则包括:
-
内部通信:SCConv 在每个空间位置上实现长距离空间和通道间依赖性,与传统的小核卷积相比,增强了特征图的丰富性。
-
异构卷积:滤波器被分成多个部分,每个部分处理不同的任务。一些滤波器对输入进行下采样,执行卷积,然后上采样,允许校准主卷积。
-
自校准操作:输入特征图被分成两部分,一部分由标准卷积处理,另一部分经过自校准过程,引入低分辨率嵌入。这种由下采样创建的嵌入会影响原始分辨率空间中的卷积。
-
增强的感受野:通过处理多个尺度(低分辨率和高分辨率)的特征图,SCConv 增加了每个卷积层的感受野,使其能够捕获更多的上下文信息。
-
无额外参数:尽管 SCConv 有诸多好处,但它不会引入额外参数或显著增加计算复杂度,因此非常高效,并且易于应用于现有网络。
2. 将C3_SCConv添加到yolov5网络中
2.1 C3_SCConv代码实现
关键步骤一: 将下面的代码粘贴到\yolov5\models\common.py中
import torch.nn.functional as Fclass SCConv(nn.Module):# https://github.com/MCG-NKU/SCNet/blob/master/scnet.pydef __init__(self, c1, c2, s=1, d=1, g=1, pooling_r=4):super(SCConv, self).__init__()self.k2 = nn.Sequential(nn.AvgPool2d(kernel_size=pooling_r, stride=pooling_r), Conv(c1, c2, k=3, d=d, g=g, act=False))self.k3 = Conv(c1, c2, k=3, d=d, g=g, act=False)self.k4 = Conv(c1, c2, k=3, s=s, d=d, g=g, act=False)def forward(self, x):identity = xout = torch.sigmoid(torch.add(identity, F.interpolate(self.k2(x), identity.size()[2:]))) # sigmoid(identity + k2)out = torch.mul(self.k3(x), out) # k3 * sigmoid(identity + k2)out = self.k4(out) # k4return outclass Bottleneck_SCConv(Bottleneck):def __init__(self, c1, c2, shortcut=True, g=1, e=0.5):super().__init__(c1, c2, shortcut, g, e)c_ = int(c2 * e) # hidden channelsself.cv1 = Conv(c1, c_, 1)self.cv2 = SCConv(c_, c2, g=g)class C3_SCConv(C3):def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):super().__init__(c1, c2, n, shortcut, g, e)c_ = int(c2 * e) # hidden channelsself.m = nn.Sequential(*(Bottleneck_SCConv(c_, c_, shortcut, g, e=1.0) for _ in range(n)))
2.2 C3_SCConv的神经网络模块代码解析
C3_SCConv
类将自校准卷积 (SCConv) 机制集成到经过修改的 C2f 块结构中,增强了其通过扩展的接受场捕获更多上下文信息的能力,同时保持了高效的计算复杂度。
-
基础结构(C3 继承):
C3_SCConv
继承自C3
类,后者通常是用于融合深度学习网络中特征的自定义卷积块。这允许基于 SCConv 的块直接替换或增强现有架构中的标准卷积。 -
Bottleneck_SCConv 集成:
C3_SCConv
的核心功能是使用Bottleneck_SCConv
,它用 SCConv 替换标准卷积。这种瓶颈结构有助于通过引入缩小的中间表示(c_
)来减少参数数量,该中间表示随后使用 SCConv 操作进行扩展。 -
SCConv 机制:
C3_SCConv
中的每个瓶颈都使用 SCConv 来:
-
将卷积滤波器拆分为单独的部分,从而实现多尺度特征提取。
-
使用下采样生成的低分辨率嵌入来指导原始分辨率空间中的卷积过程,从而改善空间和通道级信息聚合。
-
Bottleneck_SCConv 的顺序应用:
C3_SCConv
使用ModuleList
来包含多个Bottleneck_SCConv
实例,每个实例负责执行 SCConv 增强的转换。这些按顺序应用以捕获越来越丰富和详细的特征表示。 -
特征融合:与 C3 类似,
C3_SCConv
块可执行有效的特征融合,但具有 SCConv 增强卷积,这提高了模型收集长距离空间依赖性的能力,使最终的特征图更具辨别性。
总体而言,C3_SCConv
的主要目标是通过将 SCConv 嵌入 C3 块来改进特征表示,从而增强空间和通道特征提取,而不会显着增加计算负荷。
2.3 新增yaml文件
关键步骤二:在下/yolov5/models下新建文件 yolov5_C3_SCConv.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_SCConv, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3_SCConv, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3_SCConv, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3_SCConv, [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_SCConv, [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_SCConv, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3_SCConv, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3_SCConv, [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_SCConv, [128]],[-1, 1, Conv, [256, 3, 2]], # 3-P3/8[-1, 6, C3_SCConv, [256]],[-1, 1, Conv, [512, 3, 2]], # 5-P4/16[-1, 9, C3_SCConv, [512]],[-1, 1, Conv, [1024, 3, 2]], # 7-P5/32[-1, 3, C3_SCConv, [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_SCConv, [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_SCConv, [256, False]], # 17 (P3/8-small)[-1, 1, Conv, [256, 3, 2]],[[-1, 14], 1, Concat, [1]], # cat head P4[-1, 3, C3_SCConv, [512, False]], # 20 (P4/16-medium)[-1, 1, Conv, [512, 3, 2]],[[-1, 10], 1, Concat, [1]], # cat head P5[-1, 3, C3_SCConv, [1024, False]], # 23 (P5/32-large)[[17, 20, 23], 1, Segment, [nc, anchors, 32, 256]], # Segment (P3, P4, P5)]
2.4 注册模块
关键步骤三:在yolo.py的parse_model函数替换添加C3_SCConv
2.5 执行程序
在train.py中,将cfg的参数路径设置为yolov5_C3_ScConv.yaml的路径
建议大家写绝对路径,确保一定能找到
🚀运行程序,如果出现下面的内容则说明添加成功🚀
from n params module arguments0 -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 378880 models.common.C3_SCConv [128, 128, 3]3 -1 1 295424 models.common.Conv [128, 256, 3, 2]4 -1 6 2890752 models.common.C3_SCConv [256, 256, 6]5 -1 1 1180672 models.common.Conv [256, 512, 3, 2]6 -1 9 17059840 models.common.C3_SCConv [512, 512, 9]7 -1 1 4720640 models.common.Conv [512, 1024, 3, 2]8 -1 3 24133632 models.common.C3_SCConv [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 6299648 models.common.C3_SCConv [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 1576960 models.common.C3_SCConv [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 6037504 models.common.C3_SCConv [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 24133632 models.common.C3_SCConv [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_SCConv summary: 764 layers, 95478397 parameters, 95478397 gradients
3. 完整代码分享
https://pan.baidu.com/s/1tU2ys_qlK2gmOdr1bPCOXw?pwd=7u5f
提取码: 7u5f
4. GFLOPs
关于GFLOPs的计算方式可以查看:百面算法工程师 | 卷积基础知识——Convolution
未改进的GFLOPs
改进后的GFLOPs
有需要的同学自己测一下
5. 进阶
可以结合损失函数或者卷积模块进行多重改进
YOLOv5改进 | 损失函数 | EIoU、SIoU、WIoU、DIoU、FocuSIoU等多种损失函数——点击即可跳转
6. 总结
自校准卷积 (SCConv) 旨在通过扩展感受野并结合更丰富的上下文信息(包括空间和跨通道信息)来增强传统卷积运算,而无需修改整体网络架构或添加额外参数。它将卷积滤波器划分为多个部分,每个部分都发挥着不同的作用。输入的一部分被下采样并转换为低分辨率嵌入,然后被上采样并用于指导原始分辨率空间中的卷积过程。这种自校准机制使 SCConv 能够捕获长距离空间依赖性和通道间相关性,从而提高特征图的判别能力。该方法增加了感受野,使每个空间位置能够自适应地从更大的区域收集信息,从而生成更详细、更具代表性的特征,同时保持计算效率。