YOLO Vision 2026:

YOLO 架构详解:从 YOLOv3 到 YOLO26#

每一个 Ultralytics YOLO 模型都由三个阶段构建而成:提取特征的骨干网络(backbone)、跨尺度融合特征的颈部网络(neck),以及预测边界框和类别的头部网络(head)。本指南记录了构成每个阶段的模块,以及它们从 YOLOv3YOLO26 的演变过程,并将每个组件追溯到 ultralytics/cfg/models/ 下配置文件中的定义以及 ultralytics/nn/modules/ 中的模块类。

每个模型都在 YAML 文件中以声明方式定义为层的有序列表,其中每一层都遵循 [from, repeats, module, args] 格式:输入来自哪一层(或哪些层)、模块重复的次数、层类(ConvC3k2SPPFDetect 等)以及构造函数参数。Model YAML Configuration Guide 记录了这种格式(包括 repeatsargs 如何随变体的深度和宽度倍数进行缩放),以及完整的模块解析系统。本指南重点介绍模块本身及其在不同版本之间的变化。

三个阶段#

每个 Ultralytics YOLO 模型都将图像通过三个顺序阶段进行路由,每个阶段都有明确的任务:

阶段任务输出
Backbone在多个分辨率下从输入图像中提取特征步长为 8、16 和 32 的特征图(P3、P4、P5)
Neck跨尺度融合特征,使小目标和大目标都能拥有上下文信息多尺度融合特征图
Head从融合后的特征中预测边界框和类别分数每个锚点的检测结果

基本单元是 Conv 块(定义于 conv.py):按顺序应用的二维卷积、批量归一化(batch normalization)SiLU 激活函数。下面所有的更大模块都是通过组合 Conv 块构建的。

架构图#

每版本都保留相同的 backbone → neck → head 骨架并改变特定阶段。下方的标签页展示了各版本的结构:backbone 和 neck 阶段遵循 ultralytics/cfg/models/ 中的配置,而 YOLOv3 和 YOLOv5 的 head 则以其原始的 anchor-based 形式绘制,而不是它们软件包配置实际采用的无 anchor u 变体 head。逐个查看标签页可以了解每一代新增的内容。简而言之,演进过程是:YOLOv3 是一个仅有 FPN、基于 anchor 的检测器;YOLOv5 添加了自下而上的 PAN 路径和 SPPF;YOLOv8 切换到带有无 anchor、DFL head 的 C2f 模块;YOLO11 插入了 C2PSA 注意力和 C3k2 模块;YOLO26 则添加了 SPPF 残差,并使 head 变为无 NMS 和无 DFL。节点颜色遵循文档图表惯例:绿色表示输入,蓝色表示 backbone,石板灰表示空间池化和注意力,橙色表示 neck,紫色表示 head 和输出。

flowchart TD
    IN[Input 640x640]:::start --> ST[Conv stem<br/>5x stride-2 down to P1-P5]:::proc
    ST --> BB[Darknet-53 backbone<br/>stacked Bottleneck]:::proc
    BB --> FPN[Neck FPN only<br/>top-down Upsample + Concat]:::decide
    FPN --> HD[Detect head<br/>3 scales, anchor-based]:::out
    HD --> O[Predictions + NMS]:::out
    classDef start fill:#4CAF50,color:#fff
    classDef proc fill:#2196F3,color:#fff
    classDef decide fill:#FF9800,color:#fff
    classDef out fill:#9C27B0,color:#fff

YOLOv3 和 YOLOv5 图表展示了最初的基于锚框的头部。ultralytics 软件包自带无锚框的 YOLOv3uYOLOv5u 配置——它们拥有与 Darknet-53 和 C3 相同的骨干网络,但配备了 YOLOv8 的 Detect 头部——这些内容在检测头部(Detection Head)下有详细描述。

Backbone 块:Bottleneck → C3 → C2f → C3k2#

骨干网络在步长为 2 的 Conv 下采样层之间堆叠了一个重复的 CSP(跨阶段局部,Cross-Stage Partial)块。这个重复的块在各个版本中变化最大。以下所有块都位于 block.py 中;c1/c2 是输入/输出通道,c = 0.5 * c2 是隐藏宽度。

Bottleneck (YOLOv3)#

基础单元是 Bottleneck:两个 Conv 层(默认卷积核 (3, 3)),当 shortcut=Truec1 == c2 时带有可选的残差相加。YOLOv3Darknet-53 骨干网络直接堆叠了这些单元,没有 CSP 拆分,并在三个尺度(步长 8、16、32)上进行检测。

C3 (YOLOv5)#

YOLOv5C3 将输入拆分到两个 1x1 卷积中:cv1 馈送 n 个顺序的 Bottleneck 块(卷积核先是 (1, 1),然后是 (3, 3)),cv2 则绕过它们。这两条路径被拼接并通过第三个 1x1 Conv 进行融合:

def forward(self, x):
    # C3: bottleneck path m(cv1(x)) concatenated with bypass cv2(x), then fused by cv3
    return self.cv3(torch.cat((self.m(self.cv1(x)), self.cv2(x)), 1))

只有最终的瓶颈输出到达融合卷积,因此 cv3 看到 2 个特征图。

C2f (YOLOv8)#

YOLOv8C2f(“带 2 个卷积、速度更快的 CSP 瓶颈”)改变了到达融合卷积的特征:

  1. cv1 = Conv(c1, 2 * c, 1),然后 chunk(2) 将输出拆分为两个 c 通道的张量。
  2. n Bottleneck(c, c) 块(卷积核 (3, 3)(3, 3))顺序运行,每个块都由前一个块的输出提供输入。
  3. 所有 n + 2 中间张量都被拼接并通过 cv2 = Conv((2 + n) * c, c2, 1) 进行融合。

C3 将 2 个特征图传递到其融合卷积中的地方,C2f 传递了 n + 2 个——每个中间瓶颈输出都被重复使用。

C3k2 (YOLO11 和 YOLO26)#

YOLO11YOLO26 使用 C3k2,它是 C2f 的子类,替换了重复单元。根据构造函数标志,每个 n 块变为:

  • 一个普通的 Bottleneck(默认,c3k=False),
  • 一个 C3k 块(c3k=True)——一个具有可配置卷积核大小的 C3 变体,或者
  • 一个 Bottleneck + PSABlock 对(attn=True)。

第二个 YAML 参数设置 c3k;例如,[-1, 2, C3k2, [512, True]] 在 512 个输出通道处构建一个 C3k2 模块,其内部块为 C3k(因为 c3k=True)。对于 CSP 模块,repeats 字段——此处为 2,在按变体的深度倍数缩放之前——成为块的内部重复次数,而不是堆叠独立的模块。

空间池化:SPP → SPPF#

在 backbone 的末尾,空间金字塔池化模块扩大了感受野。YOLOv5 用 SPPF(空间金字塔池化 - 快速)替换了原始的多核 SPP:一个单一的 MaxPool2d(kernel_size=5, stride=1, padding=2) 按顺序应用了 n = 3 次,输入和所有三个池化输出被拼接并通过 1x1 Conv 进行融合。这在数学上等同于 SPP(k=(5, 9, 13)) 但成本更低,因为链式的 5x5 池化覆盖了较大卷积核的感受野。

YOLO26 传递了一个捷径标志(SPPF, [1024, 5, 3, True]);由于在最深层有 c1 == c2 == 1024SPPF 添加了一个残差连接(return y + x)。

空间注意力:C2PSA (YOLO11+)#

YOLO11SPPF 之后添加了 C2PSA。它是一个 CSP 模块,其活动分支是一堆 n PSABlock(位置敏感注意力)模块:cv1 = Conv(c1, 2 * c, 1) 拆分特征,一半通过 PSABlock 堆栈,cv2 = Conv(2 * c, c1, 1) 则融合拼接结果。每个 PSABlock 应用多头注意力,随后是一个两层的前馈网络(Conv(c, 2 * c, 1)Conv(2 * c, c, 1)),每个都带有残差连接。YOLO26 保留了相同的 C3k2 + C2PSA backbone。

Neck:FPN + PAN#

颈部网络将骨干网络的 P3/P4/P5 特征图与自顶向下的特征金字塔网络(FPN)以及随后的自底向上的路径聚合网络(PAN)进行融合。在 YAML 头部部分,FPN 是 nn.Upsample + Concat(将语义信息向下传递到更高分辨率),而 PAN 是步长为 2 的 Conv + Concat(将定位信息传回上方):

# YOLO11 head (FPN top-down, then PAN bottom-up)
- [-1, 1, nn.Upsample, [None, 2, "nearest"]]
- [[-1, 6], 1, Concat, [1]] # cat backbone P4
- [-1, 2, C3k2, [512, False]] # 13
# ... second upsample + concat to P3 ...
- [-1, 1, Conv, [256, 3, 2]]
- [[-1, 13], 1, Concat, [1]] # cat head P4 (PAN)
- [-1, 2, C3k2, [512, False]] # 19

颈部网络重用了其生成周期的骨干网络块——在 YOLOv5 中为 C3,在 YOLOv8 中为 C2f,在 YOLO11 和 YOLO26 中为 C3k2——因此每个合并点都运行骨干网络所使用的相同模块。三个融合输出馈送到头部。YOLOv3 是个例外:它的颈部只有自顶向下的 FPN(其 YAML 头部没有步长为 2 的下采样),没有 YOLOv5 引入的自底向上的 PAN 路径。

检测头:基于锚点 → 无锚点 → 无 NMS#

头部网络将三个融合的特征图转换为针对检测任务的预测。其设计在各个版本中发生了变化,从基于锚框到无锚框,再到无 NMS。

无锚框、解耦的 Detect#

原始的 YOLOv3 和 YOLOv5 使用了基于 anchor 的、耦合的 head:预定义的 anchor 框以及用于框和类别预测的共享分支。独立的 ultralytics/yolov3ultralytics/yolov5 仓库保留了该基于 anchor 的设计。主要的 ultralytics 软件包反而搭载了无 anchor 的 YOLOv3uYOLOv5u 变体 —— 即具有 YOLOv8 无 anchor Detect head 的相同 Darknet-53 和 C3 backbone —— 并且这里记录的 yolov3.yamlyolov5.yaml 配置正是这些 u 变体,而非历史设计。

Detect 头部(head.py)是无锚框且解耦的:它在每个金字塔层级上运行两个并行分支,并直接在网格点上进行预测,而不是针对锚框进行预测。

  • 边界框分支(cv2): Conv(x, c2, 3)Conv(c2, c2, 3)Conv2d(c2, 4 * reg_max, 1)
  • 类别分支(cv3): 在 YOLO11 和 YOLO26 中,两个深度可分离块(DWConv + 1x1 Conv)→ Conv2d(c3, nc, 1);YOLOv8 使用传统变体,即两个 3x3 Conv 层 → Conv2d(c3, nc, 1)

因此,每个锚点都会发出 no = nc + 4 * reg_max 个输出。移除预定义的锚框消除了必须调优的超参数中的锚框大小和长宽比。

分布焦点损失 (DFL)#

YOLOv8 和 YOLO11 将 4 个边界框坐标中的每一个回归为 reg_max = 16 个箱(bins)上的分布,而不是单个标量(来自广义焦点损失(Generalized Focal Loss)的积分形式)。DFL 模块将 4 * reg_max 边界框通道重塑为 (4, reg_max),对 reg_max 个箱应用 softmax,并将期望的箱索引——每个箱索引由其 softmax 概率加权,然后求和——作为预测坐标。这实现为一个固定的 1x1 卷积,其权重是箱索引 arange(reg_max),因此加权和是一个单一的点积。

YOLO26:无 NMS,无 DFL#

YOLO26 设置了两个供头部直接读取的 YAML 参数:

在其五个模型尺寸(n/s/m/l/x)中,YOLO26 在 COCO 上达到了 40.9-57.5 的 mAP,T4 TensorRT 延迟为 1.7-11.8 ms,正如 YOLO26 论文中所报告的那样。

版本总结#

版本Backbone 块空间池化注意力检测头DFL
YOLOv3Darknet-53(Bottleneck基础配置中没有原始:基于锚框;u 变体:无锚框无 / 有(u
YOLOv5C3(CSP)SPPF原始:基于锚框;u 变体:无锚框无 / 有(u
YOLOv8C2fSPPF无锚点,解耦有(reg_max=16
YOLO11C3k2SPPFC2PSA无锚点,解耦有(reg_max=16
YOLO26C3k2SPPF + 捷径C2PSA无锚框、无 NMSend2end已移除reg_max=1

有关逐个模型的详细信息、性能表格和使用示例,请参阅 YOLOv3YOLOv5YOLOv8YOLO11YOLO26 的单独页面。

亲自检查架构#

model.info() 方法会打印层、参数和 FLOPs 摘要,并且解析后的模块列表可在 model.model.model 上获取。

检查 YOLO 模型的架构
from ultralytics import YOLO

# Load a pretrained model
model = YOLO("yolo11n.pt")

# Fuse Conv + BatchNorm layers so counts match the published specs
model.fuse()

# Print a summary: layers, parameters, gradients, GFLOPs
model.info()

# Inspect the detection head (the last module in the network)
head = model.model.model[-1]
print(type(head).__name__, "| reg_max:", head.reg_max, "| end2end:", head.end2end)

跨三个世代运行该代码片段可以以数字方式展示这些变化。这些是来自 ultralytics 软件包的真实融合模型输出,与每个模型页面上公布的参数和 FLOPs 数量相匹配:

模型层数参数量GFLOPsreg_maxend2endDFL 层
YOLOv8n723,151,9048.716FalseDFL
YOLO11n1002,616,2486.516FalseDFL
YOLO26n1222,408,9325.41TrueIdentity

YOLO26n 报告了 reg_max=1end2end=True 以及一个 Identity DFL 层——这是其无 NMS、无 DFL 头部的架构特征。

融合与未融合计数

参数和 FLOPs 值是针对融合模型(model.fuse())报告的,该模型将每个 Conv 与其批量归一化(batch normalization)层进行了合并。这与公布的规格相符;刚加载的检查点在融合前会报告稍高的计数。

结论#

在各个版本中,YOLO 架构每次更改一个阶段:backbone 从 Darknet-53 演变为带有 C2PSA 注意力的基于 CSP 的 C3C2fC3k2 模块;neck 保持其 FPN + PAN 结构,同时 SPP 变成了 SPPF;head 则从基于 anchor 转变为无 anchor,然后演变为 YOLO26 的无 NMS、无 DFL 的端到端设计。

要定义自定义架构,请参阅模型 YAML 配置指南(Model YAML Configuration Guide),或在模型页面上比较模型。如有疑问,请在 GitHubDiscord 上与我们联系。

常见问题解答#

  • YOLO 模型具有一个骨干网络(backbone),用于在 8、16 和 32 的步长(strides)下提取图像特征;一个颈部(neck),通过 FPN 和 PAN 在不同尺度上融合这些特征;以及一个头部(head),用于预测边界框(bounding boxes)和类别得分。从 YOLOv3 到 YOLO26,每一款 Ultralytics YOLO 模型都遵循这种三阶段设计。

  • C2f(YOLOv8)是一个 CSP 模块,在其融合卷积之前拼接了每个内部 Bottleneck(即 n + 2 个特征图)的输出,而较旧的 C3 仅传递 2 个。C3k2(YOLO11 和 YOLO26)是 C2f 的子类,当设置了其 c3k 标志时,它可以将每个 Bottleneck 替换为 C3k 模块(一个具有可配置卷积核大小的 C3 变体)。两者的定义都在 block.py 中。

  • YOLO11 对 YOLOv8 进行了三项结构更改:它将 C2f 的 backbone 和 neck 模块替换为 C3k2,在 SPPF 之后插入了一个 C2PSA 自注意力模块,并将 head 的分类分支切换为更轻量的深度可分离卷积。两者都保留了相同的无 anchor、解耦的 Detect head 以及带有 reg_max=16 DFL 回归,因此这些更改在降低参数量和 FLOPs 的同时提高了准确率,而不是重新设计检测接口。

  • 现代 Ultralytics YOLO 模型都是无锚框的。YOLOv8、YOLO11 和 YOLO26 使用无锚框、解耦的 Detect 头部,为边界框回归和分类设置了单独的分支。最初的 YOLOv3 和 YOLOv5 是基于锚框的,但 Ultralytics 将它们作为 YOLOv3uYOLOv5u 变体发布,其配置使用了与 YOLOv8 相同的无锚框头部。

  • 是的——YOLO26 设置了 end2end=True,这为 Detect 提供了一个一对一头部,每个对象产生单个预测,并去掉了早期模型所需的非极大值抑制后处理步骤。有关详细信息,请参阅端到端检测指南(End-to-End Detection guide)

  • DFL 将每个边界框坐标回归为 reg_max 个箱(bins)上的 softmax 分布(在 YOLOv8 和 YOLO11 中默认维 16)并将期望值作为坐标,而不是预测单个标量。YOLO26 设置了 reg_max=1,因此 DFL 层变成了恒等操作,头部直接回归坐标,并且导出的 ONNX 或 TensorRT 图中不会出现 DFL 操作。

  • 在 Python 中加载模型并调用 model.info() 以获取层、参数和 GFLOPs 摘要。解析后的层位于 model.model.model 中——例如,model.model.model[-1]Detect 头部,公开了诸如 reg_maxend2end 之类的属性。完整的架构定义在模型的YAML 配置文件中。

贡献者

评论