前言
本文介绍了可编程梯度信息(PGI)和通用高效层聚合网络(GELAN),以及SPPELAN模块在YOLO26中的结合应用。针对深度网络数据传输中的信息丢失问题,提出PGI概念以提供完整输入信息计算目标函数,获得可靠梯度更新网络权重;并基于梯度路径规划设计了GELAN架构。我们将SPPELAN模块集成进YOLO26,在MS COCO目标检测任务中,GELAN展现出更好的参数利用率,PGI使模型表现优于预训练的最新模型,改进后的YOLO26也取得了良好实验结果。
文章目录: YOLO26改进大全:卷积层、轻量化、注意力机制、损失函数、Backbone、SPPF、Neck、检测头全方位优化汇总
专栏链接: YOLO26改进专栏
文章目录
- 前言
- 介绍
- 摘要
- 文章链接
- 核心代码
- YOLO26引入代码
- tasks注册
- 步骤1:
- 步骤2
- 配置yolo26-SPPELAN.yaml
- 实验
- 脚本
- 结果
介绍
摘要
当前深度学习研究主要聚焦于优化目标函数设计,旨在使模型预测结果最大程度逼近真实标注值(ground truth),同时需要构建合适的网络架构以确保预测过程中获取充分的信息支持。然而,现有研究方法普遍忽视了一个关键现象:输入数据在经历逐层特征提取与空间变换过程中会产生显著的信息丢失。本文系统性地探讨了深度网络中数据传递过程中出现的信息损失问题,特别是信息瓶颈与可逆函数相关的理论机制。为此,我们提出了**可编程梯度信息(Programmable Gradient Information, PGI)**的创新概念,该概念能够有效应对深度网络为实现多样化目标任务所需的各种变换需求。PGI机制可为特定目标任务提供完整的输入信息用于目标函数计算,从而获得可靠的梯度信息以优化网络权重更新过程。基于梯度路径规划策略,我们进一步设计了一种新型轻量级网络架构——通用高效层聚合网络(Generalized Efficient Layer Aggregation Network, GELAN),该架构的实验结果验证了PGI在轻量级模型中取得的卓越性能。在MS COCO数据集的目标检测任务中,我们对提出的GELAN与PGI进行了全面验证。实验结果表明,GELAN仅采用常规卷积算子即可实现比基于深度卷积(depth-wise convolution)的先进方法更优的参数利用效率。PGI技术展现出良好的通用性,适用于从轻量级到大规模的各种模型架构,能够有效获取完整信息,使得从零开始训练的模型性能超越基于大规模数据集预训练的先进模型,具体性能对比详见实验结果图示。相关源代码已公开于:https://github.com/WongKinYiu/yolov9。
文章链接
论文地址:论文地址
代码地址:代码地址
核心代码
classSPPELAN(nn.Module):# spp-elandef__init__(self,c1,c2,c3):# ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()self.c=c3 self.cv1=Conv(c1,c3,1,1)self.cv2=SP(5)self.cv3=SP(5)self.cv4=SP(5)self.cv5=Conv(4*c3,c2,1,1)defforward(self,x):y=[self.cv1(x)]y.extend(m(y[-1])formin[self.cv2,self.cv3,self.cv4])returnself.cv5(torch.cat(y,1))YOLO26引入代码
在根目录下的ultralytics/nn/目录,新建一个otherModules目录,然后新建一个以SPPELAN为文件名的py文件, 把代码拷贝进去。
importtorchimporttorch.nnasnndefautopad(k,p=None,d=1):# kernel, padding, dilation"""Pad to 'same' shape outputs."""ifd>1:k=d*(k-1)+1ifisinstance(k,int)else[d*(x-1)+1forxink]# actual kernel-sizeifpisNone:p=k//2ifisinstance(k,int)else[x//2forxink]# auto-padreturnpclassConv(nn.Module):"""Standard convolution with args(ch_in, ch_out, kernel, stride, padding, groups, dilation, activation)."""default_act=nn.SiLU()# default activationdef__init__(self,c1,c2,k=1,s=1,p=None,g=1,d=1,act=True):"""Initialize Conv layer with given arguments including activation."""super().__init__()self.conv=nn.Conv2d(c1,c2,k,s,autopad(k,p,d),groups=g,dilation=d,bias=False)self.bn=nn.BatchNorm2d(c2)self.act=self.default_actifactisTrueelseactifisinstance(act,nn.Module)elsenn.Identity()defforward(self,x):"""Apply convolution, batch normalization and activation to input tensor."""returnself.act(self.bn(self.conv(x)))defforward_fuse(self,x):"""Perform transposed convolution of 2D data."""returnself.act(self.conv(x))classSP(nn.Module):def__init__(self,k=3,s=1):super(SP,self).__init__()self.m=nn.MaxPool2d(kernel_size=k,stride=s,padding=k//2)defforward(self,x):returnself.m(x)classSPPELAN(nn.Module):# spp-elandef__init__(self,c1,c2,c3):# ch_in, ch_out, number, shortcut, groups, expansionsuper().__init__()self.c=c3 self.cv1=Conv(c1,c3,1,1)self.cv2=SP(5)self.cv3=SP(5)self.cv4=SP(5)self.cv5=Conv(4*c3,c2,1,1)defforward(self,x):y=[self.cv1(x)]y.extend(m(y[-1])formin[self.cv2,self.cv3,self.cv4])returnself.cv5(torch.cat(y,1))tasks注册
在ultralytics/nn/tasks.py中进行如下操作:
步骤1:
fromultralytics.nn.otherModules.SPPELANimportSPPELAN步骤2
修改def parse_model(d, ch, verbose=True):
SPPELAN配置yolo26-SPPELAN.yaml
ultralytics/cfg/models/26/yolo26-SPPELAN.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,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,SPPELAN,[1024,5]]# 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-SPPELAN.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-SPPELAN',)