YOLOv3 详解
YOLOv3: An Incremental Improvement
论文: YOLOv3: An Incremental Improvement (2018)
作者: Joseph Redmon, Ali Farhadi
代码: pjreddie.com/darknet/yolo
论文标题就叫 “An Incremental Improvement”(一点小改进),作者自嘲”没做啥特别的研究,就是把它做得更好了”。但这篇”技术报告”在工程界大受欢迎,成为后续 v4/v5/v7 的基础,也是 Redmon 关于 YOLO 的最后一篇(2020 年因反对将 YOLO 用于军事/隐私而停止更新)。
一、概述:v3 改了什么
1 | YOLOv3 = v2 的底座 + 三大新组件: |
1.1 v1 → v2 → v3 演进对比
| 维度 | YOLOv1 | YOLOv2 | YOLOv3 |
|---|---|---|---|
| Backbone | 类 GoogLeNet (24层) | Darknet-19 (19层) | Darknet-53 (53层 + 残差) |
| 下采样 | Max Pooling | Max Pooling | 步长=2 卷积 (无池化) |
| 检测尺度 | 1 个 (7×7) | 1 个 (13×13) | 3 个 (13×13, 26×26, 52×52) |
| Anchor 数 | 无 (直接回归) | 5 (K-means) | 9 (3 尺度 × 3 Anchor) |
| 分类器 | Softmax | Softmax | Sigmoid (多标签, BCE) |
| 置信度目标 | IoU (动态) | IoU / 1 (rescore) | 1 (二分类) |
| 每格预测框 | 2 | 5 | 3 (每尺度) |
| 总预测框 | 98 | 845 | 10647 |
| mAP (COCO) | - | 21.6 | 33.0 |
1.2 保留自 v2 的特性
- 端到端训练,一个 loss 搞定,统一为回归问题
- 每个卷积层后接 BN + LeakyReLU
- Anchor Box 机制 + 维度聚类 (K-means,距离用 1-IoU)
- 边框解码公式(同 v2,见 [[YOLOv2 详解]])
- 多尺度训练(每 10 batch 随机换输入尺寸)
二、网络架构:Darknet-53
2.1 三个基本单元
1 | CBL = Conv2D + BatchNorm + LeakyReLU ← 最小组件 |
基础操作辨析:
Concat(张量拼接,通道叠加,扩充维度,对应 cfg 的route)vsadd(张量相加,维度不变,对应 cfg 的shortcut,即残差连接)。v3 的 FPN 融合用 Concat,残差块内部用 add。
2.2 骨干网结构(5 个 ResX)
输入 416×416×3 经过 5 次步长=2 的卷积下采样,逐级缩小到 13×13:
1 | 输入 416×416×3 |
2.3 完整架构(骨干 + FPN 颈部 + 检测头)

1 | 13×13×1024 ──→ 5×CBL ──→ 输出 Y1 (13×13×255) 大目标 |
关键设计:
- 无池化层、无全连接层:所有下采样通过 conv stride=2 实现,保留更多空间信息;也正因全卷积,才能支持任意尺寸输入与多尺度训练。
- 每个卷积层后都接 BN + LeakyReLU。
- 53 层怎么数:
1 + (1+1×2) + (1+2×2) + (1+8×2) + (1+8×2) + (1+4×2) = 52个卷积层 + 1 个全连接(分类版)= 53。检测版去掉全连接,实际约 52 个卷积层 + 检测头。
2.4 与 Darknet-19 对比
| 特性 | Darknet-19 (v2) | Darknet-53 (v3) |
|---|---|---|
| 下采样 | 5× MaxPooling | 5× Conv stride=2 |
| 残差连接 | ❌ 无 | ✅ 5 组 Res block |
| 卷积层数 | 19 | 53 |
| ImageNet Top-1 | 72.9% | 77.2% |
| ImageNet Top-5 | 91.2% | 93.8% |
| 计算量 (224×224) | 55.8 亿次 | 65.9 亿次 |
层数翻了近 3 倍,计算量只增加 18%。残差结构使深层网络训练成为可能;Darknet-53 比 ResNet-101/152 更高效,且更好地利用了 GPU。
三、多尺度预测:FPN 思想 🔥
v3 最重要的改进。借鉴 FPN(Feature Pyramid Networks),用 3 个尺度的特征图同时预测,一举扭转了 YOLO 在小目标上的劣势。
3.1 为什么需要多尺度?

1 | v2 只在 13×13 一层做预测: |
3.2 FPN 背景:四种特征金字塔方案
理解 v3 的多尺度,先看 FPN 论文总结的四种多尺度方案:
| 方案 | 做法 | 缺点 |
|---|---|---|
| (a) 图像金字塔 | 原图多次缩放成金字塔,每级分别算特征 | 算力/内存巨大,训练测试不一致 |
| (b) 单层特征 | 只取最后一层特征(Fast/Faster R-CNN 默认) | 高分辨率层语义弱,不利于识别;低分辨率不利于小目标 |
| (c) SSD 式 | 从不同层各取特征图组金字塔 | 仅用深层,丢失高分辨率特征,小目标不利 |
| (d) FPN | 单输入 + 自上而下上采样 + 横向连接融合 | — ✅ v3 采用 |
FPN 核心思想:低层特征位置准但语义弱;高层特征语义强但位置粗。通过自上而下上采样 + 横向连接,把深层语义注入浅层,让所有层都兼具强语义与高分辨率。
3.3 FPN 融合过程

1 | 深层特征 (13×13) ← 语义强、位置粗 → 适合大目标 |
⚠️ v3 的 FPN 融合用 Concat(通道拼接) 而非 Add(逐元素相加)。
- Concat 会扩充通道数(如 256+512→768),保留更多原始信息,源于 DenseNet 思路;
- Add 维度不变,是 ResNet/Faster R-CNN 风格。
上采样用最近邻插值(不改变通道数),将小特征图放大到与目标层同尺寸后拼接。
3.4 三个尺度与 9 个 Anchor

| 尺度 | 特征图 | 下采样 | Anchor 尺寸 (COCO) | 检测目标 | 预测框数 |
|---|---|---|---|---|---|
| Y1 | 13×13 | 32× | (116×90), (156×198), (373×326) | 大物体 | 13²×3 = 507 |
| Y2 | 26×26 | 16× | (30×61), (62×45), (59×119) | 中物体 | 26²×3 = 2028 |
| Y3 | 52×52 | 8× | (10×13), (16×30), (33×23) | 小物体 | 52²×3 = 8112 |
| 合计 | 9 种 Anchor | 10647 框 |

9 个 Anchor 由 K-means 聚类得到(同 v2 方法,距离用 1-IoU),按尺寸从大到小均分给 3 个尺度。大 Anchor 配小特征图,小 Anchor 配大特征图——因为层数越深,特征图对小尺寸物体响应越弱,所以小目标交给高分辨率的浅层特征图 + 小 Anchor。
四、检测头与输出张量
每个尺度经过 5×CBL 后接一个 1×1 卷积输出预测张量。以 COCO(80 类)为例:
1 | 255 = 3 × (4 + 1 + 80) |
总预测框数:$(13^2 + 26^2 + 52^2) \times 3 = 10647$。一张图产生上万个框,绝大多数是背景,靠置信度阈值 + NMS 筛选(见第九节)。
五、边界框预测与解码
5.1 网络预测的四个偏移量
网络并不直接输出框的绝对坐标,而是输出相对于网格和先验框的偏移量 $t_x, t_y, t_w, t_h$。设:
- $(c_x, c_y)$:该网格左上角距图像左上角的格子数;
- $(p_w, p_h)$:先验框(Anchor)的宽高;
- $\sigma$:sigmoid 函数。
5.2 解码公式

$$
b_x = \sigma(t_x) + c_x, \quad b_y = \sigma(t_y) + c_y
$$
$$
b_w = p_w , e^{t_w}, \quad b_h = p_h , e^{t_h}
$$
- 中心点 $(b_x, b_y)$:sigmoid 把偏移压在 $[0,1]$,保证中心不会跑出当前网格;
- 宽高 $(b_w, b_h)$:以先验框为基准做指数缩放,$e^{t_w}$ 是放大倍数。训练时对宽高取 log 还原成 $t_w = \log(G_w/p_w)$,取 log 是为了让训练更稳定。
训练用平方误差:若真实框对应 $\hat{t}*$,则梯度为 $\hat{t}* - t_*$,真实值可由上式反解得到。
5.3 为什么 x, y 用 sigmoid 而非线性?
作者尝试过用线性激活直接预测 $(x,y)$,导致 mAP 下降、模型不稳定。sigmoid 将中心约束在网格内,是必要的稳定性保证(见第十一节”失败的尝试”)。
六、多标签分类:Sigmoid 替代 Softmax
6.1 为什么要改?
1 | Softmax 的问题: 假设类别互斥 |
6.2 损失函数跟着改
| 组件 | v1/v2 | v3 | 为什么改 |
|---|---|---|---|
| 类别损失 | Softmax + SSE | Sigmoid + BCE | 多标签 + 交叉熵更合理 |
| 置信度损失 | SSE | Sigmoid + BCE | 二分类用交叉熵 |
| 定位损失 (x,y) | SSE | Sigmoid + BCE | 中心坐标也改为 BCE |
| 定位损失 (w,h) | SSE | SSE(保留) | 宽高仍是连续回归 |
⚠️ v3 论文没有给出完整的损失函数公式,以上基于 Keras 源码(qqwweee/keras-yolo3)和社区分析总结。
七、训练:标签分配与损失函数
7.1 框分配机制(同 v2,参数有变)
1 | 分配流程: |
v3 把置信度从”回归”改为”二分类”——常被忽略但很重要:
- v2:
target = IoU(预测框, GT),网络要学”框得有多准”。小物体 IoU 始终很小,confidence 学不上去,Recall 低。- v3:
target = 1(正)/ 0(负),网络只学”这个 Anchor 有没有负责物体”,不受 IoU 大小影响。代价是定位质量不再体现在 confidence 中(这是后续版本改进方向)。
7.2 三类样本
1 | 正样本 (Positive): 与 GT IoU 最大的 Anchor(每个 GT 仅 1 个) |
1:1 严格分配是 YOLOv3 与其他检测器的区别:Faster R-CNN / RetinaNet 会把 IoU>0.7 的多个 anchor 都算正样本,YOLOv3 只选 1 个最佳。好处是训练目标明确不打架,代价是可能收敛慢。
7.3 Ignore Mask:10647 个框里只有几个”好人”
一张 COCO 训练图(假设 5 个 GT)的实际分布:
1 | 正样本: 5 个 (每个 GT 选 1 个最佳 Anchor) |
为什么需要 Ignore Mask? 多尺度下同一物体可能在多个尺度都被检测到:若把那些”也检测到了、IoU>0.5”的框强行压向 0,会反向传播大量错误梯度,三个尺度互相打架,训练不收敛。Ignore 让它们”自由发挥”——既不惩罚也不鼓励。
为什么 YOLOv3 不需要 Hard Negative Mining?
- 置信度用 BCE(二分类),负样本梯度比多分类 Softmax 小得多;
- ignore_mask 已过滤掉”说得过去”的框,剩下的负样本是真·背景;
- 正负比例虽悬殊(~5:10592),但 BCE 天然不会让负样本主导梯度方向。
7.4 跨尺度标签分配
一个中尺寸物体(如中等大小的狗)可能在多个尺度同时匹配:
1 | Y2 (26×26) 某 Anchor IoU=0.75 → 正样本(唯一!) |
有了跨尺度 ignore,三个尺度和平共处,不会互相抑制。
7.5 损失函数(基于 Keras 源码)
1 | # 定位损失 - 中心坐标用 BCE, 宽高用 MSE |
除 w, h 仍用平方误差外,其余部分(xy、置信度、类别)均用 二元交叉熵 BCE,最后相加。
7.6 损失函数权重
| 参数 | 含义 | 说明 |
|---|---|---|
| box_loss_scale | 定位损失缩放 | 2 - w_gt × h_gt,小框获得更大权重(同 v2) |
| object_mask | 正样本掩码 | Responsible Anchor = 1, 其余 = 0 |
| ignore_mask | 忽略掩码 | IoU > 0.5 但不负责的框 = 0,不参与置信度损失 |
八、训练配置
8.1 两阶段训练
1 | 第一阶段: ImageNet 分类预训练 |
论文强调:在完整图像上训练,没有硬负样本挖掘,使用多尺度训练 + 大量数据增强 + BN——都是”标准操作”。
8.2 多尺度训练
同 v2:每 10 batch 随机切换输入尺寸 ∈ {320, 352, …, 608}(32 的倍数)。全卷积架构(无 FC)使其成为可能,让模型对不同分辨率鲁棒。
九、预测流程:阈值过滤 + NMS
网络输出 10647 个预测框后,需筛出最终结果:
1 | ① 置信度过滤 |
NMS 流程(以保留 A、D 为例):
- 按类别概率排序剩余框,如 A > D > B > F > E > C;
- 取概率最大的 A,计算其余框与 A 的 IoU,IoU > 阈值者丢弃(B、C 与 A 重叠大被丢弃),保留 A;
- 从剩余框中再取最大的 D,重复上一步,保留 D;
- 直到所有框处理完,最终保留 A、D。
⚠️ NMS 的局限:若两个不同物体重叠很大(如狗压在自行车上),自行车的框可能因与狗框 IoU 过大被误删。改进方案有 Soft-NMS 等。
十、性能表现

10.1 COCO 数据集
| 模型 | mAP@0.5 | mAP@[0.5:0.95] | 推理时间 | FPS |
|---|---|---|---|---|
| YOLOv3-320 | 51.5 | 28.2 | 22 ms | 45 |
| YOLOv3-416 | 55.3 | 31.0 | 29 ms | 35 |
| YOLOv3-608 | 57.9 | 33.0 | 51 ms | 20 |
| SSD321 | 45.4 | 28.0 | 61 ms | 16 |
| SSD513 | 50.4 | 31.2 | 125 ms | 8 |
| RetinaNet-50-500 | 50.9 | 32.5 | 73 ms | 14 |
| RetinaNet-101-800 | 57.5 | 37.8 | 198 ms | 5 |
YOLOv3-608 与 RetinaNet-101 精度相当,速度快 3.8 倍;320 轻量版精度逼近 SSD513,速度快 5.7 倍。
注意:YOLOv3 在旧指标 mAP@0.5 上极强,但 mAP@[0.5:0.95] 随 IoU 阈值升高下降明显——说明它擅长”框出大概位置”,但框与目标精确对齐的能力较弱。
10.2 消融实验
| 配置 | mAP | 说明 |
|---|---|---|
| YOLOv2 baseline | 21.6 | COCO 基准 |
| + Darknet-53 | +2.2 | 残差骨干 |
| + FPN 多尺度 | +3.1 | 三尺度检测 |
| + 9 Anchor | +0.8 | 更多先验框 |
| + Logistic 分类 | +0.5 | 多标签 |
10.3 不同目标大小的表现
1 | AP_small AP_medium AP_large |
FPN 三尺度使小目标 AP 从 5.0 → 18.3,是 v3 最大亮点;但中大目标提升不如小目标显著。
十一、论文中”失败”的尝试
YOLOv3 论文的独特之处——作者诚实地记录了几个尝试了但没用的方法:
| 尝试 | 结果 | 原因 |
|---|---|---|
| 预测 $(x,y)$ 与 $(w,h)$ 的线性关系 | 不稳定 | 非线性关系更强 |
| 用线性激活替代 sigmoid 预测 $(x,y)$ | mAP ↓ | sigmoid 约束是必要的 |
| 使用 Focal Loss | mAP ↓ ~2 | YOLO 的正负样本比例和 RetinaNet 不同,已有独立 objectness 预测 |
| 双 IoU 阈值分配(仿 Faster R-CNN) | 效果不好 | 当前 1:1 分配已是局部最优 |
十二、优缺点与总结
优点 ✅
- 速度-精度最佳平衡:30 FPS @ 55 mAP,实际部署首选
- 小目标大幅改善:FPN 三尺度使小目标 AP 从 5.0 → 18.3
- 多标签支持:Sigmoid + BCE,贴合真实场景
- 全卷积无池化:更灵活、保留更多空间信息,支持任意尺寸输入
- 残差骨干可深可浅:Darknet-53 比 ResNet-101/152 更高效
- 工程生态成熟:Darknet(C)、PyTorch、Keras 多框架实现
局限 ❌
- 论文像”技术报告”:没有完整损失函数公式,需读源码
- Anchor 分配粒度粗:1 GT → 1 Anchor,密集场景有提升空间(v4/v5 改进)
- 置信度丢失 IoU 信息:改为二分类后,框质量无法从 confidence 区分(高质量框与低质量框 confidence 都是 1)
- 无数据增强创新:复用了 v2 的增强策略
- 大目标检测饱和:AP_large 从 35.5 → 41.9,提升不如小目标显著
- 高 IoU 阈值下精度下降:框对齐能力弱,mAP@[0.5:0.95] 不占优
总结
YOLOv3 的成功不靠单一突破,而是”融合经典方法 + 针对性优化”:架构上用”全卷积 + 残差连接”解决深层训练难题;检测逻辑上用”多尺度特征融合 + 9 种先验框”覆盖不同大小目标;预测逻辑上用”Logistic 激活”支持多标签。这些设计使其成为目标检测的经典基准,至今仍被广泛用于自动驾驶、安防、工业检测,也为 v4/v5 奠定基础。
十三、相关链接
- 📝 [[YOLO 系列总览]] - 版本对比总览
- 📝 [[YOLO 核心概念]] - Grid/Anchor/IoU/NMS 详解
- 📝 [[YOLOv1 详解]] - v1 基础
- 📝 [[YOLOv2 详解]] - v2 锚框 + BN 改进
- 📝 [[YOLOv4 详解]] - v4 在 v3 基础上的优化
- 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLO学习笔记3——YOLOv3详解]] - 知乎原文 (rtfff, 含 FPN 详解)
- 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/【YOLO系列】YOLOv3论文超详细解读(翻译 +学习笔记)-阿里云开发者社区]] - 论文翻译+精读
- 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/Yolov3算法详解]] - 博客园 (奥辰, 含 NMS 详解)
- 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLOv3 详解:核心改进、网络架构与目标检测实践_目标检测_2201_75691511-九章云极普惠算力]] - 核心改进总结
- 📦 [[30.resources/yolo-master/docs/Pytorch_YoLo_From_Scratch/v3/README|v3 From Scratch]]