Focal Loss
Focal Loss(焦点损失)是为了解决**极度类别不平衡(Class Imbalance)**问题而设计的损失函数,最早由何恺明团队在 RetinaNet 论文中提出。
为什么需要Focal Loss
在训练分类器(尤其是目标检测)时,往往存在两个问题:
- 正负样本不平衡: 比如在一张图里,背景(负样本)占了绝大多数,目标(正样本)很少。
- 难易样本不平衡: 大多数背景都很容易区分(Easy Negatives),模型这部分学得很好;但少部分样本很难区分(Hard Examples)。
如果使用普通的交叉熵损失(Cross Entropy, CE),那些大量的、容易分类的样本虽然单个Loss很小,但加起来会淹没掉少数的、难分类样本的Loss,导致模型学偏了。
数学公式
$$
FL(p_t) = -\alpha_t (1 - p_t)^\gamma \log(p_t)
$$
调整
Gamma
解决“难易不平衡”。当模型只学简单的,不学难的时候调整
情况 A:需要 调大 Gamma (比如从 2.0 -> 3.0 或 4.0)
- 现象: 模型的 Loss 下降很快,但准确率(mAP 或 Accuracy)就是上不去。
- 原因: 这说明大量的“简单背景”或“容易区分的负样本”虽然 Loss 很小,但因为数量太庞大,它们加起来的总 Loss 依然主导了梯度,让模型觉得“我已经学得很好了”,从而不再去优化那些真正困难的样本。
- 现象: 模型对由于遮挡、模糊、光照差导致的目标检测效果很差。
- 对策: 调大 Gamma,进一步压低简单样本的权重,强迫模型去“啃硬骨头”。
情况 B:需要 调小 Gamma (比如从 2.0 -> 1.0 或 0.5)
- 现象: 模型训练不稳定,Loss 震荡,或者难以收敛。
- 原因: 可能是 Gamma 太大,导致过多的简单样本 Loss 被清零,模型能学到的有效信息太少;或者是那些被认为是“难样本”的其实是**离群点(Outliers)*或*脏数据(标错了)。如果过度关注这些脏数据,模型就会学坏。
- 现象: 简单的任务(Easy Task)。
- 如果你的数据集本身背景很干净,目标很清晰,不需要太强的 Focal Loss,调小 Gamma 接近 0(即接近 Cross Entropy)可能效果更好。
Alpha
核心目的: 简单粗暴地平衡正负样本的数量差异,或者调节 Precision(精确率)和 Recall(召回率)的偏好。
情况 A:正负样本比例极度悬殊
- 场景: 类似于欺诈检测、极小目标检测(背景像素占比 99.9%)。
- 调整方向: 理论上应该给少类(正样本)更大的权重。但是!在 Focal Loss 中有一个反直觉的经验:
- 如果你的背景(负样本)特别多,你反而应该把正样本的 Alpha 设得小一点(比如 0.25 而不是 0.75)。
- 为什么? 因为正样本通常很少且较难(Loss大),而负样本虽然多但通常很简单(Loss会被 Gamma 压得很低)。如果 Alpha 给正样本太大,可能会导致模型过于激进地预测为正类,产生大量误报(False Positives)。
情况 B:调节指标偏好 (Precision vs Recall)
- 如果你希望提高 Recall(宁可错杀,不可放过):
- 调大 Alpha(增加正样本权重)。模型会因为害怕漏掉正样本而受到更大的惩罚,因此会更倾向于预测“是”。
- 如果你希望提高 Precision(宁缺毋滥):
- 调小 Alpha(减小正样本权重,或者说相对增加负样本权重)。模型会变得保守,只有非常有把握时才预测为“是”。
Gamma 和 Alpha 的联动调整
Gamma越大,Alpha应当越小
原理: 当你调大 Gamma 时,你已经大幅度抑制了大量简单负样本(背景)的 Loss。此时,正样本在总 Loss 里的占比其实已经变相增加了。如果你不把 Alpha 调小一点,正样本的权重就会变得“过大”,导致训练不稳定或误报增多。
经典的实验数值(来自 RetinaNet 论文):
| Gamma (γ) | Alpha (α) | 说明 |
|---|---|---|
| 0 (CE Loss) | 0.75 | 没有 Gamma 抑制时,需要用较大的 Alpha 来平衡数量 |
| 2.0 (标准) | 0.25 | 最常用的组合,Gamma 抑制了易分样本,Alpha 适当减小 |
| 5.0 (强聚焦) | 0.05 - 0.1 | Gamma 极强时,Alpha 必须设得很小 |
实战调参策略
如果不知道怎么设,建议按照这个顺序来:
- 先固定 Alpha,调 Gamma:
- 先设
alpha=0.25(或者用你数据集中正负样本比例的倒数,但不要超过 0.5)。 - 尝试
gamma = [1.0, 2.0, 3.0]。 - 看验证集 mAP 哪个最高。通常 2.0 是最稳健的起点。
- 先设
- 固定 Gamma,微调 Alpha:
- 选定最佳 Gamma 后(比如 2.0),微调
alpha。 - 比如尝试
[0.20, 0.25, 0.30]。 - 观察模型的误报率和漏检率来决定往哪边偏。
- 选定最佳 Gamma 后(比如 2.0),微调
一句话总结: 觉得模型太笨(学不会难的)就动 Gamma;觉得模型太偏科(正负失衡或误报太多)就动 Alpha。