YOLOv1损失函数
我们来逐项、逐符号、用通俗语言+例子,彻底讲清楚 YOLOv1 的损失函数(Loss Function)到底在算什么、为什么这样设计。
🎯 损失函数的目标是什么?
YOLOv1 要同时完成三件事:
- 定位物体(预测边界框的 x, y, w, h)
- 判断有没有物体(置信度 confidence)
- 识别物体类别(如“狗”、“车”)
所以它的损失函数必须同时监督这三部分,而且要聪明地分配权重——不能让某一部分“压垮”其他部分。
📐 整体结构:5 个部分相加
YOLOv1 的总损失 $ \mathcal{L} $ 是以下 5 项之和:
| 项 | 监督内容 | 只对哪些网格/框计算? |
|---|---|---|
| 1️⃣ 坐标损失(x, y) | 框中心位置 | 有物体的网格中,负责预测的那个框 |
| 2️⃣ 尺寸损失(w, h) | 框宽高 | 同上 |
| 3️⃣ 有物体的置信度损失 | confidence 应接近 IoU | 同上 |
| 4️⃣ 无物体的置信度损失 | confidence 应接近 0 | 所有不含物体中心的网格的所有框 |
| 5️⃣ 分类损失 | 类别概率 | 有物体的网格(整个网格,不是每个框) |
✅ 注意:只有真实物体中心所在的那个网格才算“有物体”。
🔍 逐项详解(配合符号说明)
符号说明(先搞懂这些!)
- $ S = 7 $:图像被分成 7×7 网格
- $ B = 2 $:每个网格预测 2 个边界框
- $ i $:网格索引(从 0 到 $S^2 - 1$,共 49 个)
- $ j $:框索引(0 或 1)
- $ \mathbb{1}_{ij}^{\text{obj}} $:指示函数
- 如果第 $i$ 个网格中的第 $j$ 个框“负责”预测某个真实物体 → 值为 1
- 否则为 0
- $ \mathbb{1}_{i}^{\text{obj}} $:如果第 $i$ 个网格包含某个物体的中心 → 为 1(用于分类损失)
- $ x_i, y_i $:模型预测的框中心(相对于网格左上角,归一化到 [0,1])
- $ \hat{x}_i, \hat{y}_i $:真实值(ground truth)
- $ w_i, h_i $:预测的宽高(相对于整图,可 >1)
- $ \hat{w}_i, \hat{h}_i $:真实宽高
- $ C_i $:预测的置信度(confidence)
- $ \hat{C}_i $:目标置信度(训练时 = 预测框与真实框的 IoU)
- $ p_i© $:预测的“该网格物体属于类别 c”的概率
- $ \hat{p}_i© $:真实标签(one-hot 编码,如“狗”=1,其余=0)
第1项:框中心坐标损失(x, y)
$$
\lambda_{\text{coord}} \sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{\text{obj}} \left[ (x_i - \hat{x}_i)^2 + (y_i - \hat{y}_i)^2 \right]
$$
✅ 含义:
只对“负责预测真实物体”的那些框,计算其中心点预测误差。
📌 关键点:
- 只有一个框会被选中(IoU 更大的那个),所以 $\mathbb{1}_{ij}^{\text{obj}}$ 大部分是 0。
- 用 L2 损失(平方误差),惩罚大偏差。
- 乘以 $\lambda_{\text{coord}} = 5$:强调定位很重要!
💡 举例:
真实物体中心在网格 (3,4),两个预测框 A 和 B。
A 与真实框 IoU=0.6,B=0.3 → 选 A。
只计算 A 的 (x,y) 误差,B 的不算。
第2项:框尺寸损失(w, h)——但用了 √!
$$
\lambda_{\text{coord}} \sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{\text{obj}} \left[ (\sqrt{w_i} - \sqrt{\hat{w}_i})^2 + (\sqrt{h_i} - \sqrt{\hat{h}_i})^2 \right]
$$
✅ 含义:同样只对“负责框”计算宽高误差,但对 w 和 h 开平方后再算误差。
❓ 为什么要开平方?
👉 解决小物体误差被大物体淹没的问题。
- 假设真实宽 = 0.1(小物体),预测 = 0.2 → 误差 = 0.01(平方后)
- 真实宽 = 0.9(大物体),预测 = 1.0 → 误差 = 0.01(一样!)
- 但实际上,小物体预测错一倍,比大物体错一点点更严重!
开平方后:
- 小物体:√0.1 ≈ 0.316,√0.2 ≈ 0.447 → 差 ≈ 0.131 → 平方 ≈ 0.017
- 大物体:√0.9 ≈ 0.949,√1.0 = 1.0 → 差 ≈ 0.051 → 平方 ≈ 0.0026
→ 小物体的损失变大了!模型会更关注它。
第3项:有物体的置信度损失
$$
\sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{\text{obj}} (C_i - \hat{C}_i)^2
$$
✅ 含义:让“负责框”的置信度 $C_i$ 接近 它与真实框的 IoU。
- 如果预测框和真实框完全重合 → IoU=1 → 希望 $C_i = 1$
- 如果重合度低 → IoU=0.5 → 希望 $C_i = 0.5$
📌 注意:这不是让 confidence=1,而是让它等于 定位质量(IoU)!
第4项:无物体的置信度损失(重点!)
$$
\lambda_{\text{noobj}} \sum_{i=0}^{S^2} \sum_{j=0}^{B} \mathbb{1}_{ij}^{\text{noobj}} (C_i - \hat{C}_i)^2
$$
✅ 含义:让不负责任何物体的框的置信度趋近于 0。
- $\mathbb{1}{ij}^{\text{noobj}} = 1 - \mathbb{1}{ij}^{\text{obj}}$
- 总共有 49 网格 × 2 框 = 98 个预测框
- 但一张图通常只有 2~5 个物体 → 只有 2~5 个框是“有物体”的
- 剩下 90+ 个框都是背景!
⚠️ 问题:如果不对这些背景框惩罚,模型会胡乱预测高置信度框(全是假阳性)。
🔧 解决方案:
- 计算它们的 loss(希望 $C_i = 0$)
- 但乘以一个小权重 $\lambda_{\text{noobj}} = 0.5$
→ 防止负样本(背景)主导总损失(否则 loss 全被背景控制,物体学不好)
第5项:分类损失
$$
\sum_{i=0}^{S^2} \mathbb{1}{i}^{\text{obj}} \sum{c \in \text{classes}} (p_i© - \hat{p}_i©)^2
$$
✅ 含义:只对包含物体中心的网格,计算其类别概率误差。
- 注意:这里没有 j(框索引)!因为 YOLOv1 中一个网格只输出一组类别概率(共享给两个框)
- 用 L2 损失(也可以用交叉熵,但原论文用 L2)
- 如果网格没物体,不计算分类 loss
💡 举例:
网格 (2,5) 中心有“猫” → $\hat{p}(\text{cat}) = 1$,其他类=0
模型预测 $p(\text{cat}) = 0.8$ → 误差 = (0.8 - 1)² = 0.04
🧩 为什么这样设计?总结三大智慧
| 设计 | 目的 |
|---|---|
| $\lambda_{\text{coord}} = 5$ | 强调定位精度比分类更重要(检测任务的核心是“在哪”) |
| $\lambda_{\text{noobj}} = 0.5$ | 平衡正负样本(98 个框 vs 3 个物体),防止背景噪声淹没信号 |
| √w, √h | 让小物体和大物体的定位误差“公平竞争”,提升小物体检测能力 |
🖼️ 举个完整例子(一张图有 1 个物体)
- 图像:448×448,含 1 只狗
- 狗的中心落在网格 #23(即第 23 个网格)
- 该网格的两个预测框:Box A(IoU=0.7),Box B(IoU=0.4)→ 选 A 负责
那么损失计算如下:
| 损失项 | 是否计算? | 说明 |
|---|---|---|
| Box A 的 (x,y) 误差 | ✅ | $\mathbb{1}_{23,0}^{\text{obj}} = 1$ |
| Box A 的 (√w, √h) 误差 | ✅ | 同上 |
| Box A 的 confidence 误差 | ✅ | 目标 = 0.7 |
| Box B 的所有误差 | ❌ | 不负责,$\mathbb{1}_{23,1}^{\text{obj}} = 0$ |
| 网格 #23 的分类误差 | ✅ | $\mathbb{1}_{23}^{\text{obj}} = 1$ |
| 其他 48 个网格的 96 个框 | ✅(仅 confidence) | $\mathbb{1}_{ij}^{\text{noobj}} = 1$,希望 confidence≈0 |
✅ 总结一句话
YOLOv1 的损失函数是一个精心加权的多任务回归损失,它通过:
- 只让正确的网格和框学习
- 放大定位和小物体的误差
- 抑制背景框的置信度
实现了端到端的统一检测训练。
如果你现在再回头看公式,应该能看懂每一项在“惩罚谁”、“为什么惩罚”、“罚多重”了!