返回专辑
·Johan·3 分钟阅读

交叉熵和 Focal

类别极不均衡或 easy negative 淹没时,CE 梯度被 head 样本主导——Focal loss 下调 easy 样本权重,检测常用但 γ 过大也会伤 recall。

交叉熵和 Focal

1. 简单负样本淹没梯度

目标检测里背景类占百分之九十九的 anchor,普通交叉熵梯度被简单负样本淹没——模型花大部分容量学「这确实是背景」,困难正样本和困难负样本贡献被稀释。Focal Loss(Lin 等)通过 下调简单样本权重,让梯度集中在困难样本上。

这不是所有不均衡场景的默认解:二分类不均衡有时 BCEWithLogitsLoss(pos_weight=...) 或交叉熵加类别权重就够;focal 与 pos_weight 叠罗汉会过度加权,loss 震荡、召回下降。

2. 公式与实现

退化为交叉熵; 是 RetinaNet 常见起点。 平衡正负(检测里常 0.25)。PyTorch 无官方一行实现,常用自写:

python
def focal_loss(logits, targets, alpha=0.25, gamma=2.0):
    ce = F.cross_entropy(logits, targets, reduction='none')
    pt = torch.exp(-ce)
    return (alpha * (1 - pt) ** gamma * ce).mean()

二分类不均衡:nn.BCEWithLogitsLoss(pos_weight=torch.tensor([5.0]))。多分类交叉熵加类别权重与 focal 别叠太狠——先试一种,看各类 loss 贡献曲线。

3. γ 与 α 的边界

γ 过大 → 只学困难样本,训练不稳定,召回可能下降。γ 过小 → 接近交叉熵,focal 无意义。语义分割用逐像素 focal 时注意 reduction='mean''sum' 影响有效学习率——mean 对像素数归一,sum 对大图梯度更大。

单阶段检测器(RetinaNet、FCOS 变体)常用 focal;两阶段 Faster R-CNN 有时在线困难样本挖掘加交叉熵够用,不必强行上 focal。

4. 与采样策略的关系

focal 是 loss 层面的重加权;在线困难样本挖掘、平衡采样是数据层面的重加权。两者目标类似,叠用前先消融。统计各类 loss 贡献和困难样本比例曲线,比只看总 loss 有用。

COCO 上 focal 对单阶段有效;若验证 mAP 不涨,查 anchor 匹配、正负比和 γ 是否过大。分割类不平衡有时类别权重更简单、可解释。

5. 案例:γ 过大伤召回

某检测项目 focal γ 调到 5,训练 loss 下降快但验证召回掉三个点——困难样本权重过高,模型对边界框偏保守。γ 回到 2 并配合 OHEM,精度召回更平衡。调 γ 必看召回,不只看 mAP。

6. 验收

  • γ=0 时实现退化为交叉熵,数值可对齐。
  • 各类 loss 贡献曲线:困难类不被简单负样本完全淹没。
  • focal 与 pos_weight、类别权重不同时叠太狠。
  • 分割的 reduction 选择与学习率匹配。
  • 验证上看召回与精度权衡,γ 过大召回可能掉。

7. 落地与衔接

上线前把损失函数选择与锚框匹配策略写进训练配置,并在消融实验里固定正负采样比例。检测流水线应记录各类损失贡献与困难样本比例,便于对比交叉熵、正样本权重与焦点损失三条基线。切换损失时同步检查学习率是否需要重调,因为有效梯度尺度会随之变化。部署评估除平均精度外单独盯召回切片,避免焦点损失在业务关键类别上悄然掉点。团队交接时把最终参数与曲线一并归档。

Focal 是检测里处理类别不平衡的利器,但不是万能。先试简单重加权,困难样本仍被淹没再上 focal,γ 从 2 起调。把 γ 与 α 的搜索范围、最终取值和召回曲线一并归档,后续改骨干网络或输入分辨率时可直接复用起点,而不是每次从零猜超参。发版材料里应同时呈现精度与召回权衡,供业务方确认操作点。类别分布变动时应重新评估是否需要焦点损失。

← 全部文章

johan's blog