YOLOv3原理解析

3 阅读10分钟

摘要

本文从目标检测的基本表示出发,依次介绍滑动窗口、全连接层转卷积、边界框、IoU、NMS、Anchor Boxes 和多尺度预测,最后梳理 YOLOv3 的 Darknet-53 Backbone、FPN-like 特征融合、输出解码、损失函数和完整推理流程。

说明:13×13、26×26、52×52 以及 3×(C+5) 等数字是以 416×416 输入和 3 个 Anchor 为例。实际输出会随输入尺寸、类别数和模型配置变化。

目录


1. 目标检测的输出表示

目标检测需要同时回答两个问题:

  1. 图片中有什么类别的目标;
  2. 目标在图片中的什么位置。

因此,一个预测框至少需要包含边界框位置、目标置信度和类别预测。设一个预测框的输出为:

tx, ty, tw, th, to, p1, p2,,pCt_x,\ t_y,\ t_w,\ t_h,\ t_o,\ p_1,\ p_2,\ldots,p_C

其中 tx、ty、tw、th 用于回归边界框,to 用于预测是否存在目标,p1 到 pC 表示 C 个类别的预测值。

1.1 边界框与目标置信度

在一个简化的 C=3 示例中,每个 Anchor 的输出维度是 5+3=8。如果一个网格有 2 个 Anchor,则该网格的输出维度是 2×8=16。因此,笔记中的 3×3×16 是一个教学示例,不是 YOLOv3 在所有数据集上的固定输出。

1.2 损失函数概览

边界框坐标、目标置信度和类别预测并不是完全使用同一种损失。YOLOv3 原论文使用边界框回归、objectness 和类别预测共同训练,其中类别预测采用独立的 logistic 分类方式,而不是对所有类别使用一个 softmax。

目标定位和简化损失示意

图 1:目标定位输出的简化示意。

2. 从滑动窗口到 YOLO

早期目标检测方法可以通过裁剪出大量局部窗口,再分别判断每个窗口中是否存在目标。但这种方法会重复计算大量重叠区域,计算成本较高。

“特征点检测”通常指人体关键点、脸部关键点等 Keypoint Detection,与目标检测相关但不是同一个任务。为了保持文章主题,本文只把它作为背景概念,不把它作为 YOLOv3 的核心步骤。

2.1 滑动窗口检测

给定一个窗口后,让它在图像上按照一定步长滑动。每次滑动都截取一个局部区域,并将局部区域送入分类网络。

这种方法的问题是:

  • 同一片图像区域会被多次卷积;
  • 窗口尺寸和步长需要人为设置;
  • 固定窗口不一定能得到贴合目标的边界框;
  • 当图片尺寸增大或窗口数量增加时,计算量快速增长。

2.2 将全连接层转化为卷积层

滑动窗口的一个优化思路是把分类网络末端的全连接层改写为卷积层,使整张图片能够一次性完成卷积计算。

全连接层转卷积层示意

整图一次性计算多个窗口示意

原图中的 1×1×4、16 个卷积核和 2×2×4 输出都属于示例配置。它们用于说明卷积化后可以共享重叠区域的特征计算,不应理解为 YOLOv3 的固定结构。

3. 边界框、IoU 与 NMS

3.1 边界框预测

滑动窗口的固定尺寸限制了边界框的精度,因此 YOLO 会直接预测边界框的中心位置、宽度和高度。

边界框预测示意

YOLO 将图片划分为网格,并把目标分配给包含目标中心点的网格。这个“中心点负责分配”的说法是对标签分配的简化描述,实际 YOLOv3 还会结合 Anchor 进行匹配。

3.2 IoU

IoU(Intersection over Union,并交比)定义为预测框与真实框的交集面积除以并集面积:

IoU=Area(BpredBgt)Area(BpredBgt)\mathrm{IoU}=\frac{\mathrm{Area}(B_\mathrm{pred}\cap B_\mathrm{gt})}{\mathrm{Area}(B_\mathrm{pred}\cup B_\mathrm{gt})}

IoU 越大,说明两个框的重叠程度越高。IoU=0.5 可能用于某些训练忽略规则或 AP50 评价,但它不是所有任务都固定使用的阈值。

IoU 计算示意

3.3 NMS

同一个目标可能会产生多个预测框。NMS 的典型流程是:

  1. 先过滤置信度低于 confidence threshold 的预测框;
  2. 按置信度从高到低排序;
  3. 保留当前置信度最高的框;
  4. 抑制与该框 IoU 大于 NMS threshold 的其他框;
  5. 对剩余框重复上述过程。

因此,NMS 中通常是 IoU 大于阈值的框被抑制,而不是 IoU 小于阈值的框被抛弃。NMS 的 IoU 阈值、置信度阈值和 AP50 评价阈值需要分别说明。

NMS 算法示意

4. Anchor Boxes 与标签分配

4.1 Anchor 的作用

如果每个网格只能直接回归一种固定形式的框,同一个网格中的多个目标会难以表示。Anchor Boxes 提供了多种不同宽高比的参考框,使网络可以在同一个网格位置预测不同形状的目标。

同一网格中多个目标的 Anchor 示意

Anchor 增加输出维度示意

对于 A 个 Anchor、C 个类别,每个网格的输出维度为:

A×(C+5)A\times(C+5)

YOLOv3 通常在每个检测尺度使用 3 个 Anchor,因此一个 N×N 的特征图输出为:

N×N×3×(C+5)N\times N\times 3\times(C+5)

4.2 Anchor 的匹配

YOLOv3 的 Anchor 通常不是随意手动指定,而是使用训练集真实框的宽高进行 K-means 聚类,得到一组具有代表性的 Anchor,再按照大小分配到不同检测尺度。

训练时,通常根据真实框与 Anchor 的形状相似程度进行匹配。学习笔记中的“取 IoU 最大的 Anchor”可以作为直观理解,但实现中还会涉及正样本、忽略样本和 objectness 的具体规则。

Anchor 匹配示意

4.3 可能出现的问题

  • 一个网格可能存在多个目标中心点,标签分配会出现冲突;
  • Anchor 的数量过少会限制目标形状的覆盖范围;
  • Anchor 的尺寸与数据集目标分布不匹配时,训练和检测效果都会受到影响;
  • 多尺度检测可以缓解小目标与不同尺寸目标的表示困难。

5. YOLOv3 的多尺度预测

5.1 三个检测尺度

以 416×416 输入为例,YOLOv3 常见的三个检测尺度是 13×13、26×26 和 52×52。三个尺度都会进行预测:

  • 13×13:特征图分辨率低、语义信息强,通常适合大目标;
  • 26×26:在语义和细节之间折中;
  • 52×52:分辨率高,通常更适合小目标。

YOLOv3 多尺度融合示意

三尺度不是先用 IoU 选择一个特征图再预测,而是三个尺度共同输出结果。IoU 主要参与 Anchor 匹配、预测框评价和后处理。

在 COCO 数据集的 80 类设置下,每个尺度的通道数为:

3×(4+1+80)=2553\times(4+1+80)=255

原图中的 13×13×21 是 C=2、A=3 的简化示例。一个 13×13 网格位置对应的是 stride=32 的坐标单元,但其有效感受野通常不等于严格的 32×32,也不应写成 32×32×3 的原图切片。

5.2 输入尺寸和 Letterbox

目标检测模型通常要求输入尺寸满足网络结构的下采样倍数。常见做法是:

  1. 直接拉伸到目标尺寸;
  2. 保持长宽比缩放,再在周围填充像素,也就是 Letterbox。

Letterbox 可以减少非等比例缩放带来的形变,但不能简单断言它在所有数据集上都一定精度更高。训练和推理必须使用一致的缩放与填充规则,并且要同步变换边界框坐标。

输入图片尺寸变换示意

5.3 边界框解码

YOLOv3 不直接把最终边界框坐标作为网络输出,而是先预测相对于网格和 Anchor 的参数。设网格左上角坐标为 cx、cy,Anchor 的宽高为 pw、ph,则:

bx=σ(tx)+cxb_x=\sigma(t_x)+c_x

by=σ(ty)+cyb_y=\sigma(t_y)+c_y

bw=pwexp(tw)b_w=p_w\exp(t_w)

bh=phexp(th)b_h=p_h\exp(t_h)

其中 sigmoid 将中心点限制在当前网格附近,指数变换用于根据 Anchor 的宽高得到预测框尺寸。

Anchor 参数和边界框解码示意

边界框参数计算示意

5.4 三尺度标签分配

YOLOv3 在每个尺度的每个网格位置使用 3 个 Anchor。以 13×13 输出为例,该尺度一共会产生:

13×13×313\times13\times3

个候选框。26×26 和 52×52 尺度同理。所有尺度的候选框会在解码后合并,再经过置信度过滤和 NMS 得到最终结果。

6. YOLOv3 网络结构

6.1 Darknet-53 Backbone

YOLOv3 使用 Darknet-53 作为特征提取网络。Darknet-53 由连续的 3×3、1×1 卷积和残差连接组成,既能够提取较强的语义特征,又比更重的分类网络更适合实时检测。

YOLOv3 Darknet-53 网络结构示意

6.2 Neck 与 FPN-like 特征融合

YOLOv3 的 Neck 使用类似 FPN 的自顶向下融合思路:

  1. 从深层特征开始预测大目标;
  2. 将深层特征上采样;
  3. 与 Backbone 中较早的高分辨率特征 concat;
  4. 继续处理并预测中目标和小目标。

YOLOv3 特征融合和 CBL 结构示意

这里的 FPN-like 表示“具有类似 FPN 的多尺度融合思想”,并不等同于直接使用标准 FPN 实现。

6.3 CBL

CBL 通常表示:

CBL=Conv+BN+LeakyReLU\mathrm{CBL}=\mathrm{Conv}+\mathrm{BN}+\mathrm{LeakyReLU}

其中 BN 是对中间特征进行归一化和统计量变换,LeakyReLU 是激活函数。它们不是“一个简单的数据归一化操作”。

7. 损失函数与推理流程

7.1 损失函数

YOLOv3 的训练目标可以按功能拆分为:

  • 边界框回归损失:使预测框的位置和尺寸接近真实框;
  • objectness 损失:判断当前 Anchor 是否负责某个目标;
  • 分类损失:判断负责的目标属于哪些类别。

YOLOv3 原论文指出,边界框坐标使用回归损失,objectness 使用 logistic 预测,类别预测使用独立的 logistic 分类和二元交叉熵思路。因此,“所有元素直接做平方和”只能作为早期简化示意,不能作为完整的 YOLOv3 损失函数。

YOLOv3 损失函数示意一

YOLOv3 损失函数示意二

7.2 推理流程

YOLOv3 的完整推理流程可以概括为:

  1. 读取图片并执行 resize 或 Letterbox;
  2. 将图片输入 Darknet-53 和检测头;
  3. 得到 13×13、26×26、52×52 三个尺度的预测张量;
  4. 根据网格坐标和 Anchor 解码边界框;
  5. 计算目标置信度和类别得分;
  6. 过滤低置信度框;
  7. 对每个类别执行 NMS;
  8. 将结果坐标映射回原始图片。

8. 总结

YOLOv3 的核心可以概括为:

  1. 用单阶段网络一次性预测目标位置和类别;
  2. 用 Anchor Boxes 表示不同形状的目标;
  3. 用 Darknet-53 提取层级特征;
  4. 用三个尺度同时检测大、中、小目标;
  5. 用边界框解码、置信度过滤和 NMS 得到最终结果。

9. 参考资料