1. 为什么目标检测需要OHEM?
目标检测任务中最大的痛点之一就是样本不平衡问题。想象一下,在一张城市街景图中,车辆和行人可能只占整张图的5%不到,剩下95%都是背景。这种极端不平衡的数据分布会导致模型训练时被大量简单背景样本"带偏",就像班级里90%的学生都能轻松考满分,老师自然会把精力放在剩下10%的困难学生身上。
传统交叉熵损失(CE)对所有样本一视同仁的缺点在这里暴露无遗。我曾在某交通监控项目中遇到过这种情况:使用普通CE损失训练后,模型对遮挡车辆和小尺寸行人的召回率不足30%。后来分析发现,这些困难样本的梯度被海量简单样本的梯度淹没,就像微弱信号被噪声覆盖。
OHEM(Online Hard Example Mining)的聪明之处在于它像一位经验丰富的教练,能自动识别哪些样本对当前模型最有挑战性。具体来说,它会:
- 动态筛选高损失值的样本(说明模型当前分类效果差)
- 忽略低损失值的"简单样本"(模型已经掌握得很好)
- 确保每批次至少有n_min个样本参与训练(防止样本过少导致训练不稳定)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. OHEM-CE的数学本质与实现机制
2.1 公式拆解:比传统CE多了什么?
先看传统交叉熵损失:
code复制CE = -[y*log(p) + (1-y)*log(1-p)]
OHEM-CE在此基础上增加了三重过滤机制:
- 目标样本保留:所有正样本(y=1)必定参与计算
- 困难负样本筛选:负样本(y=0)只有损失值>阈值时才参与
- 数量下限保障:确保每批至少有n_min个样本
用代码表示这个逻辑更直观:
python复制if 是正样本:
保留
elif 是负样本且loss > thresh:
保留
elif 保留样本数 < n_min:
补充选择top n_min高loss样本
else:
忽略
2.2 阈值设定的艺术
thresh参数是OHEM的核心开关,它决定了什么样的样本算"困难"。这里有个容易混淆的点:代码中的self.thresh实际是-log(thresh)。比如设置thresh=0.7时:
python复制self.thresh = -torch.log(torch.tensor(0.7)) #
