Hard Sample Mining
Hard Sample Mining,即困难样本挖掘,是目标检测中的一种常用方法。其主要思想是针对训练过程中损失较高的样本(即那些难以被正确分类的样本)进行挖掘,并将其补充到数据集中重新训练,以提高模型的识别能力。这种方法可以有效地解决样本不平衡和简单样本过多的问题。
分类中的一些基础概念:
在Hard Sample Mining中,正样本和负样本的概念是基础。正样本是包含我们想要识别类别的样本,而负样本则是不包含这些类别的样本。其中,难分正样本(Hard Positives)是指那些容易被错误地分类为负样本的正样本,而难分负样本(Hard Negatives)则是那些容易被错误地分类为正样本的负样本。这些难分样本通常具有较大的损失值,即它们的预测结果与真实标签相差较大。
- 正样本:包含我们想要识别类别的样本,例如,我们在做猫狗分类,那么在训练的时候,包含猫或者狗的图片就是正样本
- 负样本:在上面的例子中,不包含猫或者狗的其他所有的图片都是负样本
- 难分正样本(hard positives):易错分成负样本的正样本,对应在训练过程中损失最高的正样本,loss比较大(label与prediction相差较大)。
- 难分负样本(hard negatives):易错分成正样本的负样本,对应在训练过程中损失最高的负样本
- 易分正样本(easy positive):容易正确分类的正样本,该类的概率最高。对应在训练过程中损失最低的正样本
- 易分负样本(easy negatives):容易正确分类的负样本,该类的概率最高。对应在练过程中损失最低的负样本。
举例补充: 如果ROI(Region of Interest,感兴趣区域)
里没有物体,全是背景,这时候分类器很容易正确分类成背景,这个就叫easy negative;如果roi里有二分之一个物体,标签仍是负样本,这时候分类器就容易把他看成正样本,这时候就是had negative。
为什么要进行困难样本挖掘?
在区域提议(Region Proposal) 的目标检测算法中,负样本的数量会远高于正样本的数量,并且这些负样本中大部分是对网络训练作用相对较小的易分负样本(easy negatives)。这种样本不均衡问题会导致模型在训练过程中过度关注简单样本,而忽视了那些真正具有挑战性的难分样本(hard examples),从而影响了模型的收敛和精度。
根据Focal Loss论文的统计,简单例(基本都是负例)与有用信息的难例(正例+难负例)之比高达100000:100,一个非常悬殊的比例。这意味着在训练过程中,简单例的损失函数值会远高于难例的损失函数值,甚至可能达到40倍之多。这种损失函数值的不均衡会导致模型在优化过程中偏离正确的方向,无法有效地学习到难例中的有用信息。
为解决这个问题,提出了困难样本挖掘(Hard Sample Mining)
等方法。这些方法的核心思想是在训练过程中动态地选择一些具有高损失的样本(即难例)进行重点训练,从而提高模型的识别能力。通过这种方法,我们可以有效地降低简单例对模型训练的影响,使模型更加关注那些真正具有挑战性的难例。
解决目标检测中的样本不均衡问题对于提高模型的性能至关重要。通过合理处理简单例和难例之间的关系,可以使模型在训练过程中更加高效地学习有用信息,从而实现更高的检测精度和更好的泛化能力。
由于正样本数量一般较少,所有对于困难样本挖掘(hard example mining)一般是指难负例挖掘(Hard Negative Mining)。
为了让模型正常训练,我们必须要通过某种方法抑制大量的简单负例,挖掘所有难例的信息,这就是难例挖掘的初衷。即在训练时,尽量多挖掘些难负例(hard negative)加入负样本集参与模型的训练,这样会比easy negative组成的负样本集效果更好。
关于hard negative mining,比较生动的例子是高中时期你准备的错题集。错题集不会是每次所有的题目你都往上放。放上去的都是你最没有掌握的那些知识点(错的最厉害的),而这一部分是对你学习最有帮助的。
挖掘方法
离线
1、TopK Loss方法
在训练过程中,选择损失值(loss)最大的前K个样本进行反向传播(back propagate),而损失值较小的样本(即easy samples)则认为已经分类正确,不再进行反向传播。这里的K可以是一个百分比,例如前70%的困难样本。这种方法有助于模型更加关注那些难以分类的样本。
2、基于IOU的离线方法:Hard Negative Mining (HNM)
这是最早期和最简单的困难样本挖掘方法之一,它专注于那些模型错误分类为正样本的负样本(即难分负样本或hard negatives)。
在训练过程中,通过计算区域提议(Region Proposal)与真实标注(Ground Truth)之间的交并比(IoU),并设定一个阈值,将那些IoU低于某个阈值的负样本选为困难样本。结果超过阈值的被认为是正样本,低于阈值的则认为是负样本。这些样本随后被加入到负样本集中,以便在后续的训练迭代中被模型重点学习。
然而,随着训练的进行,可能会出现正样本数量远小于负样本的问题,导致数据分布不平衡。为了解决这个问题,有些研究者提出了对称的模型来处理这种不平衡的数据。
就是类似上图,将Hard Posiotive也重新赋给正样本。
在线
Online Hard Example Mining(OHEM)
是困难样本挖掘的一种实现方式。它的核心思想是在训练过程中动态地选择一些具有高损失的样本作为训练样本,从而改善网络参数的效果。这种方法不需要通过设置正负样本比例来解决数据的类别不平衡问题,而是采用在线选择的方式,更具针对性。
代表性论文:Training Region-Based Object Detectors with Online Hard Example Mining 【CVPR2016】
上述论文将难分样本挖掘(hard example mining)机制嵌入到SGD算法中,使得Fast R-CNN在训练的过程中根据region proposal的损失自动选取合适的Region Proposal作为正负例训练。
实验结果表明使用OHEM(Online Hard Example Mining)机制可以使得Fast R-CNN算法在VOC2007和VOC2012上mAP提高 4%左右。
实现
在mmdetection中的实现
在正负样本的挑选过程中,采用困难样例挖掘的方法进行筛选而不是简单的随机挑选;
def _sample_pos(self,
assign_result,
num_expected,
bboxes=None,
feats=None,
**kwargs):
# Sample some hard positive samples
pos_inds = torch.nonzero(assign_result.gt_inds > 0)
if pos_inds.numel() != 0:
pos_inds = pos_inds.squeeze(1)
if pos_inds.numel() <= num_expected: #如果样本量本身少于期望值不进行困难样本挖掘
return pos_inds
else:
return self.hard_mining(pos_inds, num_expected, bboxes[pos_inds],
assign_result.labels[pos_inds], feats)
def _sample_neg(self,
assign_result,
num_expected,
bboxes=None,
feats=None,
**kwargs):
# Sample some hard negative samples
neg_inds = torch.nonzero(assign_result.gt_inds == 0)
if neg_inds.numel() != 0:
neg_inds = neg_inds.squeeze(1)
if len(neg_inds) <= num_expected:
return neg_inds
else: #如果样本量多于期望值,进行困难样本挖掘进行筛选
return self.hard_mining(neg_inds, num_expected, bboxes[neg_inds],
assign_result.labels[neg_inds], feats)
计算样本的损失值,根据类别的loss挑选出损失比较大的样本【困难样本】
def hard_mining(self, inds, num_expected, bboxes, labels, feats):
#inds: 正负样本的索引; num_expected:期望的正负样本数量; bboxes:正负样本【anchor】, labels:类别标签 feats:特征图
with torch.no_grad(): #不参与梯度的计算
rois = bbox2roi([bboxes])
bbox_feats = self.bbox_roi_extractor(
feats[:self.bbox_roi_extractor.num_inputs], rois)
cls_score, _ = self.bbox_head(bbox_feats)
loss = self.bbox_head.loss(
cls_score=cls_score,
bbox_pred=None,
labels=labels,
label_weights=cls_score.new_ones(cls_score.size(0)),
bbox_targets=None,
bbox_weights=None,
reduction_override='none')['loss_cls']
_, topk_loss_inds = loss.topk(num_expected)
return inds[topk_loss_inds]
2、基于Yolov5/Yolov7的困难样本挖掘—LRM loss,提升难样本检测精度
论文地址:Improved Hard Example Mining Approach for Single Shot Object Detectors
代码地址:https://github.com/aybora/yolov5Loss
简介
困难例挖掘方法通常可以提高目标检测器的性能,因为它受到不平衡训练集的影响。在这项工作中,两种现有的困难例子挖掘方法(LRM和焦点损失,FL)被调整并结合到最先进的实时目标检测器YOLOv5中。广泛地评估了所提出的方法对于提高困难例性能的有效性。在2021年Anti-UAV挑战数据集上,与使用原始损失函数相比,所提出的方法使mAP提高了3%,与单独使用困难挖掘方法(LRM或FL)相比,提高了约1%。
在基于Yolov5/Yolov7的目标检测模型中,实现困难样本挖掘(Hard Example Mining)通常涉及到对损失函数的修改,以便模型在训练过程中更加关注那些难以正确分类的样本。LRM(Loss Rank Mining)
loss是一种专门为困难样本挖掘设计的方法,它通过考虑样本在整个数据集中的相对损失排名来选择困难样本。
基于OHEM的思想,Yu等人引入了Loss Rank Mining(LRM)[18]:该方法适用于单次检测,它通过在检测阶段之前过滤掉特征图上的一些容易的例子,使目标检测器专注于困难的例子。在训练过程中,作为第一步,输入要经过模型主干得到特征图。然后,对于每个检测,都要计算损失值。在非最大抑制(NMS)阶段之后,这些检测的损失值按降序排序,前K个检测结果被选中并过滤。其余的检测值在训练过程中不被使用。这个想法可能适用于目前的目标检测器,并对其有利,如果它能被实施到其结构中。
代码示例:
import torch
import torch.nn as nn
import torch.nn.functional as F
class LRMLoss(nn.Module):
def __init__(self, gamma=0.1, beta=0.05):
super(LRMLoss, self).__init__()
self.gamma = gamma
self.beta = beta
def forward(self, predictions, targets, indices):
# 计算原始损失(例如,交叉熵损失)
loss = F.cross_entropy(predictions, targets, reduction='none')
# 获取所有样本的损失值
loss_values = loss.view(-1)
# 计算每个样本的排名(从1开始)
ranks = torch.argsort(loss_values, descending=True)
ranks = ranks + 1 # 转换为从1开始的排名
# 计算排名损失
rank_loss = self.gamma * torch.log(1 + 1 / (ranks + self.beta))
# 选择困难样本进行更新
_, hard_indices = torch.topk(rank_loss, k=len(hard_indices))
hard_losses = loss[hard_indices]
# 计算最终的LRM损失
lrm_loss = hard_losses.mean()
return lrm_loss
# 假设我们有以下输入
# predictions: 模型的预测输出,尺寸为 [batch_size, num_classes, num_boxes]
# targets: 真实的标签,尺寸为 [batch_size, num_boxes]
# indices: 每个样本的索引,用于确定哪些样本是困难样本
# 初始化LRM损失函数
lrm_loss = LRMLoss(gamma=0.1, beta=0.05)
# 计算LRM损失
loss = lrm_loss(predictions, targets, indices)
# 反向传播和优化
loss.backward()
optimizer.step()
首先计算了标准的交叉熵损失,然后根据损失值计算每个样本的排名。接着使用排名来计算排名损失,并通过选择排名靠前的样本(即困难样本)来计算最终的LRM损失。
参考文献
- 深度学习难分样本挖掘(Hard Mining)
- 改进的one-shot目标检测的困难样本挖掘方法
- 涨点技巧:基于Yolov5/Yolov7的困难样本挖掘—LRM loss,提升难样本检测精度
- YOLOv9改进策略:loss优化 | LRM loss困难样本挖掘,提升难样本、遮挡物、低对比度等检测精度
- http://www.hqwc.cn/news/577750.html
- https://blog.csdn.net/qq_44804542/article/details/115276930