这两年 Vision Transformer 火得一塌糊涂,各种 ViT 变体层出不穷。相比之下,ConvNeXt 这类 CNN 架构似乎有点"过气"的意思。
但最近在做一个工业检测项目时重新捡起了 ConvNeXt,发现这玩意儿在某些场景下依然很能打。

CNN vs Transformer 对比:ConvNeXt 融合了 CNN 的效率与 Transformer 的设计理念
ConvNeXt 是 Meta 在 2022 年提出的现代 CNN 架构。说是 CNN,但它其实是拿着 Transformer 的设计思路重新改造 CNN 的产物。
几个核心设计:
# ConvNeXt-T 配置示例
embed_dim=96, depth=[3, 3, 9, 3], kernel_size=7
7×7 深度可分离卷积:和 Swin Transformer 的窗口注意力思路类似,但用卷积实现
反转瓶颈:把 FFN 的维度比例从 4 改到 1,MLP 隐层压缩
LayerNorm:不用 BN,用现代化的归一化方式
GELU 激活:换掉 ReLU,用更平滑的激活函数

ConvNeXt 架构:层次化设计,4 级特征输出,深度可分离卷积为核心
听起来都是小改,但加在一起,ConvNeXt-T (28M) 能在 ImageNet 上达到 82.1% 的精度,和 Swin-T 持平。参数量还更少。
ConvNeXt 的 4 级输出 (C1-C4,通道数 96/192/384/768) 和 YOLO 的 P3/P4/P5 多尺度需求天然对齐。不需要像 ViT 那样手动设计如何从单尺度特征图生成多尺度。

这个特点对工业检测很友好:缺陷目标往往跨越不同尺度,层次化的特征提取让网络更容易捕捉从小到大的各种目标。
CNN 的局部连接和权重共享让模型天然对图像的空间结构有偏好。ViT 需要通过大量数据学习这些偏置,而 ConvNeXt 生来就有。
在数据量不算特别大的工业场景,这个优势会体现出来。
同样是检测任务,ConvNeXt 的 CNN 结构在 GPU 上的并行计算效率通常比 ViT 的自注意力更高。
实测下来,ConvNeXt-Base 的推理速度比 ViT-B 快将近一倍。
ConvNeXt + YOLO26 的框架和之前 DINOv3 那套思路类似,核心区别在于特征提取层:

ConvNeXt 的多尺度输出通过 timm 的 features_only=True 获取:
self.convnext = timm.create_model(
convnext_type,
pretrained=False,
features_only=True,
out_indices=(0, 1, 2, 3)
)
features = self.convnext(x)
# features[0]: C1, 通道96, 特征图尺寸 H/4
# features[1]: C2, 通道192, H/8
# features[2]: C3, 通道384, H/16
# features[3]: C4, 通道768, H/32
这里有个细节:ConvNeXt 输出的 4 级特征是 H/4、H/8、H/16、H/32,而不是标准的 P3/P4/P5 (H/8、H/16、H/32)。需要做个映射。
FPN 风格融合,把 C1、C2、C3 转成 P3、P4、P5:
def forward(self, x):
c0, c1, c2, c3 = x # ConvNeXt 的 4 级输出
f8 = self.proj8(c0) # 96 -> 256
f16 = self.proj16(c1) # 192 -> 512
# 跨尺度融合:用 avg_pool 下采样高分辨率特征
down_8to16 = F.avg_pool2d(f8, kernel_size=2, stride=2)
n16 = self.fuse16(torch.cat([f16, down_8to16], dim=1))
f32 = self.proj32(c2) # 384 -> 512
down_16to32 = F.avg_pool2d(n16, kernel_size=2, stride=2)
n32 = self.fuse32(torch.cat([f32, down_16to32], dim=1))
return [f8, n16, n32] # P3, P4, P5

FPN 特征金字塔网络:低分辨率强语义 + 高分辨率强空间的多尺度融合
有个细节:这里 C3 (H/16) 直接作为 P5 的基础,而没有用 C4 (H/32)。原因是 ConvNeXt 的 C4 通道数是 768 太大了,和后面的检测头不匹配。
YOLO26 的检测头需要适配多尺度输出:
self.detect = nn.Identity()
def forward(self, x):
neck_feats = [f8, n16, n32]
return self.detect(neck_feats)
训练时 Ultralytics 会自动处理 forward_head 的 loss 计算。推理时检测头会输出解码后的边界框和置信度。
有个参数需要指定:
self.stride = torch.tensor([16., 32., 64.])
这对应 P3 (40×40)、P4 (20×20)、P5 (10×10) 三个尺度的 stride。
ConvNeXt 预训练权重很强,如果数据量不大(几百张),可以先冻结 backbone:
if freeze_convnext > 0:
for param in self.convnext.parameters():
param.requires_grad = False
数据量中等(上千张)的话,可以解冻最后 1-2 个阶段,让模型适应一下工业图像的分布。
默认配置:
lr0: 0.0005
weight_decay: 0.0005
cos_lr: true
ConvNeXt 的特征比较稳定,学习率可以比从头训练稍微大一点。
工业场景建议保守一点:
mosaic: 0.8 # 工业图像可以用,影响不大
mixup: 0.1
close_mosaic: 10
如果发现缺陷被 cut 掉的情况,可以把 mosaic 关掉。
导出 ONNX 一样是标准操作:
model.export(
format='onnx',
imgsz=[640, 640],
dynamic=False,
half=True
)

ONNX 跨平台部署:训练框架 → ONNX → 多种推理引擎与边缘设备
ConvNeXt 的优势在部署端也体现得出来:CNN 结构的 ONNX 模型在各个推理引擎上都有很好的支持,延迟稳定。

不是非此即彼的关系,各有适合的场景:

适合用 ConvNeXt 的场景:
适合用 ViT (DINOv3/EUPE) 的场景:
具体用哪个,可以在你的数据集上做个快速对比实验再决定。

以上是 ConvNeXt + YOLO26 方案的一些整理。如果有具体问题可以讨论,但不一定能及时回复。