YOLOv2 / YOLO9000: Better, Faster, Stronger

论文: YOLO9000: Better, Faster, Stronger (CVPR 2017)
作者: Joseph Redmon, Ali Farhadi


一、核心思想 —— v1→v2 的范式升级

YOLOv2 的关键变革:从「直接预测坐标」→「基于锚框预测偏移量」,同时引入一系列工程改进,在速度不变甚至更快的前提下,大幅提升召回率和定位精度。

1
2
3
4
5
6
7
YOLOv1:
输入 → CNN → FC → 直接输出 (x, y, w, h) ← 无先验,网络从零学坐标

YOLOv2:
输入 → CNN(全卷积) → 基于Anchor预测偏移量 (tx, ty, tw, th)

锚框: 预先聚类好的 5 种典型宽高比,给网络一个"好起点"

v1 的核心痛点 → v2 的解决:

v1 痛点 v2 解决 效果
定位精度差,召回率低 Anchor Box 机制 召回率 81%→88%
训练收敛慢 Batch Normalization mAP +2.4%
每格只能预测 1 个物体 Anchor 解耦:每个 Anchor 独立预测类别 密集场景大幅改善
小目标检测差 Passthrough 细粒度特征融合 mAP +1%
FC 层绑定分辨率 全卷积 + 多尺度训练 支持 320~608 任意输入
类别有限 (20类) YOLO9000 联合训练 + WordTree 可检测 9000+ 类

改进消融实验

论文中逐步叠加改进,清楚展示了每一项的贡献:

改进项 累积 mAP 单项增益
YOLOv1 基线 63.4%
+ Batch Normalization 65.8% +2.4
+ 高分辨率分类器 (448×448) 69.5% +3.7
+ Anchor Box (416×416) 69.2% -0.3 (但召回率↑)
+ 维度聚类 (K-means Anchor) 74.0% +4.8
+ 新网络 Darknet-19 73.2% -0.8
+ 直接位置预测 (sigmoid约束) 75.0% +1.8
+ Passthrough 细粒度特征 76.4% +1.4
+ 多尺度训练 77.9% +1.5
+ 高分辨率检测器 (544×544) 78.6% +0.7

📌 总计:从 63.4% 提升到 78.6%,+15.2 mAP——且保持了实时速度!


二、网络架构:Darknet-19

2.1 设计理念

设计原则 说明
3×3 卷积为主 类似 VGG,结构简单规整
池化后通道翻倍 每次 2× 下采样,通道数 ×2(128→256→512→1024)
1×1 降维卷积 置于 3×3 之间,压缩特征维度,减少计算量
BN 全覆盖 每个卷积层后、激活函数前都加 Batch Normalization
全局平均池化 替换 FC 层,消除固定分辨率限制
无 Dropout BN 自带正则化效果,移除 Dropout 也不怕过拟合

2.2 完整架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
输入: 416×416×3

┌─────────────────────────────────────────────────────┐
│ Conv 3×3×32 + BN + LeakyReLU │
│ MaxPool 2×2/2 → 208×208×32 │
├─────────────────────────────────────────────────────┤
│ Conv 3×3×64 + BN + LeakyReLU │
│ MaxPool 2×2/2 → 104×104×64 │
├─────────────────────────────────────────────────────┤
│ Conv 3×3×128 + BN + LeakyReLU ← 3个3×3卷积 │
│ Conv 1×1×64 + BN + LeakyReLU ← 1×1降维 │
│ Conv 3×3×128 + BN + LeakyReLU │
│ MaxPool 2×2/2 → 52×52×128 │
├─────────────────────────────────────────────────────┤
│ Conv 3×3×256 + BN + LeakyReLU ← 3个3×3卷积 │
│ Conv 1×1×128 + BN + LeakyReLU │
│ Conv 3×3×256 + BN + LeakyReLU │
│ MaxPool 2×2/2 → 26×26×256 │ ← ★ Passthrough 源
├─────────────────────────────────────────────────────┤
│ Conv 3×3×512 + BN + LeakyReLU ← 5个3×3卷积 │
│ Conv 1×1×256 + BN + LeakyReLU │
│ Conv 3×3×512 + BN + LeakyReLU │
│ Conv 1×1×256 + BN + LeakyReLU │
│ Conv 3×3×512 + BN + LeakyReLU │
│ MaxPool 2×2/2 → 13×13×512 │
├─────────────────────────────────────────────────────┤
│ Conv 3×3×1024 + BN + LeakyReLU ← 3个3×3卷积 │
│ Conv 1×1×512 + BN + LeakyReLU │
│ Conv 3×3×1024 + BN + LeakyReLU │
│ ↓ │
│ 13×13×1024 特征图 │
└─────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────┐
│ 检测头 (替换了v1的FC层): │
│ │
│ [Passthrough: 26×26×512 → 13×13×2048] ───┐ │
│ ├── Concat │
│ 13×13×1024 ────────────────────────────────┘ │
│ ↓ 13×13×3072 │
│ Conv 3×3×1024 + BN + LeakyReLU │
│ Conv 1×1×125 │
│ ↓ │
│ 输出: 13×13×125 张量 │
│ (5 Anchor × (4坐标 + 1置信度 + 20类别)) │
└─────────────────────────────────────────────────────┘

2.3 下采样过程

1
2
3
4
416×416 → Pool1 → 208×208 → Pool2 → 104×104
→ Pool3 → 52×52 → Pool4 → 26×26 → Pool5 → 13×13

最终特征图: 13×13 → 检测输出: 13×13×125

为什么输入是 416×416?

经过 5 次 2× 下采样 ($2^5 = 32$),$416 / 32 = 13$,得到奇数尺寸的特征图。
奇数尺寸保证有唯一的中心网格,大型物体(通常位于图像中心)只需一个网格来预测,而不是分散在四个相邻网格中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
偶数特征图 (如 14×14):
┌───┬───┐
│ │ │ 中心落在十字交叉点 → 4个网格争抢
├───┼───┤
│ │ │
└───┴───┘

奇数特征图 (如 13×13):
┌───┬───┬───┐
│ │ │ │
├───┼───┼───┤
│ │ ■ │ │ 中心落在唯一网格 → 1个网格负责 ✅
├───┼───┼───┤
│ │ │ │
└───┴───┴───┘

分类版 vs 检测版 Darknet-19

  • 分类版:最后一层为 global average pooling + softmax,输出 1000 类
  • 检测版:移除最后的 conv、avgpool、softmax → 新增 3 个 3×3×1024 conv + Passthrough + 1×1×(5×(5+C)) 卷积输出层

2.4 与 VGG-16 / YOLOv1 对比

网络 卷积层 计算量 ImageNet Top-1 ImageNet Top-5
VGG-16 16 306.9亿 73.0% 91.2%
YOLOv1 (类GoogLeNet) 24 ~85亿 88.0%
Darknet-19 19 55.8亿 72.9% 91.2%

Darknet-19:VGG 级别的精度,~1/6 的计算量,快 6 倍


三、图像预处理

3.1 输入处理流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
原始图像 (任意尺寸)

1. Resize: 缩放到 416×416 (保持宽高比,填充灰边)

2. Normalize: 像素值归一化到 [0, 1]
└── pixel = pixel / 255.0

3. 数据增强 (仅训练时):
├── 随机裁剪 + 缩放
├── 随机翻转 (水平)
├── 曝光调整: 随机改变亮度、对比度
├── 饱和度调整: HSV 空间 1.5× 扰动
└── 多尺度训练: 每10个batch随机切换输入分辨率 (见下文)

输入张量: [batch, 3, H, W] (H=W∈{320,352,...,608})

3.2 多尺度训练

YOLOv2 的全卷积设计使其可以接受任意尺寸输入。每 10 个 batch 随机改变输入分辨率,强制网络学会在不同尺度下检测。

1
2
3
4
5
6
7
8
9
训练过程中:
Batch 1-10: 320×320
Batch 11-20: 416×416 ← 随机!
Batch 21-30: 544×544
Batch 31-40: 384×384
...

尺寸范围: {320, 352, 384, 416, 448, 480, 512, 544, 576, 608}
(全部是 32 的倍数,确保整除 2^5)

效果:同一网络在推理时可以灵活选择分辨率,在速度和精度间做折中。


四、Anchor Box 机制详解 🔥🔥🔥

这是 YOLOv2 最核心的变革。从 v1 的「一张白纸直接画」变成「给我一个模板,我来微调」。

4.1 为什么需要 Anchor Box?

1
2
YOLOv1:  网络看到图片 → 从零猜测物体在哪里 → 前期训练极其困难
YOLOv2: 网络看到图片 → 锚框说"物体大概长这样"→ 只需微调偏移量 → 快速收敛
对比维度 YOLOv1 (无Anchor) YOLOv2 (有Anchor)
坐标预测 直接输出 (x, y, w, h) 输出相对于锚框的偏移 (tx, ty, tw, th)
先验知识 无,网络从零学 有,聚类得到的 5 种典型形状
每格预测数 2 个 BBox 5 个 Anchor Box
类别预测 每格 1 组类别(共享) 每个 Anchor 独立预测类别
总预测框 7×7×2 = 98 13×13×5 = 845
召回率 (框多了!)

4.2 Anchor Box 工作原理

1
2
3
4
5
6
7
8
9
10
11
一张 416×416 图片 → 13×13 网格 → 每个网格预置 5 个锚框

网格 (cx, cy) 的 5 个 Anchor:
Anchor 1: 细长竖框 (w=0.57, h=1.72) ← 适合站着的人
Anchor 2: 宽扁横框 (w=1.88, h=0.88) ← 适合横躺的车
Anchor 3: 中等方框 (w=1.16, h=2.19) ← 适合坐着的狗
Anchor 4: 小方块 (w=0.37, h=0.57) ← 适合远处的鸟
Anchor 5: 大方块 (w=3.45, h=4.17) ← 适合近处的大物体

网络的任务: 对每个Anchor,输出一个微调量 (tx, ty, tw, th)
"这个锚框再往右移一点、变宽一点,就能框住目标了"

4.3 直接位置预测(Direct Location Prediction)

YOLOv2 没有直接套用 Faster R-CNN 的 Anchor 公式,而是加了一个关键约束:sigmoid 限制中心点在网格内

Faster R-CNN 的 Anchor 公式(无约束)
$$x = (t_x \times w_a) + x_a$$
$$y = (t_y \times h_a) + y_a$$

❌ 问题:$t_x, t_y$ 无范围限制,预测框的中心可以跑到图的任意位置,训练初期极其不稳定。

YOLOv2 的改进公式(sigmoid 约束)

$$b_x = \sigma(t_x) + c_x$$
$$b_y = \sigma(t_y) + c_y$$
$$b_w = p_w \cdot e^{t_w}$$
$$b_h = p_h \cdot e^{t_h}$$

$$\text{confidence} = \sigma(t_o)$$

符号 含义
$t_x, t_y, t_w, t_h, t_o$ 网络原始输出(5 个值 per anchor)
$\sigma(t_x), \sigma(t_y)$ sigmoid 后 ∈ (0, 1),相对于网格左上角的偏移
$c_x, c_y$ 当前网格的整数坐标(左上角在特征图中的位置,如 (0,0), (0,1), …, (12,12))
$p_w, p_h$ 该 Anchor 的预设宽高(由 K-means 聚类得到)
$b_x, b_y, b_w, b_h$ 解码后的实际预测框坐标

4.4 坐标解码图解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
特征图 13×13,设当前网格坐标为 (cx=3, cy=2),Anchor 宽高为 (pw, ph)

σ(tx)
←──→
┌─────────────┐
│ │
│ ■ │ ■ = (bx, by) = (cx + σ(tx), cy + σ(ty))
│ (cx,cy) │
└─────────────┘

bw = pw × e^(tw) ← 在锚框宽度基础上指数缩放
bh = ph × e^(th) ← 在锚框高度基础上指数缩放

关键: σ(tx) ∈ (0,1) → 中心点永远在网格 (cx,cy) 内部!

数学直观

  • $\sigma(t_x) = 0.5$ → 中心在网格正中
  • $\sigma(t_x) \approx 0$ → 中心紧贴网格左边界
  • $\sigma(t_x) \approx 1$ → 中心紧贴网格右边界
  • $e^{t_w} = 1 \ (t_w=0)$ → 宽度 = Anchor 宽度(不变)
  • $e^{t_w} > 1 \ (t_w>0)$ → 变宽
  • $e^{t_w} < 1 \ (t_w<0)$ → 变窄

4.5 输出张量结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
YOLOv2 (VOC, 20类, 5 Anchor):
13×13×125

125 的构成 (per grid cell):
┌──────────────────────────────────────────────────────┐
│ Anchor 1: tx ty tw th to | p1 p2 ... p20 │ ← 25 维
│ Anchor 2: tx ty tw th to | p1 p2 ... p20 │ ← 25 维
│ Anchor 3: tx ty tw th to | p1 p2 ... p20 │ ← 25 维
│ Anchor 4: tx ty tw th to | p1 p2 ... p20 │ ← 25 维
│ Anchor 5: tx ty tw th to | p1 p2 ... p20 │ ← 25 维
└──────────────────────────────────────────────────────┘
5 × 25 = 125

与 v1 的关键区别:
v1: 每格只有 1 组类别概率(两个 BBox 共享)
v2: 每个 Anchor 都有自己独立的 20 类概率!
→ 同一网格内的不同 Anchor 可以预测不同类别 ✅

置信度定义(与 v1 一致):
$$\text{confidence} = \text{Pr(Object)} \times \text{IoU}_{pred}^{truth}$$

推理时,$\sigma(t_o)$ 直接输出 confidence。


五、维度聚类 (Dimension Clusters) 🔑

不再手工设定 Anchor 尺寸,而是用 K-means 聚类从训练集 GT 框中自动发现最佳锚框形状。

5.1 为什么用 K-means?

1
2
3
4
5
Faster R-CNN: 手工挑选 9 种 Anchor (3尺度 × 3比例)
问题: 手工选的未必适合当前数据集

YOLOv2: K-means 聚类
优势: 自动从训练数据中"学"出最具代表性的框形状

5.2 自定义距离度量

⚠️ 不能直接用欧氏距离! 大框的欧氏距离天然大于小框,聚类会偏向大框。

YOLOv2 的距离公式
$$d(\text{box}, \text{centroid}) = 1 - \text{IoU}(\text{box}, \text{centroid})$$

1
2
3
4
5
6
7
8
9
为什么不用欧氏距离?
大框 (100×100) 和 (105×105): 欧氏距离大 → 聚类时被"重点关注"
小框 (10×10) 和 (15×15): 欧氏距离小 → 聚类时被"忽视"
但实际上小框的 5 像素偏差影响更大!

用 1 - IoU:
大框 IoU=0.9 → 距离=0.1
小框 IoU=0.5 → 距离=0.5 ← 被正确聚类到不同组 ✅
IoU 天然是尺度无关的,完美解决大小框不平衡问题!

5.3 K 值选择

K 值 方法 平均 IoU
5 YOLOv2 K-means 61.0%
9 Faster R-CNN 手工 60.9%
9 YOLOv2 K-means 67.2%

YOLOv2 仅用 5 个锚框就超过了 Faster R-CNN 的 9 个手工锚框
K=5 是精度和速度的最佳平衡点。更多 Anchor → 更多计算 → 但精度提升递减。

5.4 VOC/COCO 聚类结果

以下数值为相对于特征图尺寸(13×13,每格视为 1×1 单位)的宽高。

Anchor # VOC 2007 (w, h) COCO (w, h) 适合检测
1 (1.32, 1.73) (0.57, 0.68) 中等偏高物体(人)
2 (3.19, 4.01) (1.87, 2.06) 中大物体(站立的人/狗)
3 (5.06, 8.10) (3.34, 5.47) 高瘦物体(站着的人)
4 (9.47, 4.84) (7.88, 3.53) 宽扁物体(横躺的车)
5 (11.24, 10.01) (9.77, 9.17) 超大物体(近处主目标)

转换为像素尺寸(416×416 输入):乘以网格宽度 $416/13 \approx 32$
如 VOC Anchor 1: 1.32×32 ≈ 42px 宽,1.73×32 ≈ 55px 高


六、预测阶段(前向推断)详解

6.1 完整推理流程

1
2
3
4
5
6
Step 1: Resize image → 416×416 (或其他 32 的倍数)
Step 2: Run Darknet-19 → 输出 13×13×125 张量
Step 3: 解码每个 Anchor 的偏移 → 得到实际 BBox 坐标
Step 4: 计算 class-specific confidence score
Step 5: 阈值过滤 → 低分框置零
Step 6: NMS 去重 → 得到最终检测结果

6.2 网格划分策略

将输入图像划分为 13×13 = 169 个网格

核心规则(与 v1 一致):物体中心点落在哪个网格,该网格负责预测该物体。

但与 v1 不同的是:该网格内的 5 个 Anchor 中,与 GT 框 IoU 最大的那个 Anchor 负责预测。

1
2
3
4
5
6
7
┌───────────────────┐
│ │ │ │ │ │
│───┼───┼───┼───┼───│
│ │ │ ● │ │ │ ← ● = 物体中心点
│───┼───┼───┼───┼───│ 网格(2,3)的5个Anchor中
│ │ │ │ │ │ IoU最大的那个负责预测
└───────────────────┘ 此物体

6.3 每个网格的预测内容

每个网格预测 B=5 个 Anchor Box

内容 每个 Anchor 5个Anchor合计
坐标偏移 $t_x, t_y, t_w, t_h$ (4个值) 20 个值
置信度 $\sigma(t_o)$ (1个值) 5 个值
类别概率 $P(class_i \mid Object)$ (20个值) 100 个值
总计 25 个值/Anchor 125 个值/网格

整张图产生: 13×13×5 = 845 个预测框(v1 仅 98 个!)

6.4 坐标解码(输入尺寸归一化)

最终需要将预测框坐标归一化到图像尺寸(便于后处理):

设图像宽度为 $W$,高度为 $H$,网格宽度 $g_w = W/13$,网格高度 $g_h = H/13$:

$$\text{pixel_x_center} = (c_x + \sigma(t_x)) \times g_w$$
$$\text{pixel_y_center} = (c_y + \sigma(t_y)) \times g_h$$
$$\text{pixel_width} = p_w \cdot e^{t_w} \times g_w$$
$$\text{pixel_height} = p_h \cdot e^{t_h} \times g_h$$

实际实现中常用相对坐标(除以图像宽高),此处展示像素级换算以便理解。

6.5 Class-Specific Confidence Score

与 v1 的公式一致,但含义因 Anchor 而不同。

$$\text{Score} = P(Class_i \mid Object) \times \text{confidence}$$
$$= \underbrace{P(Class_i \mid Object)}{\text{该Anchor预测的类别概率}} \times \underbrace{\sigma(t_o)}{\text{该Anchor的置信度}}$$

1
2
3
4
5
6
7
8
9
10
11
具体计算 (每个网格):
Anchor1: Score[dog] = P1(dog|Object) × σ(to1)
Anchor1: Score[car] = P1(car|Object) × σ(to1)
Anchor2: Score[dog] = P2(dog|Object) × σ(to2)
Anchor2: Score[car] = P2(car|Object) × σ(to2)
...
Anchor5: Score[dog] = P5(dog|Object) × σ(to5)

关键差异 vs v1:
v1: 同一网格两个BBox共享类别概率 → 两个框只能预测同一个类别
v2: 每个Anchor独立预测类别 → 同一网格可同时检测狗和猫!✅

整张图产生: 13×13×5×20 = 16,900 个分数


七、IoU 计算方法

基本计算流程与 [[YOLOv1 详解#五、IoU 计算方法|YOLOv1 §五]] 完全一致,此处不再重复。

YOLOv2 中 IoU 的额外用途

用途 何时 说明
训练时选 Anchor 反向传播 5 个 Anchor 中与 GT IoU 最大的那个负责定位损失
K-means 距离 Anchor 聚类 $d = 1 - \text{IoU}$ 作为聚类距离
NMS 去重 推理后处理 同 v1

八、NMS(非极大值抑制)处理流程

同 [[YOLOv1 详解#六、NMS(非极大值抑制)处理流程|YOLOv1 §六]],唯一变化是预测框数量从 98 → 845 个。

1
2
3
4
5
6
7
8
逐类别 NMS 步骤:
Step 1: 得分过滤 — score < threshold → 移除
Step 2: 按得分降序排列
Step 3: 取最高分框,抑制与其 IoU > 0.5 的其他框
Step 4: 在剩余框中重复 Step 3
Step 5: 处理下一个类别

与 v1 相比: 输入框更多(845 vs 98),但流程完全相同

九、训练阶段(反向传播)详解

9.1 训练参数设定

参数 含义
网格数 13×13 特征图尺寸
B (Anchor 数) 5 每网格 5 个锚框
C 20 (VOC) / 80 (COCO) 类别数
输入尺寸 多尺度 (320~608) 每 10 batch 随机换
输出张量 13×13×(5×(5+C)) e.g. VOC → 13×13×125

9.2 检测框分配机制 —— Anchor 时代的核心 🔥🔥🔥

YOLOv2 的分配机制比 v1 多了一层:网格分配 → Anchor 分配

1
2
3
4
5
6
7
层次化分配流程:

Step 1 — 网格分配 (同 v1):
物体中心落在哪个网格 → 该网格负责

Step 2 — Anchor 分配 (v2 新增!):
该网格的 5 个 Anchor 中 → 与 GT 框 IoU 最大的那个 "当选"

第一步:网格分配 —— 谁”拥有”这个物体?

与 v1 完全一致:只看物体的几何中心点。

1
物体中心在格(6,4) → 格(6,4)负责 → 它的5个Anchor进入第二步竞争

第二步:Anchor 分配 —— 谁来”干活”?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
网格(6,4) 有 5 个 Anchor (预聚类得到的5种形状):
Anchor 1 (0.6, 1.7): 与 GT IoU = 0.45 ❌
Anchor 2 (1.9, 0.9): 与 GT IoU = 0.23 ❌
Anchor 3 (1.2, 2.2): 与 GT IoU = 0.67 ✅ 当选! (responsible anchor)
Anchor 4 (0.4, 0.6): 与 GT IoU = 0.12 ❌
Anchor 5 (3.5, 4.2): 与 GT IoU = 0.71 ← 等等! 这个更高! ✅ 当选!

Anchor 5 与 GT 框的 IoU 最大 → "responsible anchor"

Anchor 5 的职责(Responsible Anchor):
├── 预测位置偏移 (tx, ty, tw, th) → 参与位置损失
├── 预测置信度 to → 参与置信度损失 (target = IoU)
└── 预测类别 → 参与分类损失 (target = GT 类别 one-hot)

其他 4 个 Anchor —— 分为两种处理:
① IoU > ignore_thresh (0.6): 不参与任何损失 (完全忽略!)
└── 因为预测得"还不错",只是不是最好的,不去惩罚它
② IoU < ignore_thresh (0.6): 参与置信度损失 (target = 0)
└── 预测得太差 → "你要知道这里没有你要负责的物体"

注意: 非 Responsible Anchor 都不参与位置和类别损失

第三步:完整分配链示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
假设一张训练图有 3 个物体: 狗(中心在格(2,4))、车(在格(7,3))、人(在格(10,8))

═══ 169个网格中:
3个网格"有责" (包含物体中心)
166个网格"无责"
═══

网格(2,4) - 负责"狗"(GT长宽比约 1:1.5):
Anchor 1 (0.6, 1.7): IoU=0.75 → ★ Responsible! 学习预测 (tx,ty,tw,th)
Anchor 3 (1.2, 2.2): IoU=0.62 → >0.6 阈值 → ★ 忽略 (不参与任何损失)
Anchor 2,4,5: IoU < 0.6 → confidence 监督为 0
类别: [狗=1, 车=0, 人=0, ...] (仅 Anchor 1 学习分类)

网格(7,3) - 负责"车"(GT长宽比约 2:1):
Anchor 2 (1.9, 0.9): IoU=0.68 → ★ Responsible!
Anchor 1,4 (IoU≈0.3~0.5): → confidence 监督为 0
Anchor 3,5 (IoU≈0.1): → confidence 监督为 0
类别: [狗=0, 车=1, 人=0, ...]

网格(10,8) - 负责"人"(GT长宽比约 1:2.5):
Anchor 3 (1.2, 2.2): IoU=0.72 → ★ Responsible!
Anchor 1 (0.6, 1.7): IoU=0.63 → >0.6 阈值 → ★ 忽略
Anchor 2,4,5: → confidence 监督为 0
类别: [狗=0, 车=0, 人=1, ...]

其余 166 个网格:
每个网格的 5 个 Anchor → confidence 全部监督为 0 (无物体,全部→0)
不参与位置损失和类别损失

v2 分配 vs v1 分配的对比

对比维度 YOLOv1 YOLOv2
每格几选一? 2 个 BBox 中 IoU 最大者 5 个 Anchor 中 IoU 最大者
类别归属 网格级别(两框共享) Anchor 级别(独立)
同格多类可行? ❌ 不行 ✅ 可以
每格最多检出 1 个物体 5 个物体 (每Anchor一个)

9.3 训练时的 Ground Truth 构造

基于以上分配机制,构造 13×13×(5×(5+C)) 的 target 张量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
对于坐标为 (i, j) 的网格,有 5 个 Anchor:

├── 如果该网格包含物体中心 + 此 Anchor 是 IoU 最大者 (Responsible):
│ ├── tx_target: GT 中心相对于该网格左上角的偏移 (需反算)
│ │ (因为训练时网络输出 tx, 而 GT 给出的是实际坐标)
│ ├── ty_target: 同上
│ ├── tw_target: log(GT_w / pw) ← 反算: 让 e^(tw) × pw = GT_w
│ ├── th_target: log(GT_h / ph)
│ ├── to_target: IoU(pred, GT) ← 动态计算! (rescore=1 时)
│ └── class[gt_label] = 1 (one-hot)

├── 如果该网格包含物体中心 + 此 Anchor 不是 Responsible:
│ ├── 若 IoU > ignore_thresh (0.6): ★ 完全忽略,不计算任何损失
│ └── 若 IoU < ignore_thresh (0.6): to_target = 0 (仅置信度→0)

└── 如果该网格不包含物体中心:
└── 5个Anchor的 to_target = 0 (都不参与位置和类别损失)

9.4 训练时的 Confidence 计算细节

⚠️ 与 v1 同样:训练时 confidence 的 GT 是动态变化的!

情况 Confidence GT / 处理 说明
有物体的网格 + Responsible Anchor $\hat{C} = \text{IoU}_{pred}^{truth}$ rescore=1 时动态计算;rescore=0 时 $\hat{C}=1$
有物体的网格 + 非 Responsible (IoU > 0.6) 完全忽略 不计算任何损失!预测得还行,不惩罚
有物体的网格 + 非 Responsible (IoU < 0.6) $\hat{C} = 0$ 预测太差,confidence→0(仅置信度损失)
无物体的网格 + 所有 Anchor $\hat{C} = 0$ 全部 confidence→0

⚠️ 关键区别 vs v1:v1 所有非最佳 BBox 的 confidence 都→0。v2 中,IoU > 0.6 的框完全忽略——因为它们其实预测得还行,强行惩罚反而干扰训练。

9.5 损失函数 —— 完整版本 🔥🔥🔥

YOLOv2 的损失函数并非论文直接给出,以下是基于 Darknet 源码和社区分析的完整版。相比 v1 有三大关键变化:忽略阈值、前期 anchor 预热、小框权重修正。

$$\mathcal{L} = \underbrace{\lambda_{noobj}\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}_{ij}^{noobj}(C_i-\hat{C}i)^2}{\text{① 背景框的置信度损失(Max IOU < 0.6),}\hat{C}_i=0}$$

$$+ \underbrace{\lambda_{prior}\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}^{<12800}\left[(t_x-\hat{t}_x)^2+(t_y-\hat{t}_y)^2+(t_w-\hat{t}_w)^2+(t_h-\hat{t}h)^2\right]}{\text{② Anchor 先验损失(仅前12800次迭代),让预测快速学会锚框形状}}$$

$$+ \underbrace{\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}{ij}^{obj}\Bigg[\lambda{coord} \cdot (2 - w_{gt} \cdot h_{gt}) \cdot \big((t_x-\hat{t}x)^2+(t_y-\hat{t}y)^2\big)\Bigg]}{\text{③ 负责Anchor的中心偏移损失(小框通过 }(2-w{gt}h_{gt})\text{ 获得更大权重)}}$$

$$+ \underbrace{\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}{ij}^{obj}\Bigg[\lambda{coord} \cdot (2 - w_{gt} \cdot h_{gt}) \cdot \big((t_w-\hat{t}_w)^2+(t_h-\hat{t}h)^2\big)\Bigg]}{\text{④ 负责Anchor的宽高偏移损失(同样小框获得更大权重)}}$$

$$+ \underbrace{\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}_{ij}^{obj}(C_i-\hat{C}i)^2}{\text{⑤ 负责Anchor的置信度损失, }\hat{C}_i=\text{IoU (rescore=1时) 或 1 (rescore=0时)}}$$

$$+ \underbrace{\sum_{i=0}^{S^2}\sum_{j=0}^{B}\mathbb{1}{ij}^{obj}\sum{c \in classes}(p_i(c)-\hat{p}i(c))^2}{\text{⑥ 负责Anchor的类别概率损失}}$$

关键机制详解

① 背景框判定(Ignore Thresh)

1
2
3
4
5
6
7
8
对每个预测框,计算它和所有 GT 框的 IoU,取最大值 Max_IOU:
Max_IOU < 0.6 → 标记为 background → 计算 noobj 置信度损失(target=0)
Max_IOU ≥ 0.6 → ★ 不计算任何损失(被忽略)—— 但前提是该框不是 Responsible Anchor

为什么要有 ignore_thresh?
如果某个预测框其实框得还不错(IoU≥0.6),只是不如另一个 Anchor 好,
强行让它 confidence→0 会"惩罚一个基本正确的预测",反而让训练不稳定。
→ 所以直接忽略它,让它"自由发挥"。

② Anchor 先验损失(Warmup)

1
2
3
4
5
6
7
仅在前 12800 次迭代中生效。
目的: 训练初期让预测框快速学会锚框的基本形状,而不是从随机开始乱跑。

tx, ty, tw, th 全部参与位置损失(不管是不是 Responsible Anchor),
相当于训练早期强制所有预测框"靠近各自的 Anchor 模板"。

12800 次迭代后,这部分损失归零,只靠正常的位置损失继续训练。

③④ 小框权重修正 —— 替代 v1 的开根号

1
2
3
4
5
6
7
v1 对 w,h 开根号缓解大小框不平衡。
v2 采用更直接的方法: 权重系数 = (2 - w_gt × h_gt)

大框: w_gt=0.8, h_gt=0.8 → 权重 = 2 - 0.64 = 1.36
小框: w_gt=0.1, h_gt=0.1 → 权重 = 2 - 0.01 = 1.99 ← 约 1.5× 大框的权重!

效果: 小框预测偏差 1 像素的惩罚 ≈ 大框同样偏差的 1.5 倍 → 更关注小物体定位!

⑤ rescore 参数

1
2
3
4
5
rescore=1 (默认): 置信度 target = 预测框与 GT 的实时 IoU
→ "你的 confidence 应该反映你当前预测得有多准"

rescore=0: 置信度 target = 1
→ 简单的二分类:"有物体就是 1"

⑥ bias_match=1

1
2
3
在计算 Anchor 与 GT 的 IoU 来分配 Responsible Anchor 时:
先将 Anchor 和 GT 的中心都移到 (0,0),只在原点比较形状匹配度
→ 纯按形状选 Anchor,不受位置影响

完整的损失参与矩阵

1
2
3
4
5
6
7
8
9
10
11
每个预测框参与哪些损失?

位置损失 置信度损失 类别损失
──────── ──────── ────────
Responsible Anchor: ✅ ✅ ✅
(warmup 前12800次: 全部Anchor → 位置损失 ✅)

Ignore (IoU>0.6,非Resp): ❌ ❌ ❌ ← 完全忽略!
Background (IoU<0.6): ❌ ✅(→0) ❌

无物体网格全部Anchor: ❌ ✅(→0) ❌

与 v1 损失函数的关键区别

区别 YOLOv1 YOLOv2
位置损失目标 直接回归 (x,y,w,h) 回归偏移量 (tx,ty,tw,th)
大小框平衡 w,h 开根号 $(2 - w_{gt} \cdot h_{gt})$ 权重系数
非最佳框处理 全部 confidence→0 IoU>0.6 忽略,IoU<0.6 →0
训练早期稳定 无特殊处理 前12800次迭代 Anchor 先验损失
置信度 target 固定 IoU rescore=0→1, rescore=1→动态IoU
类别损失 网格级别(每格1组) Anchor 级别(独立)
Anchor匹配 bias_match=1,仅按形状匹配

9.6 损失函数权重

参数 原因
λ_coord 5 定位权重,定位比分类更重要
λ_noobj 0.5 无目标置信度惩罚权重(845个框中绝大多数是背景)
λ_prior 0.01 Anchor 先验损失权重(warmup 阶段,不宜太大)
ignore_thresh 0.6 IoU > 此值的非 Responsible 框完全忽略

9.7 训练流程伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 简化版 YOLOv2 训练循环

for iteration in range(total_iterations):
for images, targets in dataloader: # images: [B,3,H,W], H,W 可变

# 多尺度训练: 每10个batch随机切换输入尺寸
if batch_idx % 10 == 0:
new_size = random.choice([320,352,384,416,448,480,512,544,576,608])
resize_images(new_size)

# 1. 前向传播
predictions = model(images) # [B, 13, 13, 125]

# 2. 计算每个预测框与所有 GT 的最大 IoU (用于 ignore 判定)
for each predicted box:
max_iou = max(IoU(pred_box, gt) for gt in all_GTs)

# 3. 逐网格计算损失
for each grid cell (i,j) in 13×13:
for each anchor k in 5:
tx, ty, tw, th, to = predictions[i,j, k*25 : k*25+5]
class_probs = predictions[i,j, k*25+5 : (k+1)*25]

# [Warmup] 前12800次迭代: 所有 Anchor 都参与位置先验损失
if iteration < 12800:
prior_loss += λ_prior × ((tx - anchor_tx)^2 + ...)

if object_center_in_cell(i,j):
# ★ 按形状匹配选 Responsible Anchor (bias_match=1)
# 将 Anchor 和 GT 中心都移到原点后再算 IoU
shape_iou = compute_shape_iou(anchor[k], gt_box)
if k == argmax(shape_iou): # Responsible!
loc_loss += λ_coord × (2-w_gt×h_gt) × ((tx-tx_gt)^2 + ...)
conf_loss += (σ(to) - IoU_pred_gt)^2 # rescore=1
cls_loss += (class_probs - gt_onehot)^2
else:
# 无物体网格: 全为背景
conf_loss += λ_noobj × (σ(to) - 0)^2

# ★ Ignore 机制: Max_IOU ≥ 0.6 且非 Responsible → 不计算任何损失
if max_iou >= 0.6 and not is_responsible:
pass # 完全忽略!

# 4. 总损失
total_loss = prior_loss + loc_loss + conf_loss + cls_loss

# 5. 反向传播 + 优化
total_loss.backward()
optimizer.step()

十、各项改进深度解析

10.1 Batch Normalization(批量标准化)🔑

位置: 每个卷积层后、激活函数前
效果: mAP +2.4%,可去掉 Dropout

公式
$$\hat{x}^{(k)} = \frac{x^{(k)} - \mu_{batch}}{\sqrt{\sigma_{batch}^2 + \epsilon}}$$
$$y^{(k)} = \gamma^{(k)}\hat{x}^{(k)} + \beta^{(k)}$$

参数 含义
$\mu_{batch}$ 当前 batch 的均值
$\sigma_{batch}^2$ 当前 batch 的方差
$\gamma, \beta$ 可学习的缩放和偏移参数
$\epsilon$ 防止除零的小常数

为什么 BN 能加速训练?

1
2
3
4
5
6
7
8
没有 BN:  每层输入分布随前层参数更新而漂移 (Internal Covariate Shift)
→ 每层都要"适应"新的输入分布
→ 学习率不敢太大,收敛慢

有了 BN: 每层输入被标准化为均值0、方差1
→ 各层相对独立,不受前层参数变化影响
→ 学习率可以更大,收敛更快
→ 自带轻微正则化,可移除 Dropout

10.2 高分辨率分类器 (High Resolution Classifier)

v1 的问题:分类预训练用 224×224,检测微调突然跳到 448×448 → 网络要同时适应分辨率变化和学习检测。

1
2
3
4
5
6
7
8
9
10
11
YOLOv1 的训练流程:
① ImageNet 预训练: 224×224 (分类) ┐
② 检测微调: 448×448 (检测) ├── 分辨率突变! 网络不适应


YOLOv2 的训练流程:
① ImageNet 预训练: 224×224 (分类)
② 高分辨率微调: 448×448 (分类, 仅10 epoch) ← ★ 让网络先"熟悉"高分辨率
③ 检测微调: 416×416 (检测)

效果: mAP +3.7%

10.3 Passthrough Layer(细粒度特征融合)

问题: 13×13 特征图对小物体来说太粗糙了,一个网格覆盖 32×32 像素区域,小鸟可能只占几个像素。

解决: 把浅层的高分辨率特征”搬运”到检测层。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
Passthrough 操作 (也叫 Space-to-Depth / Reorg):

浅层特征图: 26×26×512

将每个 2×2 局部区域展开为深度维度:

26×26×512 → 拆分为 → 13×13×2048
(2×2空间区域 × 512通道 = 4×512 = 2048)

示意 (单通道):
原始 4×4: 拆分后 2×2×4:
┌──┬──┬──┬──┐ ch1 ch2 ch3 ch4
│a1│a2│b1│b2│ ┌──┬──┐┌──┬──┐┌──┬──┐┌──┬──┐
├──┼──┼──┼──┤ │a1│b1││a2│b2││c1│d1││c2│d2│
│a3│a4│b3│b4│ → └──┴──┘└──┴──┘└──┴──┘└──┴──┘
├──┼──┼──┼──┤
│c1│c2│d1│d2│
├──┼──┼──┼──┤
│c3│c4│d3│d4│
└──┴──┴──┴──┘

拼接流程:
26×26×512 ──Passthrough──→ 13×13×2048 ┐
├── Concat → 13×13×3072 → 检测
13×13×1024 (深层语义特征) ──────────────────┘

> ⚠️ **论文 vs 实现**: 论文描述直接对 26×26×512 做 passthrough → 13×13×2048。但部分源码实现中,为了减少计算量,会先用 **1×1 卷积**将 512 通道压缩到 64 通道,再做 passthrough → 13×13×256,最终 concat 得到 13×13×1280。两种方式的原理一致(特征融合),只是通道数不同。

效果: 小目标检测 mAP +1%,尤其对密集小物体场景改善明显

10.4 多尺度训练

YOLOv2 去掉 FC 层后变成全卷积网络 → 可以接受任意尺寸输入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
训练策略:
每 10 个 batch (不是 10 个 epoch!):
随机选择新的输入尺寸 ∈ {320, 352, 384, 416, 448, 480, 512, 544, 576, 608}
重新 resize 输入图片,然后继续训练
由于只有卷积和池化层,直接改输入尺寸不需重建网络

推理策略 (速度/精度折中):
┌─────────────┬───────┬───────┐
│ 输入分辨率 │ mAP │ FPS │
├─────────────┼───────┼───────┤
│ 288×288 │ 69.0% │ 91 │ ← 追求速度
│ 352×352 │ 73.7% │ 81 │
│ 416×416 │ 76.8% │ 67 │ ← 平衡点
│ 480×480 │ 77.8% │ 59 │
│ 544×544 │ 78.6% │ 40 │ ← 追求精度
└─────────────┴───────┴───────┘

同一个模型,检测时只需改输入尺寸,无需重新训练!

十一、YOLO9000:检测 9000+ 类别

YOLOv2 是检测网络,YOLO9000 是在其基础上的训练方法论创新——联合训练检测+分类数据,使模型能检测远超检测数据集标注范围的类别。

⚠️ YOLO9000 网络调整:为控制输出尺寸,Anchor 数从 5 减至 3,每个 Anchor 需预测 $4+1+9418=9423$ 个值 → 每网格 $3\times9423=28269$,特征图 $13\times13\times28269$。

11.1 核心挑战

1
2
3
4
5
6
7
8
检测数据集 (如 COCO):  有框+类别 → 可训练定位+分类 → 但类别少 (80类)
分类数据集 (如 ImageNet): 有类别 → 可训练分类 → 类别多 (22K类)

问题: 怎么同时利用两类数据?
- 分类数据没有框 → 不能训练定位
- 检测数据和分类数据的类别体系不同

YOLO9000 的方案: WordTree + 联合训练

11.2 WordTree 层次分类

将 ImageNet 和 COCO 的类别组织成一个树形层次结构(基于 WordNet)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
WordTree 示意:

┌── 梗犬 ─── 苏格兰梗
│ ─── 约克夏梗
┌── 猎犬 ───┼── 指示犬
│ └── ...

┌── 动物 ───┼── 鸟类 ─── 鸵鸟
│ │ ─── 鸡
│ └── ...

│ ┌── 轿车
│ │
物体 ──┼── 车辆 ───┼── 卡车
│ │
│ └── 巴士

│ ┌── 苹果
└── 水果 ───┼── 香蕉
└── ...

关键特性:
- 每个节点有概率 P(node) = P(node | parent) × P(parent)
- 根节点概率 = 1
- 用层次 Softmax: 每个层级独立做 softmax,而非在全部 9000+ 类上做

11.3 联合训练策略

1
2
3
4
5
6
7
8
9
10
11
12
训练时混合两个数据源:

检测数据 (COCO, 有框):
→ 正常反向传播整个损失函数 (位置 + 置信度 + 分类)
→ 分类损失传播到 WordTree 中对应的叶子节点及其祖先

分类数据 (ImageNet, 无框):
→ 只反向传播分类损失 (没有位置损失!)
→ 把分类标签映射到 WordTree 中对应的路径
→ 这样即使没有框,模型也能学会识别更多类别

结果: 可检测 9418 个类别 (远超任一检测数据集的标注范围!)

11.4 YOLO9000 性能

数据集 能力
COCO (80类) mAP 较低 (训练数据不足),但概念验证成功
ImageNet Detection (200类) 19.7 mAP
未在检测数据中见过的 156 类 16.0 mAP ← 零样本检测!

十二、优缺点深度分析

优点 ✅

  1. 实时性顶级: 67 FPS @ 76.8 mAP,91 FPS @ 69.0 mAP(当时最快)
  2. 召回率大幅提升: Anchor Box 机制使候选框从 98→845,召回率 81%→88%
  3. 多尺度灵活: 同一模型可在 320~608 间自由切换,精度/速度灵活折中
  4. 小目标改善: Passthrough 层保留细粒度空间信息
  5. 训练高效: BN 加速收敛,K-means Anchor 减少无效搜索
  6. 全卷积设计: 不受固定输入尺寸限制
  7. YOLO9000 泛化能力: 可检测训练中未见过的类别(零样本检测)

局限 ❌

  1. 单尺度特征图检测: 只在 13×13 一层上预测,对不同尺度目标覆盖不足(v3 改进为 3 尺度 FPN)
  2. 小目标仍不理想: Passthrough 缓解但未根治(不像 v3 有专门的大尺度检测层)
  3. Anchor 仍需手工 K 值: K=5 是经验选择,不同数据集可能需要不同 K
  4. 损失函数仍用 SSE: 分类和置信度用均方误差不如交叉熵合理(v3 改进)
  5. 每 Anchor 独立分类: 5 个 Anchor 各自做 softmax → 同一网格可能对同一物体输出多个类
  6. 无残差连接: Darknet-19 是纯 VGG 风格,深层梯度传递不如 ResNet(v3 引入残差)

十三、性能表现

13.1 VOC 2007

模型 mAP FPS
YOLOv1 63.4% 45
Fast R-CNN 70.0% 0.5
Faster R-CNN (VGG-16) 73.2% 7
Faster R-CNN (ZF) 62.1% 17
SSD300 74.3% 46
SSD500 76.8% 19
YOLOv2 288×288 69.0% 91
YOLOv2 352×352 73.7% 81
YOLOv2 416×416 76.8% 67
YOLOv2 480×480 77.8% 59
YOLOv2 544×544 78.6% 40

13.2 COCO

模型 mAP@0.5 mAP@[0.5:0.95]
YOLOv2 416×416 44.0% 21.6%
YOLOv2 608×608 48.1%
SSD300 43.1% 25.1%
SSD512 48.5% 28.8%

十四、训练配置

14.1 三阶段训练流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
════════════════════════════════════════════════════════
第一阶段: ImageNet 分类预训练 (224×224)
════════════════════════════════════════════════════════
数据集: ImageNet 1000 类
网络: Darknet-19 (分类版本,含 global avgpool + softmax)
输入: 224×224
Epochs: 160
学习率: 初始 0.1,多项式衰减(power=4)
权重衰减: 0.0005
动量: 0.9
数据增强: 随机裁剪、旋转、色相/饱和度/曝光变换
结果: Top-1 72.9%, Top-5 91.2%



════════════════════════════════════════════════════════
第二阶段: 高分辨率分类微调 (448×448)
════════════════════════════════════════════════════════
数据集: ImageNet 1000 类(同上)
输入: 448×448 (分辨率翻倍!)
Epochs: 10 (仅微调,让网络适应高分辨率)
学习率: 0.001 (比第一阶段低 100×,轻微调整)
结果: Top-1 76.5%, Top-5 93.3%
↑ 比第一阶段提升 3.6% / 2.1%



════════════════════════════════════════════════════════
第三阶段: 检测微调 (多尺度 320~608)
════════════════════════════════════════════════════════
网络修改:
- 移除: 最后一个卷积层、global avgpool、softmax
- 新增: 3 个 3×3×1024 卷积层
- 新增: Passthrough 层 (从倒数第二个 3×3 层接入)
- 新增: 1×1×(5×(5+C)) 卷积输出层 (VOC: 125, COCO: 425)

数据集: VOC 2007+2012 或 COCO
输入: 多尺度 {320, 352, ..., 608},每 10 batch 随机切换
Epochs: 160
学习率: 初始 0.001,第 60/90 epoch 时 ÷10
权重衰减: 0.0005
动量: 0.9
Warmup: 前 12800 次迭代计算 Anchor 先验损失
Ignore Thresh: 0.6
数据增强: 随机裁剪、翻转、色彩抖动(同 v1)

14.2 关键超参数汇总

配置项 第一阶段(分类) 第二阶段(高分辨率) 第三阶段(检测)
数据集 ImageNet ImageNet VOC / COCO
输入尺寸 224×224 448×448 320~608 (多尺度)
Epochs 160 10 160
初始学习率 0.1 0.001 0.001
学习率衰减 多项式(power=4) ×0.1 @60,90 epoch
权重衰减 0.0005 0.0005 0.0005
动量 0.9 0.9 0.9
Batch Size 64 64 64
Anchor 数 5 (K-means)
Ignore Thresh 0.6
Warmup Iter 12800

十五、相关链接

  • 📝 [[YOLO 系列总览]] — 版本对比总览
  • 📝 [[YOLOv1 详解]] — v1 基础(Grid/置信度/NMS 详见此处)
  • 📝 [[YOLO 核心概念]] — Grid/Anchor/IoU/NMS 详解
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLO学习笔记2——YOLOv2详解]] — 知乎原文 (rtfff,含损失函数源码分析)
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/【YOLO系列】YOLOv2论文超详细解读(翻译 +学习笔记)-阿里云开发者社区]] — 论文翻译+精读笔记
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLOv2 詳細解讀]] — Medium 原文 (Steven Meng,含 K-means 步骤图解)
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/深入解析YOLOv2]] — CSDN (festaw)
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLO系列算法精讲:从yolov1至yolov8的进阶之路(2万字超全整理)-CSDN博客]] — CSDN (AI菌)
  • 📋 [[10.clippings/感知算法/2D检测/单阶段/YOLO/YOLO 详解:从 v1 到 v11]] — 知乎 v1→v11 系列