news 2026/9/1 13:35:59

YOLO26改进 - 卷积Conv | SPConv:基于分割的卷积巧解特征冗余,实现高效特征提取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLO26改进 - 卷积Conv | SPConv:基于分割的卷积巧解特征冗余,实现高效特征提取

前言

本文介绍了一种基于分割的卷积操作SPConv及其在YOLO26中的结合。传统卷积方法忽视了特征图中的模式冗余,SPConv将输入特征图分割为代表性部分和不确定冗余部分,分别采用k × k k \times kk×k卷积和1 × 1 1 \times 11×1卷积处理,并引入组卷积减少代表性部分冗余,还设计了无参数特征融合模块。SPConv可直接替代原始卷积。我们将其集成进YOLO26,实验表明配备SPConv的网络在准确性、推理时间上优于基准模型,同时减少了浮点运算和参数量。

文章目录: YOLO26改进大全:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总

专栏链接: YOLO26改进专栏

文章目录

  • 前言
  • 介绍
    • 摘要
  • 文章链接
  • 基本原理
    • 代表性部分的进一步减少
    • 3.2 无参数特征融合模块
  • 核心代码
  • YOLO26引入代码
  • 注册
    • 步骤1:
    • 步骤2
  • 配置yolo26-SPConv.yaml
  • 实验
    • 脚本
    • 结果

介绍

摘要

许多有效的解决方案已被提出以减少推理加速中模型的冗余。然而,常见的方法大多集中在消除不重要的滤波器或构建高效的操作上,而忽视了特征图中的模式冗余。我们揭示了在一个层内,许多特征图分享相似但不完全相同的模式。然而,确定具有类似模式的特征是否冗余或包含重要细节是困难的。因此,我们提出了一种基于分割的卷积操作,即SPConv,来容忍具有相似模式但需要较少计算的特征。具体来说,我们将输入的特征图分割成代表性部分和不确定冗余部分,从代表性部分中通过相对复杂的计算提取内在信息,而在不确定冗余部分中处理微小的隐藏细节则采用轻量级操作。为了重新校准和融合这两组处理过的特征,我们提出了一个无需参数的特征融合模块。此外,我们的SPConv设计成可以直接替代原始卷积,在使用中非常便捷。实验结果表明,基准测试中配备SPConv的网络在GPU上在准确性和推理时间上始终优于最先进的基准模型,同时大幅减少了浮点运算和参数量。

文章链接

论文地址:论文地址

代码地址:代码地址

基本原理

在现有的滤波器中,如常规卷积、GhostConv、OctConv和HetConv,通常在所有输入通道上执行 ( k \times k ) 卷积操作。然而,这些方法未能解决同一层特征中存在的冗余问题,即使不存在完全相同的两个通道特征,也难以直接剔除冗余。

受此现象启发,研究者提出了一种新的方法,将所有输入特征按比例分为两部分:

  1. 代表性部分:执行k × k k \times kk×k卷积以提取重要信息;
  2. 不确定部分:执行1 × 1 1 \times 11×1卷积以补充隐含细节信息。

这种过程可以用以下公式描述:

SPConv = Representative部分 ⊕ Uncertain部分 \text{SPConv} = \text{Representative部分} \oplus \text{Uncertain部分}SPConv=Representative部分Uncertain部分

代表性部分的进一步减少

在将所有输入通道分成两个主要部分后,代表性部分之间可能存在冗余。为了进一步减少这种冗余,我们引入了组卷积的概念。组卷积可以视作具有稀疏块对角卷积核的普通卷积,其中每个块对应一个通道,并且分组之间没有连接。这一步骤旨在消除代表性部分内部的冗余,尽管可能会牺牲一些跨通道连接的有用信息。为了弥补信息损失,我们在所有代表性通道上应用逐点卷积,将组卷积和逐点卷积的结果通过直接求和融合,从而获得更丰富的特征表示。

3.2 无参数特征融合模块

为了克服分组信息损失带来的影响,我们设计了一个无参数特征融合模块,用于控制不同输入通道特征的有效融合。这一模块与传统的直接求和融合不同,不需要额外的参数,却能提升模型的性能表现。这种设计使得我们的SPConv在性能和效率上都有显著的提升。

通过这些优化,SPConv不仅解决了传统方法中存在的特征冗余和信息损失问题,还有效地提升了模型的整体性能和学习能力。

这些创新的特征提取和融合方法,使得SPConv在图像处理和计算机视觉任务中具有广泛的应用前景。

核心代码

classSPConv_3x3(nn.Module):def__init__(self,inplanes,outplanes,stride=1,ratio=0.5):super(SPConv_3x3,self).__init__()# 计算3x3卷积和1x1卷积的输入输出通道数self.inplanes_3x3=int(inplanes*ratio)self.inplanes_1x1=inplanes-self.inplanes_3x3 self.outplanes_3x3=int(outplanes*ratio)self.outplanes_1x1=outplanes-self.outplanes_3x3 self.outplanes=outplanes self.stride=stride# 定义3x3组卷积和1x1卷积层self.gwc=nn.Conv2d(self.inplanes_3x3,self.outplanes,kernel_size=3,stride=self.stride,padding=1,groups=2,bias=False)self.pwc=nn.Conv2d(self.inplanes_3x3,self.outplanes,kernel_size=1,bias=False)# 定义1x1卷积层self.conv1x1=nn.Conv2d(self.inplanes_1x1,self.outplanes,kernel_size=1)# 定义平均池化层self.avgpool_s2_1=nn.AvgPool2d(kernel_size=2,stride=2)self.avgpool_s2_3=nn.AvgPool2d(kernel_size=2,stride=2)self.avgpool_add_1=nn.AdaptiveAvgPool2d(1)self.avgpool_add_3=nn.AdaptiveAvgPool2d(1)# 定义批归一化层self.bn1=nn.BatchNorm2d(self.outplanes)self.bn2=nn.BatchNorm2d(self.outplanes)self.ratio=ratio self.groups=int(1/self.ratio)defforward(self,x):b,c,_,_=x.size()# 分割输入特征为3x3卷积部分和1x1卷积部分x_3x3=x[:,:int(c*self.ratio),:,:]x_1x1=x[:,int(c*self.ratio):,:,:]# 3x3卷积部分的前向传播out_3x3_gwc=self.gwc(x_3x3)ifself.stride==2:x_3x3=self.avgpool_s2_3(x_3x3)out_3x3_pwc=self.pwc(x_3x3)out_3x3=out_3x3_gwc+out_3x3_pwc out_3x3=self.bn1(out_3x3)out_3x3_ratio=self.avgpool_add_3(out_3x3).squeeze(dim=3).squeeze(dim=2)# 1x1卷积部分的前向传播ifself.stride==2:x_1x1=self.avgpool_s2_1(x_1x1)out_1x1=self.conv1x1(x_1x1)out_1x1=self.bn2(out_1x1)out_1x1_ratio=self.avgpool_add_1(out_1x1).squeeze(dim=3).squeeze(dim=2)# 将3x3和1x1卷积部分的输出按通道进行堆叠,并应用Softmax进行权重融合out_31_ratio=torch.stack((out_3x3_ratio,out_1x1_ratio),2)out_31_ratio=nn.Softmax(dim=2)(out_31_ratio)# 按融合的权重计算最终的输出out=out_1x1*(out_31_ratio[:,:,1].view(b,self.outplanes,1,1).expand_as(out_1x1))\+out_3x3*(out_31_ratio[:,:,0].view(b,self.outplanes,1,1).expand_as(out_3x3))returnout

YOLO26引入代码

在根目录下的ultralytics/nn/目录,新建一个conv目录,然后新建一个以SPConv为文件名的py文件, 把代码拷贝进去。

importtorchimporttorch.nnasnnclassSPConv(nn.Module):def__init__(self,inplanes,outplanes,stride=1,ratio=0.5):super(SPConv,self).__init__()self.inplanes_3x3=int(inplanes*ratio)self.inplanes_1x1=inplanes-self.inplanes_3x3 self.outplanes_3x3=int(outplanes*ratio)self.outplanes_1x1=outplanes-self.outplanes_3x3 self.outplanes=outplanes self.stride=stride self.gwc=nn.Conv2d(self.inplanes_3x3,self.outplanes,kernel_size=3,stride=self.stride,padding=1,groups=2,bias=False)self.pwc=nn.Conv2d(self.inplanes_3x3,self.outplanes,kernel_size=1,bias=False)self.conv1x1=nn.Conv2d(self.inplanes_1x1,self.outplanes,kernel_size=1)self.avgpool_s2_1=nn.AvgPool2d(kernel_size=2,stride=2)self.avgpool_s2_3=nn.AvgPool2d(kernel_size=2,stride=2)self.avgpool_add_1=nn.AdaptiveAvgPool2d(1)self.avgpool_add_3=nn.AdaptiveAvgPool2d(1)self.bn1=nn.BatchNorm2d(self.outplanes)self.bn2=nn.BatchNorm2d(self.outplanes)self.ratio=ratio self.groups=int(1/self.ratio)defforward(self,x):b,c,_,_=x.size()x_3x3=x[:,:int(c*self.ratio),:,:]x_1x1=x[:,int(c*self.ratio):,:,:]out_3x3_gwc=self.gwc(x_3x3)ifself.stride==2:x_3x3=self.avgpool_s2_3(x_3x3)out_3x3_pwc=self.pwc(x_3x3)out_3x3=out_3x3_gwc+out_3x3_pwc out_3x3=self.bn1(out_3x3)out_3x3_ratio=self.avgpool_add_3(out_3x3).squeeze(dim=3).squeeze(dim=2)# use avgpool first to reduce information lostifself.stride==2:x_1x1=self.avgpool_s2_1(x_1x1)out_1x1=self.conv1x1(x_1x1)out_1x1=self.bn2(out_1x1)out_1x1_ratio=self.avgpool_add_1(out_1x1).squeeze(dim=3).squeeze(dim=2)out_31_ratio=torch.stack((out_3x3_ratio,out_1x1_ratio),2)out_31_ratio=nn.Softmax(dim=2)(out_31_ratio)out=out_1x1*(out_31_ratio[:,:,1].view(b,self.outplanes,1,1).expand_as(out_1x1))\+out_3x3*(out_31_ratio[:,:,0].view(b,self.outplanes,1,1).expand_as(out_3x3))returnout

注册

ultralytics/nn/tasks.py中进行如下操作:

步骤1:

fromultralytics.nn.conv.SPConvimportSPConv

步骤2

修改def parse_model(d, ch, verbose=True):

SPConv

配置yolo26-SPConv.yaml

ultralytics/cfg/models/26/yolo26-SPConv.yaml

# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/license# Ultralytics YOLO26 object detection model with P3/8 - P5/32 outputs# Model docs: https://docs.ultralytics.com/models/yolo26# Task docs: https://docs.ultralytics.com/tasks/detect# Parametersnc:80# number of classesend2end:True# whether to use end-to-end modereg_max:1# DFL binsscales:# model compound scaling constants, i.e. 'model=yolo26n.yaml' will call yolo26.yaml with scale 'n'# [depth, width, max_channels]n:[0.50,0.25,1024]# summary: 260 layers, 2,572,280 parameters, 2,572,280 gradients, 6.1 GFLOPss:[0.50,0.50,1024]# summary: 260 layers, 10,009,784 parameters, 10,009,784 gradients, 22.8 GFLOPsm:[0.50,1.00,512]# summary: 280 layers, 21,896,248 parameters, 21,896,248 gradients, 75.4 GFLOPsl:[1.00,1.00,512]# summary: 392 layers, 26,299,704 parameters, 26,299,704 gradients, 93.8 GFLOPsx:[1.00,1.50,512]# summary: 392 layers, 58,993,368 parameters, 58,993,368 gradients, 209.5 GFLOPs# YOLO26n backbonebackbone:# [from, repeats, module, args]-[-1,1,Conv,[64,3,2]]# 0-P1/2-[-1,1,SPConv,[128,2]]# 1-P2/4-[-1,2,C3k2,[256,False,0.25]]-[-1,1,SPConv,[256,2]]# 3-P3/8-[-1,2,C3k2,[512,False,0.25]]-[-1,1,SPConv,[512,2]]# 5-P4/16-[-1,2,C3k2,[512,True]]-[-1,1,SPConv,[1024,2]]# 7-P5/32-[-1,2,C3k2,[1024,True]]-[-1,1,SPPF,[1024,5,3,True]]# 9-[-1,2,C2PSA,[1024]]# 10# YOLO26n headhead:-[-1,1,nn.Upsample,[None,2,"nearest"]]-[[-1,6],1,Concat,[1]]# cat backbone P4-[-1,2,C3k2,[512,True]]# 13-[-1,1,nn.Upsample,[None,2,"nearest"]]-[[-1,4],1,Concat,[1]]# cat backbone P3-[-1,2,C3k2,[256,True]]# 16 (P3/8-small)-[-1,1,Conv,[256,3,2]]-[[-1,13],1,Concat,[1]]# cat head P4-[-1,2,C3k2,[512,True]]# 19 (P4/16-medium)-[-1,1,Conv,[512,3,2]]-[[-1,10],1,Concat,[1]]# cat head P5-[-1,1,C3k2,[1024,True,0.5,True]]# 22 (P5/32-large)-[[16,19,22],1,Detect,[nc]]# Detect(P3, P4, P5)

实验

脚本

importwarnings warnings.filterwarnings('ignore')fromultralyticsimportYOLOif__name__=='__main__':# 修改为自己的配置文件地址model=YOLO('./ultralytics/cfg/models/26/yolo26-SPConv.yaml')# 修改为自己的数据集地址model.train(data='./ultralytics/cfg/datasets/coco8.yaml',cache=False,imgsz=640,epochs=10,single_cls=False,# 是否是单类别检测batch=8,close_mosaic=10,workers=0,optimizer='MuSGD',# optimizer='SGD',amp=False,project='runs/train',name='yolo26-SPConv',)

结果

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/22 2:26:17

电气设计的隐藏外挂:1:1元器件图库实战

电气高低压成套元器件 几乎每个厂家的元器件都画出来了尺寸大小电气高低压成套元器件 几乎每个厂家的元器件都画出来了尺寸大小型号都有,应有尽有,全部1:1尺寸,直接标注就OK配电柜设计现场最要命的场景:左手抓着某厂家的断路器样本…

作者头像 李华
网站建设 2026/8/27 5:38:04

珲春推荐烤肉哪家无广

珲春无广烤肉推荐:延炭乳酸菌烤肉 在珲春这座美食之城,烤肉是当地极具特色的美食之一。若想寻找一家无广且高品质的烤肉店,延炭乳酸菌烤肉是不可错过的选择。 主打健康概念 延炭乳酸菌烤肉以其独特的健康理念脱颖而出。店内用乳酸菌腌制肉类…

作者头像 李华
网站建设 2026/9/1 5:03:21

基于BP神经网络的迭代优化实现(MATLAB)

一、MATLAB实现代码 1. 网络结构定义 %% 网络参数设置 input_neurons 2; % 输入层神经元数 hidden_neurons 3; % 隐藏层神经元数 output_neurons 1; % 输出层神经元数 learning_rate 0.1; % 学习率 epochs 10000; % 迭代次数%% 权重初始化(He初始化…

作者头像 李华
网站建设 2026/8/26 2:47:27

Java分布式系统开发与实践!

我们都知道,目前大型网站跟企业级应用目前的要求都是达到“互联网三高”,这时传统的集中式系统肯定是无法满足基本的需求的,越来越多的企业的系统架构目前都是向着分布式系统的方向演进。分布式系统的特征分布式系统相对于传统的集中式系统来…

作者头像 李华
网站建设 2026/9/1 4:03:54

灵活就业简历制作难?项目导向模板下载,HR一眼认可

不同求职场景,简历误区各不相同?校招应届生分不清实习和校招简历重点,要么堆砌校园经历,要么遗漏实习成果;跨行业转行想突破壁垒,却不会衔接过往经历、突出可迁移技能;职场深耕3-5年&#xff0c…

作者头像 李华
网站建设 2026/8/23 5:32:00

利用Multisite实现WordPress多语言网站

利用WordPress Multisite(多站点)实现多语言网站,核心是将每种语言对应为一个独立子站点,通过统一的网络管理实现多语言布局,同时兼顾站点隔离性与基础的语言互通性。以下是完整、可落地的实操步骤,从开启多站点到SEO优化、功能增…

作者头像 李华