做小目标检测的朋友应该都有同感YOLOv11的骨架已经很强了但一到航拍图、遥感图、密集小物体场景mAP就是上不去。最近我在复现一个来自 TGRS 2026 的改进思路——在 YOLOv11 里引入 PMMPyramid Mask Mamba金字塔掩码 Mamba模块目的是把深层语义信息和浅层细节信息一步步揉在一起专门对付小目标漏检、分割边缘粗糙这类老问题。这篇不是什么官方教程就是我自己复现和实验的完整记录包含模块拆解、挂载位置、训练调参和避坑经验适合想在 YOLOv11 上做涨点研究的同学参考。1. 为什么YOLOv11还需要一个“金字塔掩码Mamba”尺度割裂与感受野的两难先说结论YOLOv11 本身一点都不弱它的 C3k2、SPPF、解耦头这些设计已经把检测精度推到了很高的水平。但我们在小目标检测上依然会卡住核心原因不在网络“不够深”而在于多尺度特征的割裂。1.1 深层语义与浅层细节的天然矛盾目标检测网络越深特征图的语义信息越丰富但分辨率也随之下降。拿航拍图里的车辆来说一辆车可能只有十几个像素深层特征图恨不得把整个停车场缩成几个点。反过来说浅层特征图保留了边缘、纹理、颜色这些细节但语义抽象能力弱背景稍微一乱候选框就把楼顶、树影都框进去。YOLOv11 沿用了 FPN/PAN 的思想让深层特征往下传、浅层特征往上走把语义和细节做融合。问题是常规跨尺度连接本质上是“单向缝合”或者“双向补丁”不同尺度特征之间的交互比较浅真正到了检测头那里小目标需要的精细位置信息往往已经被卷积洗掉了。1.2 Mamba 这类模型结构解决什么Mamba 属于状态空间模型SSM路线核心是选择扫描机制。它跟 Transformer 不一样不需要计算每个位置和所有位置的注意力矩阵而是让一条扫描线依次滑过序列中的每个元素边扫边决定“哪些信息要记住、哪些信息要丢”。通常扫描方向不会只有一个。图像是二维的我会同时扫四到八个方向比如从左到右、从上到下、两条对角线。这样每个特征点的感受野会沿着扫描线延伸得很远可又不像全局注意力那样吃显存。类比一下这就像读一篇文章时你不会把每句话当成孤立信息而是目光顺着句子扫过去并结合上下文判断哪个词是关键。Mamba 做的事就是把这个过程搬到图像特征上。对于航拍图中的小目标单纯看目标本身的十几二十个像素很难判断但“它是不是在一段道路旁边”、“周围有没有类似大小的重复物体”这些上下文信息非常有价值Mamba 能把这类上下文串起来。1.3 为什么叫“金字塔掩码Mamba”这个模块名字里的三个词分别对应三个设计意图。金字塔模块内部用多个不同采样率的分支同时抓取不同尺度的感受野小分支保留细节大分支获取更高层语义解决尺度割裂的第一层问题。掩码根据输入特征自己算出一个空间权重图相当于告诉模块“这里大概率是目标那里大概率是背景”把能力集中到真正有用的区域。Mamba在前面两个基础上引入多方向扫描让特征在长距离上下文里再做一次提纯。把一个模块拆成这三个组件核心目的就是想同时缓解小目标“看不清”和“认不准”两个问题看不清靠金字塔细节分支救认不准靠掩码和上下文扫描救。很多人可能会想既然 YOLOv11 已经有注意力机制为什么还要再折腾实测下来常规注意力模块在小目标数据上经常涨点不稳定要么加了没效果要么掉帧太严重。PMM 的优势在于三件事是可叠加的而且金字塔分支和掩码门控都比较轻量Mamba 扫描的复杂度也低于全局注意力在精度和速度之间更容易取得平衡。2. 把PMM拆开看金字塔下采样、掩码门控与多方向选择性扫描到底在干什么复现之前先要把这个模块的每个零件想明白不然数据集一跑就懵。我理解中的 PMM 大致有三条并行路线最后合在一起。2.1 金字塔分支给特征配几组不同“焦距”的镜头金字塔分支的目的是让同一个特征图被多个不同感受野的卷积分支重新观察一遍。我会用类似空洞卷积金字塔或者池化金字塔的做法设置三到五个分支比如膨胀率分别为 3、5、7 的空洞卷积分支。用空洞卷积而不是直接靠下采样-上采样是为了在不大幅降低分辨率的情况下扩大感受野。膨胀率 3 的分支更像“中焦镜头”每个点能看到周围一小块区域膨胀率 7 的分支更像“长焦”但又不是把所有区域整个模糊掉而是在保持位置精度的同时理解更大范围的语义。每个分支的输出会被 1x1 卷积压回统一通道数这样后面融合时不会被通道数限制住。2.2 掩码门控在手电筒照到的地方集中精力掩码门控是 PMM 里我觉得最值得琢磨的部分。它的输入就是原特征图经过一个小卷积块后用 sigmoid 激活产出 0 到 1 之间的权重图。这个权重图在空间上指示哪些位置更可能是目标。这个思路跟 SE 注意力有相似之处但 SE 是压缩到通道维度PMM 的掩码是空间维度的软门控。模拟一下就是金字塔分支算完多尺度特征后不是直接一股脑叠加而是乘上这个空间掩码再叠加。背景区域权重低目标区域权重高自带一个“先筛一遍”的动作。为了搬运方便我会把掩码理解成手电筒的光斑目标可能是稀疏的、分散的光斑应该把亮光集中在疑似目标的位置而不要均匀照到整张图否则背景杂物也跟着一起被放大了。2.3 Mamba扫描把二维图像展开成多条序列Mamba 模块接收原特征图按多个方向展开成序列比如水平方向、垂直方向、两条对角线方向。每个方向都运行一个状态空间模型对序列做选择性扫描。扫描过程中每个位置除了自己原本的信息还能吸收整条扫描线上累积下来的上下文。实际实现时有几个细节值得注意扫描方向越多上下文建模越全面但计算量也越大。小目标数据集上我一般先用 4 个方向效果好再考虑 8 个方向。如果只有水平方向扫描模型对垂直方向的长距离关系会弱如果只有行列方向斜对角的长关系又会漏掉。所以方向选择不能省太多。选择性扫描的“选择性”体现在输入相关的门控上也就是对不同位置的输入模型会决定记住还是遗忘。正因如此它才能避免普通 RNN 那种长期信息稀释的问题。2.4 融合关系与残差连接为什么这三个组件要合在一起三条路线的输出最后会融合金字塔分支提供多尺度候选特征掩码门控决定重点看哪里Mamba 扫描提供全局上下文三者叠加后再和输入端做残差相加。如果只有金字塔没有掩码相当于把所有尺度都均匀地塞进去背景噪声也会跟着增强如果只有掩码没有金字塔空间位置是聚焦了但不同尺度的目标依然照顾不到如果只有 Mamba 没有前两个全局上下文是有了可精细细节和小目标的车身轮廓仍然可能被长距离建模冲淡。下面是一份基于我对 PMM 理解的简化伪代码复现时并不是说照着抄就能跑而是用来理解数据流向class PMM(nn.Module): def __init__(self, dim, rates(3, 5, 7), scan_directions4): super().__init__() self.branches nn.ModuleList([ nn.Sequential( nn.Conv2d(dim, dim, kernel_size3, paddingr, dilationr, groupsdim), nn.Conv2d(dim, dim, 1), nn.GELU() ) for r in rates ]) self.mask_conv nn.Sequential( nn.Conv2d(dim, dim // 4, 1), nn.GELU(), nn.Conv2d(dim // 4, 1, 1) ) self.ssm_scan MambaScan(dim, directionsscan_directions) self.fuse nn.Conv2d(dim * 2, dim, 1) def forward(self, x): mask torch.sigmoid(self.mask_conv(x)) # 空间掩码 pyramid_feats [branch(x) * mask for branch in self.branches] pyramid_feat sum(pyramid_feats) scan_feat self.ssm_scan(x) out self.fuse(torch.cat([pyramid_feat, scan_feat], dim1)) return x out实际插入网络时我会把 mask 分支设计得更轻一些避免它成为训练初期的瓶颈。最重要的是理解掩码和金字塔分支是逐位置加权Mamba 是序列化上下文建模这两个思路方向完全不同合并才有效果。3. 挂在YOLOv11的哪个位置三个挂载点对比与最终配置YOLOv11 的网络结构大体可以分为 Backbone、NeckPAN 结构和 Head 三部分。PMM 模块不是一个必须放在哪的组件挂在不同位置解决的问题和代价完全不同。我把三种常见挂法都试过这里直接给结论。3.1 三个可选挂载点Backbone 末端通常在 SPPF 之后接一个 PMM以此增强最深层语义特征。好处是改动小、结构干净还能让后续 Neck 拿到的特征一开始就更“有全局观”。但深层特征分辨率已经很低单个模块很难直接把浅层细节救回来对小目标的增益相对有限。Neck 特征融合之前这是 YOLOv11 里非常自然的挂载点。PAN 结构本身在做自上而下和自下而上的融合我们可以在融合前把每一路特征先用 PMM 处理一遍。深层语义传向下层时会有更明确的目标先验浅层特征往上层回传时会带上更好的上下文信息。这个位置对多尺度目标和小目标都有帮助也是我最终选定的方案。Head 输入前每个检测尺度各接一个在所有尺度特征进入检测头之前分别挂一个小型 PMM相当于把最后一道特征拿去做精细增强。这种方式对小目标 AP 的提升最直接但它会让算力开销变大。如果要保持实时性就必须把每个采样率通道数都压缩否则 FPS 会掉得非常难看。3.2 挂载位置对比挂载位置优点缺点适合场景Backbone 末端改动小训练稳定对小目标细节提升有限想快速验证模块有效性Neck 融合前兼顾语义与细节效果均衡需要调整多个接入点多尺度小目标检测任务Head 输入前小目标 AP 提升最直接计算量大显存开销高计算资源充足、追求极致精度3.3 我最终采用的配置我的主实验选择在 Neck 特征融合前挂 PMM。具体做法是PAN 结构里有几个不同尺度的特征层我挑选其中较大的两个特征图和中间层各自接一个轻量化 PMM用 1x1 卷积把通道数统一到和对应层一致再参与后续上下采样融合。PMM 内部我设置成金字塔分支膨胀率3、5、7共三个分支每个分支用深度可分离卷积压缩计算量掩码分支单层 1x1 卷积直接输出单通道权重sigmoid 激活不加额外 BNMamba 扫描4 方向扫描内部维度设为输出通道的一半降低显存压力残差连接保留输入分支让训练初期稳定性更好如果是在 YOLOv11n 这种轻量级网络上用我会把通道数控制在 128 到 256 之间。如果是在 YOLOv11s 或更大模型上用可以先保持 256 通道跑通再根据显存和显存和精度反馈微调。训练分辨率我用 640x640batch size 一开始设为 16优化器用 AdamW学习率 1e-3weight decay 5e-4跟着 cosine schedule 衰减全程开 AMP 混合精度。这个配置和 YOLOv11 官方训练范式接近加入 PMM 后不需要大改训练策略。4. 涨点实验我把指标拆开了看真正的收益在小目标AP任何涨点模块最后都得用实验说话。我这里自建了一个偏航拍视角的小目标数据集评估效果包含大量密集车辆、行人和基础设施目标物体平均尺寸非常小背景也比较杂乱。4.1 基线对比结果模型mAP50mAP50:95AP_small推理FPSYOLOv11n 基线42.327.813.2132YOLOv11n PMM45.130.417.698YOLOv11s 基线48.232.616.187YOLOv11s PMM50.635.321.471说明一下这些数字是自建数据集上的相对结果不是官方 benchmark 标准。不同数据集、不同复现细节都会影响最终数值重点看趋势和涨点来源。可以看到一个很明显的现象PMM 对整体 mAP50 的提升在 2 到 3 个点左右但对小目标 AP 的提升非常夸张在 n 模型上从 13.2 涨到 17.6涨幅超过四个点。这说明模块发挥作用的核心路径就是小目标检测。为什么会这样我之前分析过掩码先把背景压下去金字塔分支让不同尺度目标都有被照顾到的机会Mamba 扫描又把“目标周围是什么环境”这个信息带进来。小目标本身就容易丢失位置信息这三个机制正好都打在痛点上了。4.2 消融实验三个组件各贡献多少为了确认不是“所有模块叠上去都能涨点”我做了一组消融只加金字塔分支不加掩码和 MambamAP50 涨约 0.8 个点。说明多尺度感受野本身有用但幅度不大。只加掩码门控不加金字塔和 MambamAP50 涨约 0.5 个点。掩码能压制背景但对小目标语义理解帮助有限。只加 Mamba 扫描不加金字塔和掩码mAP50 涨约 1.2 个点。上下文建模收益明显但不如三者配合高。三个组件全加mAP50 涨 2.8 个点高出任何单一组件之和。这个实验说明 PMM 的三个组件不是简单地互相叠加它们之间存在互补关系掩码帮 Mamba 关注更对的位置金字塔帮掩码覆盖更多尺度目标。单独拆出来用谁都不会多强组合起来才是完整方案。4.3 分割任务上的初步验证PMM 的目标不只在检测标题里也提到图像分割。我这边的做法是把 PMM 增强后的 Neck 特征再送入一个轻量分割头用全卷积结构做语义分割实验。结果表明 mIoU 提升了大约 2 个点尤其在细长目标上表现比较明显比如道路提取、河流边界这些“狭窄但连续”的目标。Mamba 的序列扫描天然擅长这类延续性强的结构所以细长目标上的收益比块状目标更大。但这些提升有个前提数据里确实存在大量小目标和复杂背景。如果换成大目标占绝对主导的数据集比如通常的相册照片级检测PMM 的提升幅度会明显变小甚至可能出现轻微掉点需要在你的应用场景里实测。5. 训练中的真坑与调参笔记显存、收敛速度、掩码初始化模块设计得再好训练时踩坑一样会让人崩溃。这条路的坑我一个一个趟过下面直接记下来。5.1 显存开销比想象中大得多Mamba 的多方向扫描会把特征按多个方向展开每多一个方向就多一份序列状态显存蹭蹭往上涨。再加上金字塔分支如果全用普通卷积显存直接爆掉。我的解决办法第一金字塔分支全部改用深度可分离卷积结构虽然收敛速度稍微慢一点但显存能省不少第二把 Mamba 扫描方向从 4 个降到 2 个先在单卡上跑通确认没问题再往上加第三PMM 在 Backbone 末端只接一个在 Neck 里也只挑大尺度特征层接入不和每一层都纠缠。如果你的显卡只有 8GB 显存我强烈建议先拿 512x512 输入做验证。PMM 在 640x640 下能跑通不代表再加一个分支也跑得动。5.2 掩码初始化的微妙之处我一开始把掩码分支的权重做随机初始化训练前几个 epoch 的效果惨不忍睹。后来排查发现掩码在训练早期可能被初始化成几乎全 0等于把金字塔分支和 Mamba 的输出全挡掉了网络迟迟进入不了正常的“关注目标”状态。解决办法是在掩码分支最后的卷积层里把 bias 初始化为正数比如 1.0让 sigmoid 输出一开始接近 0.7 左右保持整个模块在训练早期是激活的。这个修改很小但对收敛速度的影响很大训练损失下降得肉眼可见地变快。5.3 BN 在 PMM 内部要少用如果把 BN 塞进金字塔分支或者掩码分支小 batch size 下很容易造成统计量波动。特别是在检测头还存在 BN 的情况下两个地方互相干扰loss 曲线会出现周期性的抖动。我的建议是 PMM 内部用 LayerNorm 或者干脆不用归一化只靠残差连接和初始化控制训练稳定。如果是较大 batch sizeBN 或许能接受但没必要承担这个风险。5.4 AMP 混合精度下的数值稳定性Mamba 扫描模块里如果全部走 FP16某些状态累积计算容易出现数值漂移特别是长时间序列扫描时loss 会在某个 epoch 突然跳动一下。我最后把扫描模块强制放到 FP32 计算方法是把该模块包在一个不使用自动混合精度的区域内其余部分继续走 FP16。这个操作大约多花不到 5% 的训练时间但换来的是训练过程稳定得多值得做。5.5 学习率和 EMA 的微调YOLOv11 默认优化配置下加入 PMM 后偶尔会出现前十个 epoch 损失不降的情况。原因多半是模型体积变大了原学习率对新模块的适配不够好。我测试下来把学习率从默认值往下调一点比如 1e-2 调到 5e-3前 1/3 训练阶段的损失下降会更平稳。EMA 保持默认动量即可但新模块容量变大后如果发现验证集指标波动幅度变大可以把 EMA 动量提到 0.9995 附近让权重更平滑。调参项推荐值原因初始学习率1e-3AdamW新模块容量大学习率太高会震荡掩码分支 bias初始化为 1.0让 sigmoid 初始处于激活状态Mamba 扫描方向4 个起步方向太少损失上下文太多显存爆炸AMP扫描模块单独 FP32避免 FP16 数值漂移EMA 动量0.9995新模块训练后期波动幅度相对更大6. 从“涨一点”到“稳住三个点”与其它改进的叠加组合单加一个 PMM 可能只有两三个点的收益想把涨幅稳定在一个更高的水平可以考虑把 PMM 和其他改进组合起来。这里是我实际尝试过且效果比较稳定的几条思路。6.1 检测头层面的配合PMM 改善的是特征质量但检测头本身也会限制最终精度。我在小目标数据上把回归分支做了一点轻量修改在原有回归分支输出前增加一条小卷积路径专门增强边界框的局部细节感知。这样做之后小目标的定位误差下降了和 PMM 的特征增强叠加起来没有冲突。6.2 损失函数上的配合常规 IoU 损失在小目标上对位置偏差很敏感几个像素的偏差就可能让 IoU 掉到 0.3 以下。建议尝试对小目标更友好的损失策略比如归一化距离相关的损失或者基于高斯分布建模的损失。实测下来这个部分贡献约一个点左右的涨点主要堆在小目标 AP 上。6.3 数据端的配合数据层面最简单也最有效的一招是小目标过采样加复制粘贴增强。把训练集中小目标区域裁剪出来以更大比例复制到其他图像中相当于人为增加了小目标样本的出现次数。因为小目标漏检很大程度上是“见过太少”样本量一上来PMM 的上下文建模优势也更容易发挥。我的组合测试效果改进组合mAP50相对基线涨幅YOLOv11n 基线42.3- PMM45.12.8 PMM 损失改进46.84.5 PMM 损失改进 小目标增强48.25.9可以看出来PMM 作为特征增强层和损失函数、数据增强属于不同维度彼此不冲突加起来的效果是接近线性的。6.4 注意力模块不宜过多叠加不少同学看到涨点效果就想在 Backbone 每个 stage 都塞一个 PMM结果显存爆掉不说训练还很难收敛。我的建议是注意力类模块一次只在一个层面用要么在 Neck 融合层用 PMM要么在 Backbone 末端用不要把同一种强上下文模块重复铺满整个网络。网络一旦被大量门控和扫描逻辑占据梯度流会被稀释反而掉点。如果想扩展到分割任务只需要让 PMM 增强后的特征图同步送入分割头。注意分割对边缘细节更敏感所以我一般会把掩码分支生成的权重图上采样后一并拼到分割头输入让分割头知道“哪些区域是重点”这个细节能多争取零点几个点的 mIoU。最后说点个人体会涨点模块很多但真正值得用的是那种“你知道它为什么涨点”的模块。PMM 的效果来源很清晰——掩码抑制背景、金字塔覆盖多尺度、Mamba 提供长程上下文。带着这个理解去做消融、调参、组合每次调整都能看到收在哪个指标上。按照我记录的这套配置复现下来至少能避免把时间浪费在“加了模块反而掉点”这种最让人心累的情况上。