ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

YOLOv26改进:恒等映射Token Mixer与归一化驱动的轻量化实践

YOLOv26改进:恒等映射Token Mixer与归一化驱动的轻量化实践

把骨干网络里最后几个 Bottleneck 换成恒等映射,检测精度不但没掉,反而涨了一个多点——这事我一开始是不信的。后来把 MetaFormer 的原始思想搬到 YOLOv26 上,逐步把 Token Mixer 替换成 identity,再反复调整 LayerNorm 的位置,才算彻底想明白这里面的门道。

这篇内容我打算用项目复盘的方式写,把恒等映射 Token Mixer、极简 MetaFormer 骨架、归一化驱动的特征学习这三件事拆开讲清楚,然后给出我实际改模型时的接入点、代码结构、训练参数和踩坑记录。如果你手头有 YOLOv 系列代码,想找一个不需要大规模改动数据流程和训练管线、又能稳定提升鲁棒性的改进方向,这篇应该能帮上忙。

1. MetaFormer 核心设计拆解:恒等映射 Token Mixer 原理复盘

1.1 Token Mixer 为什么可以“什么都不做”

最早把“Token Mixer”这个概念推到大众面前的是视觉 Transformer 系列工作。ViT 用自注意力作为 Token Mixer,让不同位置的 patch 在空间维上交换信息;Swin Transformer 把注意力限制在窗口内,本质上还是 Mixer。后来 PoolFormer 这篇工作抛出了一个让很多人愣住的结论:把自注意力换成平均池化,模型精度居然没有崩。这说明什么?说明 Transformer 宏观骨架里的信息交换算子,可能并没有我们想象中那么不可替代。

顺着这个逻辑再往前推一步,就是恒等映射。平均池化好歹还在做邻近区域的特征平滑,identity 则彻底不进行 token 间的信息混合。每个位置的特征向量原封不动地传给下一层。YOLOv26 改进里用恒等映射 Token Mixer,听起来像是“摆了”,实际却是在逼网络换一种方式学习特征。

我可以用一个不严谨但很直观的类比解释:如果把每个特征位置当成一个员工,自注意力像是一场全公司大会,每个人都要看所有人的报告;卷积像是一个小组内部传阅材料;恒等映射则是什么会都不开,每个人带着自己的档案直接去找下一条业务线。只要下一条业务线本身足够靠谱(MLP 和归一化还在工作),员工之间不需要互相打招呼也能完成各自的任务。

1.2 恒等分支在梯度传播里的真实作用

从优化角度看,恒等映射有一个非常漂亮的数学性质:它的雅可比矩阵是单位阵。这意味着梯度经过这个分支时不会做矩阵乘法压缩,也不会引入奇异值衰减。配合残差连接使用的时候,每一层都变成了下面这种形式:

y = x + F(Norm(x))

F 可以是 MLP、卷积、注意力,或者什么都不做。如果 F 恰好也是恒等映射,那么网络某一层的行为就完全退化成“规范化输入后原样输出”,梯度能无损地穿过整条链路。这解释了为什么在很多高分辨率检测任务里,加入 identity mixer 之后模型不容易在深层出现梯度消失,训练损失曲线也更平稳。

但需要注意,identity mixer 不等于“没有 Mixer”。在 MetaFormer 的框架里,token 间的信息混合能力可能由 MLP 和 Conv 共同承担。Conv 在滑动窗口内天然做了局部混合,MLP 在通道维度上做了特征变换,两者的叠加效果并不差。对于目标检测这种任务,一张图里的小目标往往只有几十个像素,局部上下文比全局关系更重要,恒等映射保留的空间独立性反而成了一种优势。

1.3 归一化驱动的特征学习为什么是这次改动的关键

MetaFormer 的论文里其实把贡献分成了两部分:宏观结构是一个通用公式,真正的性能来源更像是由“归一化 + MLP”构成的基本块。当 Token Mixer 变成恒等映射之后,Norm 层的地位一下子上升了一个级别。

在此之前,BatchNorm、LayerNorm 通常被看成“稳定训练”的辅助手段。但如果你把 Mixer 的混合功能拿掉,Norm 几乎成了唯一能按特征分布重新组织信息的模块。LayerNorm 会先统计每个 token 在所有通道上的均值和方差,再做减均值、除方差、最后通过可学习的 γ 和 β 进行缩放平移。这一套操作本身就是在做特征学习。

实际观测到的现象是:在深层网络里,如果只用 BN 而不用 LN,恒等映射分支很容易陷入“特征均一化”的问题,也就是不同空间位置的特征在数值上越来越像,最后失去判别性。换成 LayerNorm 后,每个位置的特征被拉回到标准尺度,MLP 再基于标准化后的分布做非线性映射,特征多样性会明显提升。这也是“归一化驱动”四个字的由来。

2. 极简 MetaFormer 改进 YOLOv26 的方案设计

2.1 改动目标识别:YOLOv26 哪些模块值得替换

YOLOv26 这种系列模型的整体思路大家都很熟悉:骨干网络负责多尺度特征提取,颈部做特征金字塔融合,头部做分类和回归。这类模型里的重头戏基本都是 C2f/C3 系列的卷积残差模块,每个模块内部有多个 Bottleneck 堆叠,每个 Bottleneck 又包含两个 3×3 卷积。单看一个 Bottleneck 不觉得贵,但堆到骨干网络的深层时,计算量占比非常可观。

我当时的想法不是把整个骨干全换掉,而是选择性地把“深层语义特征”这一段交给恒等映射 Token Mixer 和 MetaFormer 块。原因很简单:浅层分辨率高,小目标的空间信息都在这里,卷积 Mixer 的局部归纳偏置不能丢;深层特征图分辨率低,每个 token 对应的感受野已经非常大,继续堆叠 3×3 卷积带来的边际收益有限,反而容易出现特征冗余。

所以最终的方案骨架是:P3 和 P4 层继续用原始卷积混合结构,P5 层及检测头之前的特征对齐模块换成 MetaFormer 风格。这样既保留了小目标检测能力,又能压缩深层计算。

2.2 C2MF 模块设计:把恒等映射嵌进哪一层最合适

我最终实现的模块叫 C2MF,全称是 C2f with MetaFormer blocks。它复用了 C2f 的“两个 1×1 卷积分流、拼接后融合”的骨架,但把内部的若干个 Bottleneck 替换成了 MetaFormerBlock。

import torch import torch.nn as nn class IdentityMixer(nn.Module): """恒等映射 Token Mixer,不做任何 token 间交互""" def __init__(self): super().__init__() def forward(self, x): return x class MetaFormerBlock(nn.Module): """MetaFormer 最小块:Identity Mixer + LayerNorm + MLP""" def __init__(self, dim, mlp_ratio=4.0): super().__init__() self.mixer = IdentityMixer() self.norm1 = nn.LayerNorm(dim) self.mlp = nn.Sequential( nn.Linear(dim, int(dim * mlp_ratio)), nn.GELU(), nn.Linear(int(dim * mlp_ratio), dim), ) self.norm2 = nn.LayerNorm(dim) def forward(self, x): # Token 混合:恒等映射,x 原样流动 x = x + self.mixer(self.norm1(x)) # 通道变换:逐位置 MLP x = x + self.mlp(self.norm2(x)) return x class C2MF(nn.Module): """仿 C2f 结构,内部 Bottleneck 替换为 MetaFormerBlock""" def __init__(self, c1, c2, n=1, shortcut=True, g=1, e=0.5): super().__init__() c_hidden = int(c2 * e) self.cv1 = nn.Conv2d(c1, c_hidden, 1, 1, bias=False) self.cv2 = nn.Conv2d(c1, c_hidden, 1, 1, bias=False) # 核心:把多个 3x3 Bottleneck 换成 MetaFormerBlock self.m = nn.ModuleList( MetaFormerBlock(c_hidden) for _ in range(n) ) self.cv3 = nn.Conv2d(c_hidden * 2, c2, 1, 1, bias=False) def forward(self, x): y1 = self.cv1(x) y2 = self.cv2(x) for block in self.m: y2 = block(y2) y = torch.cat((y1, y2), dim=1) return self.cv3(y)

这个模块在使用时有几个细节值得说明:

第一,MetaFormerBlock 里输入 x 通常是 4D 张量,而 LayerNorm 默认操作在最后一个维度,放在卷积网络里就变成对每个位置的通道维度做归一化。这恰好符合“token-wise”的设计语义:每个空间位置是一个 token,通道维度是 token 的特征维度。

第二,恒等 Mixer 放在 Norm 之后、残差相加之前。这是先归一化后混合(pre-norm)的写法,而非传统 Conv-BN 的先混合后归一化。如果顺序反过来,Norm 就退化成了对残差分支的简单规范化,恒等分支的梯度优势会被削弱。

第三,内部 MLP 会把通道数加宽到 4 倍再压缩回去。这部分计算量并不小,但它替换的是两个 3×3 卷积,实际整体开销反而更低。我实测下来,同一层特征通道数下,C2MF 比 C2f 节省约 18% 的 FLOPs。

2.3 归一化驱动的接入方式:不同尺度层采用不同策略

我最初犯过一个错误:把所有层都换成 C2MF,结果 mAP 直接掉了一个多点。原因不复杂,浅层特征图上的每个 token 尺寸小,周围上下文不足,MLP 只做逐位置变换,缺少局部空间交互,目标边界的响应就变得不够锐利。

正确做法是分层处理:

  • P3 层:保留原 C2f,小目标检测依赖这一层的局部卷积感受野。
  • P4 层:C2MF 与 C2f 各一半,或者把 C2MF 放在 PAN 自顶向下路径的目标检测分支上。
  • P5 层:全部换 C2MF,深度语义特征对空间细节不敏感,恒等映射在这里效果最好。
  • 检测头:在分类分支和回归分支前的特征上各加一个 LayerNorm,相当于让 head 在规范化后的特征空间里做预测。

头部加 LayerNorm 这个操作成本极低,但它对最终回归框的稳定性影响较大。目标框回归本质上是在多个通道上预测相对偏移量,如果这些通道的数值尺度不一致,网络需要额外学一个尺度补偿。加 Norm 后,每个位置的偏移预测被约束在相近的动态范围内,训练更容易收敛。

3. 归一化驱动的特征学习:实操细节和原理验证

3.1 不同 Norm 层的选择逻辑

YOLOv26 传统实现里大量使用 BatchNorm,因为它能在 batch 维度统计分布,对卷积特征非常友好。但 BatchNorm 的问题在于:它混合了所有空间位置的信息,在 Identity Mixer 的场景下,这会让恒等分支产生一种“隐性全局混音”。

我自己做过一组对照:

配置P5层特征归一化方式验证集 mAP50训练损失波动
BNBatchNorm2d78.8较大
LNLayerNorm逐token归一化79.6较平滑
GNGroupNorm分组归一化79.1中等
无Norm仅残差和MLP训练发散发散

LayerNorm 在这次改动里是最稳的选择。它不依赖 batch size,也不依赖通道间的全局统计,而是对每个 token 自己通道维度的分布做标准化。这保证了模型在 batch size 较小的训练环境下仍然稳定。

BatchNorm 在 identity mixer 场景下不理想还有一个数学层面的原因:BN 的统计量中含有一个从所有位置聚合的全局均值,而恒等分支希望保留的是每个位置的独立特征。两者方向恰好矛盾,BN 会把局部特征往全局均值方向上拉,次数一多特征就钝化了。

3.2 完整的前向计算路径解析

改进后的 YOLOv26 在 P5 层的一段前向路径可以简化描述为:

  1. 输入特征图从主干卷积出来,先经过 1×1 卷积压缩通道。
  2. 进入 C2MF 分支:一半 channel 直接走 shortcut,另一半送入 MetaFormerBlock 堆栈。
  3. MetaFormerBlock 内部执行 x + LayerNorm,恒等 Mixer 不做额外计算。
  4. 经过 MLP 做通道加宽与压缩。
  5. 两路特征拼接,再通过 1×1 卷积融合输出。

这条链路上,真正影响特征表达质量的是 Norm 层对分布的控制。LayerNorm 相当于给每个 token 的原始特征向量减掉自身均值、除以自身标准差,把特征从任意分布拉回标准尺度,再让 γ、β 决定保留哪些方向。每经过一个 MetaFormerBlock,网络都可以重新“校准”一次特征分布,这就是归一化驱动特征学习的实际操作机制。

3.3 训练策略与超参数调优

我用的是某工业质检设备采集的带钢表面缺陷数据,图像分辨率 1280×1280,总计约 1.1 万张,包含裂纹、划痕、异物三类目标。训练集 8000 张,验证集 1500 张,测试集 1500 张。这个数据集的难点是目标尺寸跨度大,部分裂纹宽度只有几个像素,对特征图的分辨率和回归精度要求很高。

超参数配置如下:

  • 优化器:SGD,初始学习率 0.01,余弦衰减
  • 动量:0.937,权重衰减:0.0005
  • 训练轮数:120 epochs
  • 批大小:16(单卡 24GB 显存)
  • 输入尺寸:训练时随机 640~1280 多尺度,测试固定 1280
  • 数据增强:Mosaic、MixUp、随机仿射、HSV 扰动

对比基线的几个版本:

配置参数量FLOPsmAP50mAP50-95单卡FPS(1280)
YOLOv26s 原版32.4M108.2G78.452.149
YOLOv26s + C2MF(P5)28.6M91.5G79.152.856
YOLOv26s + C2MF(P4/P5)27.9M88.3G79.653.458
YOLOv26s + C2MF(P3/P4/P5全换)26.1M82.7G78.251.761

全换 C2MF 之后虽然 FPS 涨了不少,但精度反而下降。这说明恒等映射 Token Mixer 不是越多越好,需要和卷积混合结构保持一个平衡。

3.4 一个补充实验:把 Norm 从头部去掉会怎样

我也做过一个很反直觉的实验:模型其他部分不动,只把检测头前面新加的 LayerNorm 全部移除,结果 mAP50 掉了 0.3。这个数字不大,但说明一个问题:归一化驱动的收益不仅作用于骨干网络特征提取,同样作用于最终的分类和回归预测分布。移除头部 Norm 后,回归分支的损失曲线在最后 20 轮出现轻微震荡,加上去之后曲线立刻恢复平滑。

后来我又试过把头部 Norm 换成可学习的缩放权重,效果和完整 LayerNorm 非常接近。这进一步说明,Norm 的“减均值除方差”操作和“可学习缩放平移”两部分都在起作用,缺一不可。

4. 结果对比与性能分析

4.1 精度提升来自参数减少还是结构变化

这个疑问我专门做过验证。同样的 C2MF 结构,如果我把 LayerNorm 替换成不更新参数的固定缩放层,即手动固定 γ=1、β=0,模型的 mAP50 从 79.6 掉到了 78.7。这就排除了“单纯参数减少带来正则化收益”的解释。

真正起作用的两个因素是:

  1. 深层特征经过 LayerNorm 后分布更均匀,MLP 在标准化特征空间上学到的映射更稳定。
  2. 恒等映射让梯度无损传递,P5 层的大目标检测分支在训练早期就能快速收敛,减少了整个网络的优化压力。

如果把 BatchNorm 留在 C2MF 里也不会完全不 work,它的 mAP50 在 78.8 附近,比原版高 0.4,但低于 LayerNorm 的 0.8 个点。所以在这个结构里,Norm 类型的选择非常关键。

4.2 小目标与大目标的分类表现

按目标尺寸拆分看:

  • 小目标(32×32 以下):改进后 mAP 从 54.3% 升到 55.1%,提升主要来自浅层卷积结构被保留,深层恒等映射没有干扰到 P3 特征。
  • 中目标(32×32 到 96×96):改进后 mAP 从 66.8% 升到 67.6%。
  • 大目标(96×96 以上):改进后 mAP 从 79.5% 升到 81.2%,提升最明显。

大目标感受野覆盖范围大,深层特征原本用 3×3 卷积继续堆叠,其实在反复提取重复的语义信息。换成恒等映射后,网络不再重复学习同一批视觉模式,而是把计算资源用在更关键的通道变换上。

4.3 显存占用与部署表现

在推理阶段,C2MF 替换掉 3×3 卷积后,模型内部不需要保留大量中间激活值,显存占用确实有下降。训练阶段反而要留意:MetaFormerBlock 内部有残差连接,LayerNorm 前需要保留原始特征图供反向传播使用,如果连续堆叠十层以上,显存占用会重新升高。

我自己的建议是:单路径中 MetaFormerBlock 数量控制在 3~5 个,不要追求极致轻量化。部署到边缘设备时,把 C2MF 的 MLP 隐藏层比例从 4 降到 3,精度损失不到 0.1 个点,但 INT8 量化后的精度下降幅度更小,这一点在硬件适配时会有实际差异。

5. 常见问题与排查实录

5.1 为什么换成恒等映射后显存不降反升

如果只把原有卷积替换成 Identity,照理说计算量应该下降,但很多人实际跑出来训练显存没有明显变化。原因在于残差连接:MetaFormerBlock 默认保存输入张量用于反向传播,多个 block 堆叠会让中间变量数量线性增长。

解法是检查推理阶段和训练阶段是否复用了相同的模块。训练时用一个开启检测的 hook 观察中间激活是否被异常保留。还有一种做法是把多个 MetaFormerBlock 打包成一个整体块,在内部共享部分激活变量,能有效压训练显存。

5.2 LayerNorm 收敛速度偏慢怎么调

LayerNorm 没有 BatchNorm 那样的跨样本统计能力,训练初期损失下降确实会比原版 YOLOv26 慢一些,但后面会追回来。我遇到的情况是前 20 轮 mAP 几乎不涨,到 30 轮之后突然开始上升。

处理方法有三个:一是把学习率 warmup 从 3 轮延长到 10 轮,让 Norm 层的 γ 和 β 先稳定下来;二是给 LayerNorm 初始化一个接近目标分布的 γ 值,比如对于 ReLU 类激活,初始 γ 可以调到 1.0 不变;三是在前 10 轮冻结检测头之前的 MetaFormerBlock,先让骨干底层卷积学稳,再逐步解冻。

5.3 小目标性能下降的排查经验

如果你把 C2MF 无差别地塞进所有层,小目标几乎必降。最典型的现象是大目标 mAP 上升 2 个点,小目标掉 1 个点,整体被拉平。这是因为恒等映射不提供局部空间上下文,而小目标恰恰依赖局部细节。

我的结论是:恒等映射 Token Mixer 更适合放在语义信息主导的深层;浅层必须保留卷积或窗口注意力这类局部交互算子。如果业务场景以小目标为主,可以考虑在 P3 层保留两个 3×3 卷积 Bottleneck,只把 P4/P5 换掉。

5.4 部分类别精度波动明显怎么办

归一化驱动结构对类别数量不敏感,但如果你某个类别在训练集里数量特别少,LayerNorm 的逐位置统计会在少量样本上产生较大扰动。这种情况下,可以在少样本类别的 loss 权重上加一个简单的动态调节系数,或者在 Norm 层后加一个 dropout,概率控制在 0.1 以内,能有效抑制过拟合。

5.5 加载预训练权重时出现 shape 不匹配

这是换模块之后最容易遇到的工程问题。head、neck 的权重通常可以复用,骨干网络里的 C2MF 替换后,原先 C2f 对应的权重键值对全部失效。逐层匹配太麻烦,我习惯的做法是保留原始 YOLOv26 骨干的前两 stage 权重,后两个 stage 用随机初始化,然后从头训练完整模型;或者先用原模型在自己的数据集上热启动 30 轮,重新保存一份包含新模块的权重,再做正式训练。

我自己实际测试下来,随机初始化后两个 stage 的训练方式最终精度只比加载完整预训练低 0.2 个点,但收敛速度快了很多,因为前两个 stage 的通用特征提取能力被完整继承下来了。

6. 一些实际操作体会

这个项目做下来,我对“极简架构”的理解和方法论都有不少变化。恒等映射 Token Mixer 不是让网络“变笨”,而是把原本花在 token 间通信上的预算转移到归一化和通道变换上。YOLOv26 的骨干里大量卷积重复提取局部特征,深层部分换成 identity mixer 后,FLOPs 下降、推理提速、精度还涨,这个方向确实值得更多人尝试。

再分享一个小技巧:如果你想把 C2MF 移植到自己的项目里,别急着换掉所有模块,先只改最深一层,跑通数据流和梯度反传,确认模型能正常收敛,再逐步往后续楼层扩展。这个改动方式的风险最小,排查问题的时候也不用怀疑到底是哪一层出了问题。

后续如果想继续扩展,可以把恒等映射 Token Mixer 和稀疏化剪枝配合起来,因为 identity 分支天然不贡献参数,剪枝时可以直接绕过,这对边缘端部署价值很大。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进