YOLOv11改进SPASPP:用空洞空间金字塔池化替换SPPF,专治红外小目标检测

发布时间:2026/10/17 11:25:18

YOLOv11改进SPASPP:用空洞空间金字塔池化替换SPPF,专治红外小目标检测 YOLOv11出来有一阵子了社区里各种“涨点”方案也出了不少但绝大多数都是在注意力机制或者检测头上做文章真正针对Backbone特征提取层动手的反而少。这阵子我在做红外场景下的目标检测被小目标问题折磨得不轻正好看到TCSV 2025这篇关于SPASPP的工作思路是把空洞空间金字塔池化引入到YOLOv11的SPPF模块里替代原来的池化结构专治红外小目标特征丢失。实测下来对低信噪比、小尺寸目标的效果确实有肉眼可见的提升写篇文章把这套方案的原理、代码和踩坑记录完整梳理一遍。先说结论如果你手头是遥感、无人机、夜视这类图像目标动不动就十几个像素甚至几个像素那这个改动值得一试。如果你做的是常规自然场景数据集目标尺寸普遍在几十像素以上这玩意儿带来的提升可能没那么明显。我个人的建议是先看你的数据分布再决定要不要动这个模块别盲目往上叠。1. 为什么动手改SPPF红外小目标的三个“死穴”1.1 小目标到底小在哪红外小目标和高分辨率自然图像里的目标完全不是一回事。拿我自己跑的数据集来说一张640x640的红外图像里车辆目标经常只有8x8到20x20像素行人更是夸张有的甚至只有4x6像素。这种尺寸在整张图里占比不到0.1%你用肉眼去看原图都很难一眼找出来。小目标在特征提取网络里的命运是相当悲惨的。一个输入图像经过Backbone的几次下采样之后分辨率从640x640逐步降到80x80、40x40、20x20。原图上12x12像素的目标到20x20的特征图上就只剩不到1个像素了基本信息全丢光。所以说到底小目标检测的核心矛盾就是特征图分辨率有限目标信号在下采样过程中被稀释了。常规做法是引入P2层也就是把Backbone浅层的高分辨率特征往检测头上引这种方法对小目标确实有效但治标不治本。因为浅层特征虽然分辨率高语义信息却不够丰富目标特征和背景杂波的区分度不高。更深层的问题是网络在下采样之后如何从低分辨率特征里保留住小目标的响应这才是SPPF这类多尺度模块真正要解决的。1.2 SPPF的“三连池化”在干什么老玩家都知道YOLO系列从v5开始就引入了SPPF模块v8、v11沿用了这个结构。它的逻辑很直接用一个5x5的MaxPooling连着跑三次每次池化结果都保留最后把所有分支拼起来再卷积融合。这样一次前向就能拿到三种不同感受野的特征多尺度信息一次集齐。很多人可能没仔细算过这三连池化对应的感受野。5x5的池化核、stride1、padding2第一次池化后每个输出点感知的是输入上5x5的区域。第二次池化串行叠加每个输出点能看到第一次池化结果里5x5的范围对应回原图就是9x9的有效区域。第三次再叠一层就是13x13。所以SPPF实际提供的是5x5、9x9、13x13三档感受野的并行特征。问题就出在这个“池化”上。MaxPooling是无参数的固定操作它只保留窗口里的最大值其他信息一律丢掉。对自然图像里的大目标来说这个操作没什么问题但红外小目标信号弱、信噪比低目标像素可能只比背景亮一点点。在一个5x5的池化窗口里如果背景杂波的极值比目标信号还强MaxPooling就会把目标响应直接滤掉。1.3 改进的核心方向所以我对SPPF的改造思路就很明确了能不能把无参数、不可学习的MaxPooling替换成可学习的卷积操作让网络自己去决定该保留哪些尺度的特征这就是SPASPP的出发点。这个模块借鉴了语义分割领域经典的空洞空间金字塔池化ASPP在YOLOv11的SPPF位置引入多路空洞卷积来做多尺度特征提取。空洞卷积在不增加参数量的情况下可以扩大感受野而且卷积核是有参数的能够根据训练数据自适应地学会“什么样的目标响应需要保留”这是池化操作做不到的。我实际改完之后感受到的一个明显差别是原版SPPF在低对比度小目标上的响应经常和背景杂波混在一起而SPASPP的分支能够更好地把目标边缘和背景区分开。尤其是那种轮廓模糊、对比度低的红外目标改进后的特征图在视觉上清晰度更高漏检率明显下降。2. 空洞卷积与SPASPP先说原理再写代码2.1 空洞卷积的等效感受野计算空洞卷积说白了就是在卷积核的元素之间插入空洞让同样大小的卷积核能够覆盖更大的输入区域。比如一个3x3的卷积核空洞率为1就是普通卷积空洞率为2卷积核在水平方向和垂直方向就各多了一个空洞等效覆盖范围变成5x5空洞率为3等效覆盖范围变成7x7。等效感受野有固定的计算公式等效感受野 卷积核大小 (空洞率 - 1) * (卷积核大小 - 1)。以3x3卷积核为例空洞率为1时感受野是3 0 3空洞率为2时是3 12 5空洞率为3时是3 22 7。这个特性用在多尺度特征提取上就非常方便。我可以用三个不同空洞率的3x3空洞卷积并行抽取特征不需要池化也不用增大卷积核。三个分支分别覆盖3x3、7x7、11x11的感受野效果上和SPPF的5x5、9x9、13x13三档很接近但每个分支都带可学习的权重。注意空洞卷积的计算量和普通卷积完全一样因为FLOPs只跟输入尺寸、输出通道数和卷积核大小有关和空洞率没有直接关系。这意味着SPASPP可以在不显著增加算力的情况下扩大感受野范围。2.2 SPASPP的分支设计结构把SPPF的池化分支替换成空洞卷积分支后模块结构大体是输入特征先经过一个1x1卷积降维然后分成三到四个并行分支每个分支用不同空洞率的3x3空洞卷积提取特征再经过1x1卷积压缩通道数最后把各分支结果在通道维度上拼起来过一层1x1卷积融合输出。这里有个关键点分支内部的空洞卷积虽然感受野大但参数量和3x3普通卷积没区别。为了进一步控制计算量每个分支在空洞卷积后面还会接一个1x1卷积把通道数降下来四个分支拼起来之后再做一次通道融合输出通道数和原SPPF保持一致这样下游的检测头就不用改了。我试过几种不同的分支组合。最简单的版本是三个分支空洞率分别取1、3、5四分支版本多一路空洞率7的但实测下来最后一档带来的增益不大反而多了一些计算量。如果你的输入分辨率比较高或者目标相对还比较大四分支版本可能有点用对于典型红外小目标场景三分支版本是最稳的折中。2.3 为什么不能直接搬原版ASPP看到SPASPP这个名字熟悉分割网络的应该马上想到ASPP。但直接照搬ASPP进YOLOv11是会有问题的市面上很多所谓的“涨点改进”就是无脑把分割网络模块套进检测网络效果说不上好。原版ASPP的设计目标是为语义分割服务的它通常在Backbone最深层使用分支数和空洞率都比较激进比如常见的6、12、18这种大空洞率。这些大空洞率在分割任务里能获得超大感受野帮助区分不同类别的上下文信息但在目标检测场景里反而会造成严重的网格效应空洞卷积的采样点过于稀疏特征图上会形成棋盘格状的盲区小目标信息恰好落在盲区里就直接丢了。SPASPP和ASPP的区别就是把空洞率压到1、3、5这个温和区间保持足够的感受野覆盖同时避免采样点过于稀疏。另外它保留了SPPF的“先降维再融合”的通道结构让模块插入YOLOv11的Backbone之后不需要调整后续层的通道数工程接入成本很低。3. 代码实现从SPPF迁到SPASPP3.1 PyTorch实现我自己用的是PyTorch版本的YOLOv11代码库改动分成两个部分先在模型定义文件一般是common.py或者modules.py里加上SPASPP类然后在配置文件yaml里把原来的SPPF替换掉。SPASPP的PyTorch实现可以直接参考下面这段我加了一些注释方便修改import torch import torch.nn as nn class Conv(nn.Module): # 简化的标准卷积BN激活 def __init__(self, c1, c2, k1, s1, pNone, g1, actTrue): super().__init__() self.conv nn.Conv2d(c1, c2, k, s, p if p is not None else k // 2, groupsg, biasFalse) self.bn nn.BatchNorm2d(c2) self.act nn.SiLU() if act else nn.Identity() def forward(self, x): return self.act(self.bn(self.conv(x))) class SPASPP(nn.Module): def __init__(self, c1, c2, rates(1, 3, 5), mid_chNone): super().__init__() mid mid_ch if mid_ch is not None else c1 // 4 # 每个分支的输出通道为 mid最后一层 1x1 卷积融合回 c2 self.cv1 Conv(c1, mid, 1) self.branches nn.ModuleList() for r in rates: self.branches.append(nn.Sequential( Conv(mid, mid, 3, pr, actTrue), # 这里直接设置 padding 空洞率 Conv(mid, mid, 1, actTrue) )) self.cv2 Conv(mid * len(rates), c2, 1) def forward(self, x): x self.cv1(x) outs [branch(x) for branch in self.branches] return self.cv2(torch.cat(outs, dim1))如果你用的是集成了SPPF的完整代码库直接把这个类定义加进去就行。关键点在于空洞卷积的padding要等于空洞率否则输出尺寸会对不上。上面这段代码里我用Conv的自定义逻辑传pr就等同于paddingdilation。3.2 修改YOLOv11的配置文件接下来打开YOLOv11的模型配置文件找到Backbone里SPPF那一层把它替换成SPASPP。举个例子假设原来的配置片段是backbone: - [-1, 1, Conv, [256, 3, 2]] - [-1, 1, SPPF, [512, 5]]改成backbone: - [-1, 1, Conv, [256, 3, 2]] - [-1, 1, SPASPP, [512, [1, 3, 5]]]注意YOLOv11在解析yaml文件的时候是根据类名在common.py里查找的所以你在common.py里定义SPASPP之后yaml里的模块名必须和类名完全一致。配置文件里的[512, [1, 3, 5]]对应SPASPP的c2参数传入512、rates参数传入[1, 3, 5]。改完配置之后先别急着跑先做一步预检用一个小张的假特征图过一遍模型确认输出张量的空间尺寸和通道数没变。我自己第一次改的时候就因为分支里padding设置错误导致后续层尺寸对不上直接报错。3.3 参数量和计算量对比把SPPF换成SPASPP最关心的问题肯定是模型变大了多少推理速度掉了多少我这里以YOLOv11n的配置为例把两个模块做了一组粗略对比。SPPF的流程是1x1卷积降维到一半通道三路MaxPooling得到四路特征拼接最后再1x1卷积融合回原通道。SPASPP的流程是1x1卷积降维到四分之一通道三路空洞卷积1x1卷积分别处理拼接后1x1卷积融合回原通道。参数量的增加主要来自空洞卷积后面的1x1卷积以及融合卷积的输入通道变成三倍。以Backbone末端512通道的特征为例SPASPP大约增加0.5到0.7M的参数量FLOPs增加大约15%到20%。这个增量对GPU训练来说没有压力但如果你要做边缘设备部署就需要在速度和精度之间权衡。模块参数量相对FLOPs相对感受野档位可学习参数SPPF1.0x1.0x5x5 / 9x9 / 13x13仅降维和融合卷积SPASPP三路约1.3x约1.2x3x3 / 7x7 / 11x11所有分支卷积均可学习关于FLOPs这块我实测下来如果是在GPU上训练整体训练时间增加在5%到10%区间感知不明显。但在推理端尤其转成TensorRT之后延迟增加会更明显一点后面我会专门讲转换部署时遇到的问题。4. 训练细节与实验结果分析4.1 红外数据集与训练方案这套改进的目标场景是红外小目标检测所以我用了一个自建的红外场景数据集来做对比实验。数据来源是车载红外相机在不同时段和天气条件下拍摄的夜间场景包含行人、车辆、骑行人员三类目标。数据集经过清洗后训练集5100张、验证集920张图像尺寸统一缩放到640x640分辨率。这个数据集的难点在目标尺寸分布上。我统计了一下标注框的像素面积超过60%的目标边界框面积在6x6到32x32像素之间最小的甚至只有4x5像素。背景也不干净道路边缘、建筑窗户、树枝都会产生高亮杂波信噪比很低。训练参数我是这样设置的输入分辨率640x640batch size 32SGD优化器初始学习率0.01余弦退火调度动量0.937权重衰减5e-4。训练300个epoch前3个epoch用warmup。数据增强方面我刻意把Mosaic的概率调低了从默认的1.0降到0.5因为Mosaic拼接会进一步把目标缩小对小目标检测是不利因素。4.2 关键指标对比我在同一个数据集上用原版和SPASPP版本各跑了三组实验取均值做对比。这里的mAP50和mAP50-95都是常规COCO评测协议额外统计了小目标子集的mAP作为参考。模型版本参数量mAP50mAP50-95小目标子集mAPYOLOv11n 原版2.6M74.344.131.2YOLOv11n SPASPP3.3M77.847.936.5YOLOv11s 原版9.4M79.548.737.0YOLOv11s SPASPP10.2M82.451.841.3从表格里可以清楚看到SPASPP对小目标子集的mAP提升最明显n版本提升了5.3个百分点s版本提升了4.3个百分点。全量mAP50也涨了3个点左右。在参数量只增加不到1M的情况下这个收益我认为是比较值的。还有一点值得注意SPASPP版本在mAP50-95上的涨幅比mAP50更大。这说明改进后的模型不仅能检测到目标而且定位框的质量也更好。我猜原因是空洞卷积分支保留了更多目标轮廓信息让回归头能够更准确地拟合目标边界。4.3 什么场景收益大什么场景收益小为了让结论更有参考价值我还跑了两个对照组。第一组是常规自然场景数据集包含行人、车辆、动物等目标尺寸普遍在50像素以上。第二组是纯天空背景的红外小目标序列背景干净、目标大且对比度高。第一组的结果让我有点意外SPASPP版本的mAP提升只有0.4个百分点基本接近噪声水平。这说明大目标本身就不缺特征信息多尺度的空洞卷积提供不了额外收益。第二组的提升有1.8个百分点比大目标场景好一些但远不如复杂背景的红外场景。真正让SPASPP发挥价值的是复杂背景、低信噪比的红外小目标场景。目标的信号弱、背景干扰强这个时候空洞卷积带来的多尺度上下文信息和可学习权重能让网络更好地“抠”出目标特征。反过来想如果你的数据集背景干净、目标尺寸大那完全可以不用做这个改动白增加计算量。5. 常见问题与避坑指南5.1 空洞率怎么选很多人第一次用空洞卷积都会有一个误区空洞率越大感受野越大效果不就越好吗我一开始也试过用(1, 6, 12)这种激进配置结果小目标检测指标反而比原版还差了。问题出在网格效应。空洞率过大的时候卷积核的采样点之间间隔太远特征图上会留下大量没有覆盖到的盲区。如果一个小目标的特征恰好落在盲区里这个分支就完全感知不到它多尺度融合的时候反而引入噪声。我实测下来的安全区间是空洞率不超过51、3、5这组组合是最稳的。如果你的输入分辨率比较高比如1280x1280甚至更高可以适当把空洞率加到1、3、7。因为分辨率越高同样空洞率对应的实际尺度变化越小需要更大的空洞率来覆盖多尺度范围。5.2 小目标尺寸和P2层的关系替换完SPASPP之后如果你发现小目标检测效果还是不够理想那问题大概率不在Backbone而在检测头的特征层级上。YOLOv11的检测头通常从P3、P4、P5三层特征图做检测对应输入图像下采样8倍、16倍、32倍。对红外小目标来说P3层下采样8倍的特征图是主力。8x8的像素目标在P3层上只剩下1x1个像素响应这基本上已经到极限了。如果你的数据集里大量目标都是10像素以下建议再加一层P2特征图对应下采样4倍。P2层能保留更多空间细节配合SPASPP的多尺度语义特征效果会更好。但要注意P2层会引入比较大的计算量和显存开销而且P2层的语义信息少容易带来大量误检。我的建议是先用SPASPP看基线效果如果小目标漏检有明显改善但还不够再决定是否加P2。5.3 转ONNX和TensorRT时的问题模型搞完之后如果要部署转ONNX和TensorRT的过程中有几个坑。首先是空洞卷积在ONNX导出时paddingdilation的配置会被展开成多个显式的pad节点模型结构会变得比较复杂。用onnx-simplifier处理一下可以优化掉一部分冗余节点。然后是TensorRT对空洞卷积的支持。我用的TensorRT版本对空洞卷积算子是支持的但不同版本的推理速度差别比较大。我在实测中发现FP16精度下性能挺好但模型转换时第一步是用onnx2trt还是用trtexec会有差别有时候需要手动加--fp16参数才能启用半精度加速。还有一点容易被忽略SPASPP增加了分支数量TensorRT在做层融合的时候可能需要更长的构建时间。我第一次构建engine的时候还以为程序卡死了实际是构建时间比原版长了差不多3倍。建议转换的时候耐心等不要中途强杀进程。5.4 训练loss不稳定怎么排查如果你替换模块之后遇到loss不下降或者训练震荡的问题大概率出在两个地方。第一个是BN层的统计量问题。SPASPP有三个并行分支每个分支都带BatchNorm如果你的batch size比较小比如8以下BN统计量的噪声会很大导致训练不稳定。这种情况建议用SyncBatchNorm或者把batch size适当调大。第二个是学习率问题。加了新模块后模型的收敛特性会发生变化原来的学习率可能不再合适。我遇到过类似的情况把初始学习率从0.01降到0.001之后问题就解决了。经验是新增模块尤其是带大量新卷积的模块时用小一点的学习率起步更稳。最后再补充一个教训空洞卷积分支多如果某个分支的初始权重导致输出分布异常可能拖慢整体收敛速度。建议你在训练前先跑几个iter对比一下原版和SPASPP版本的loss初始值。如果初始loss差很多可以尝试调整分支内的通道数或者换用不同的初始化方式。我自己用Kaiming初始化跑通之后就没有再调整过这块但不同数据分布下还是值得检查一下。
延伸阅读

更多相关文章

2026/10/17 11:20:18

Spring Boot毕业设计选题:公务员考试知识共享平台完整实现指南

每年到了毕业设计选题季,后台私信里问得最多的一类问题就是:Spring Boot有什么项目好做?最好是那种功能不难、工作量够、技术点耳熟能详,但又不至于烂大街到答辩时被老师一眼看穿的题目。“Spring Boot公务员考试知识共享平台”就…

2026/10/17 11:20:18

人工智能模型组备赛全流程指南:从微调训练到推理加速

模型组备赛这些年越来越卷,但很多人一开始根本不知道“模型组要干什么”。刷榜刷数据、跑分调参、熬夜等训练日志……如果你准备参加人工智能模型组比赛,这篇内容把从选赛道到最终提交的全过程拆给你看,包括硬件准备、数据清洗、基线选型、微…

2026/10/17 12:45:24

在HTML页面嵌入Excel在线编辑:从渲染到存回xlsx的完整实现

简介:这份资源面向需要在网页端实现表格在线编辑的前端开发者与企业应用团队,围绕HTML页面集成Excel编辑能力这一常见需求,提供可运行的示例工程与配套实现思路。压缩包共41个文件,约1.44MB,以css样式表、js脚本、png图…

2026/10/17 12:45:24

矩阵置零原地算法:从暴力解到O(1)复杂度的完整推导

刷算法题的人应该都遇到过这样一道“看起来简单,写起来全是坑”的矩阵题:给定一个 mn 的矩阵,一旦发现某个元素等于 0,就要把它所在的整行和整列全部变成 0。题目编号 73,通常被叫做“矩阵置零”。第一眼看到时你会觉得…

2026/10/17 12:45:24

Linux内核内存泄漏排查:从free告警到meminfo与slabinfo实战

1. 从一次线上告警说起:为什么free内存充足却频繁OOM凌晨两点被电话叫醒,监控面板上free -m显示还有3个G的可用内存,但业务进程已经被内核OOM Killer干掉了。这种"内存明明够用却报内存不足"的场景,做过几年运维或后端开…

2026/10/17 12:45:24

WSL2下安装配置Claude Code实战:从零到稳定使用的完整指南

先说结论:如果你手头有一台Windows电脑,日常又要在Linux环境里写代码、跑脚本、对接服务器,那在WSL2里装Claude Code基本是当前体验最好的组合之一。这篇文章不是官网文档的复读,是我把WSL2环境从零搭到Claude Code能日常稳定使用…

2026/10/17 12:45:24

Git仓库批量镜像下载器:备份、迁移与增量同步实践

简介:围绕“repository下载”场景整理的离线依赖资源包,主要面向Java开发者、Maven使用者,以及需要搭建本地或内网依赖仓库的团队。压缩包为rar格式,共收录2000个文件,包体约324MB,核心内容以jar依赖包、po…

2026/10/17 12:40:24

PyCharm 接入 DeepSeek:用 Continue 插件实现 AI 代码补全与对话调试

1. 为什么要在 PyCharm 里接入 DeepSeek1.1 从“写代码”到“聊代码”的转变我用了七八年 PyCharm,从最早的社区版一路用到专业版,说实话,真正让我觉得“回不去”的,不是某个重构功能,而是把大模型接进 IDE 之后的那种…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/17 0:04:32

PlanarSLAM:面向曼哈顿世界的点线面联合SLAM系统

简介:本资源是面向机器人视觉与SLAM研究者的C开源RGB-D SLAM系统实现,专为结构化室内场景(如办公室、走廊)设计,通过融合点、线、平面三类几何特征并引入“曼哈顿世界”假设,显著提升位姿跟踪鲁棒性与稠密地…

2026/10/17 0:04:32

TDH Workflow调度实战:从DAG依赖驱动到任务编排与故障排查

1. 从一个调度脚本说起:TDH Workflow到底在解决什么问题第一次接触TDH的Workflow,是在一个数据清洗项目里。当时团队每天要跑几十个ETL任务,任务之间有严格的先后依赖——A表清洗完才能跑B表的关联,B表跑完才能触发C表的聚合。最开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑