3、YOLOv8基础:架构概览与三大核心模块

YOLOv8 是 Ultralytics 在 2023 年初推出的目标检测模型。说实话,我第一次跑通它的时候,第一反应是「这也太稳了」。相比之前的版本,v8 在精度和速度上做了很务实的取舍。今天我就带你把它的骨架拆开看看。

整个 YOLOv8 可以分成三块:Backbone(主干网络)、Neck(颈部) 和 Head(检测头)。我习惯把这三部分比作「眼睛-脖子-手」——眼睛看特征,脖子做融合,手去抓目标。

核心思路: YOLOv8 延续了「Anchor-Free」的设计,不再依赖预设的锚框。这意味着少了很多调参的麻烦,模型自己学会预测目标的中心点和宽高。
YOLOv8 三阶段架构图 YOLOv8 架构:Backbone → Neck → Head Backbone CSPDarknet Conv + C2f 模块 SPPF 空间金字塔池化 多尺度特征提取 输出: P3, P4, P5 Neck PAN-FPN 自顶向下 FPN 自底向上 PAN 特征融合与增强 输出: 融合特征图 Head 解耦头 分类分支 回归分支 DFL 分布损失 输出: 类别 + 边框 数据流方向:输入图像 → Backbone 提取特征 → Neck 融合多尺度 → Head 输出检测结果

3.1 Backbone:CSPDarknet 的进化

YOLOv8 的 Backbone 沿用了 CSPDarknet 结构,但做了关键改进。我最早接触 CSP 结构是在 YOLOv4 时代,当时就觉得这种跨阶段部分连接的设计很聪明——它把特征图分成两路,一路做常规卷积,另一路直接拼接,既减少了计算量又保留了梯度信息。

v8 的 Backbone 主要包含以下组件:

  • Conv 模块:标准的卷积 + BN + SiLU 激活。SiLU 比 ReLU 更平滑,训练时梯度更稳定。
  • C2f 模块:这是 v8 的核心创新。它借鉴了 ELAN 的设计思路,把输入分成多个分支,每个分支做 3×3 卷积,最后全部拼接起来。我试过在自定义数据集上对比,C2f 比 v5 的 C3 模块参数量略增,但 mAP 能涨 1-2 个点。
  • SPPF:快速空间金字塔池化。用三个串联的 5×5 最大池化替代原来的并行结构,速度更快,感受野不变。
我的经验: 如果你在训练时发现显存不够,可以尝试减少 Backbone 的深度。YOLOv8 提供了 n/s/m/l/x 五个版本,n 版本只有 3.2M 参数,适合移动端部署。

Backbone 的输出是三个尺度的特征图,我习惯叫它们 P3、P4、P5。P3 分辨率最高(原图的 1/8),负责检测小目标;P5 分辨率最低(1/32),负责大目标。这种多尺度设计是 YOLO 能同时检测大小物体的关键。

3.2 Neck:PAN-FPN 的双向融合

Neck 的作用是把 Backbone 输出的多尺度特征融合起来。YOLOv8 用的是 PAN-FPN 结构,说白了就是「一条自上而下的路 + 一条自下而上的路」。

为什么需要双向?我打个比方:FPN 自上而下传递语义信息(让低层特征知道「这是什么」),PAN 自下而上传递位置信息(让高层特征知道「它在哪里」)。两者结合,检测头拿到的特征图既有丰富的语义又有精确的位置。

路径 方向 传递的信息 作用
FPN 自顶向下 语义特征(类别) 增强低层特征的语义能力
PAN 自底向上 位置特征(坐标) 增强高层特征的定位精度

在 Neck 部分,YOLOv8 去掉了 v5 中的一些冗余卷积层,让特征融合更直接。我曾在一次工业缺陷检测项目里对比过,去掉这些层后推理速度提升了 15%,精度几乎没有下降。

注意: 不要盲目修改 Neck 的结构。我曾经尝试在 Neck 里加入注意力模块,结果训练时间翻倍,精度只涨了 0.3 个点。对于大多数场景,原生的 PAN-FPN 已经足够好。

3.3 Head:解耦头的设计哲学

Head 是 YOLOv8 变化最大的部分。v5 用的是耦合头——分类和回归共享同一组卷积。v8 换成了解耦头,分类和回归各走各的分支。

为什么要解耦?你想想看,分类任务关注的是「这是什么」,回归任务关注的是「它在哪里」。这两个任务的特征需求不同,硬绑在一起反而互相干扰。解耦后每个分支可以专注学习自己的特征。

解耦头的具体结构:

  1. 输入特征图先经过两个 3×3 卷积降维
  2. 分成两个分支:分类分支和回归分支
  3. 每个分支再经过两个 3×3 卷积
  4. 分类分支输出类别概率,回归分支输出边框坐标

回归分支还引入了一个新东西——DFL(Distribution Focal Loss)。传统的边框回归直接预测四个坐标值,DFL 改为预测坐标值的分布。举个例子,传统方法直接说「x=0.5」,DFL 会说「x 有 80% 可能是 0.5,20% 可能是 0.6」。这种分布式的表达让模型对模糊边界更鲁棒。

关键参数: 解耦头的输出通道数 = (类别数 + 4 × 16) × 每个尺度的 anchor 数。其中 16 是 DFL 的分布桶数,这个值一般不需要改。

我刚开始用解耦头时有个困惑:为什么分类和回归分支的卷积核数量不一样?后来看了源码才明白,分类分支的输出通道等于类别数,回归分支的输出通道等于 4×16(四个坐标各对应 16 个分布值)。这个设计很巧妙,它让每个分支的参数量刚好匹配各自的任务复杂度。

3.4 损失函数与训练策略

YOLOv8 的损失函数由三部分组成:

损失项 计算方式 权重
分类损失 BCE Loss(二值交叉熵) 0.5
回归损失 CIoU Loss + DFL 7.5
DFL 损失 交叉熵(分布预测) 1.5

注意回归损失的权重是 7.5,远大于分类损失。这是因为边框回归的精度对最终 mAP 影响更大。我在训练自己的数据集时试过调整这个比例,发现默认值确实是最优的。

训练建议: YOLOv8 默认使用 SGD 优化器,学习率 0.01,权重衰减 0.0005。如果你用 AdamW,建议把学习率降到 0.001,否则容易震荡。

还有一个细节:YOLOv8 在训练时使用了任务对齐学习器(TaskAlignedAssigner)来分配正负样本。它不再像 v5 那样只看 IoU,而是同时考虑分类得分和 IoU 的加权组合。说白了,一个锚框既要「分得准」又要「框得准」,才能被选为正样本。这个策略让训练初期收敛更快。