物体检测中的困难样本挖掘,之前有一个名词叫做hard negative mining困难负样本挖掘
先讨论什么是on-line hard example mining(OHEM):例如一个背景,被很大概率预测为前景了,那么这个背景就是困难样本;对于一个前景(ground truth classes为foreground),网络模型预测它很大的概率值为背景,则这个前景也是困难样本,也就是说,在线困难忘本挖掘是不区分正负样本的(但是在代码实现中,由于正样本个数较少,通常保留所有的正样本,然后按照1:3的比例采样出3倍数量的负样本),它希望更多的训练困难样本,而不是简单样本,具体的程序实现在 torchcv中的ssdloss.py中有所体现。
在SSD和FPNSSD编码器中,都是将IOU_max大于0.5的anchor设置为正样本,小于0.5的设置为负样本,
classification target为 -1 ingore 0 negative examples 1 2 3 ~ num_classes positive examples
然后计算SSDLoss时,也是先计算出所有正样本anchor boxes和所有负样本anchor boxes的classification loss,但是size_average参数设置为False,然后从所有的正负样本中找出所有的困难样本。
ingore(classification target=-1)的classification loss=0
然后取出所有的正样本的loss,并记录当前batch size图像中positive examples总数,再对所有的负样本的classification loss进行排序,取出前3*(num positive examples)个负样本,这是因为负样本的个数要比正样本多出很多。
也就是说,SSD训练过程中的正负样本比例是1:3,只对负样本进行了困难样本挖掘,不对正样本进行困难样本挖掘,这样做的主要原因在于,设置IOU_max>0.5做为正样本,或者说在众多的anchor boxes中,正样本的个数很少,大多数都是负样本,这样会带来严重的类别不平衡问题,故而设定固定比例,取出较为困难(体现在classification loss大)的负样本,计算classification loss。在每次训练过程中的困难负样本都不一样,故而称之为在线困难样本挖掘(因为每次模型参数不一样,negative examples的classification loss排序不同)
class SSDLoss(nn.Module):#损失函数 def __init__(self, num_classes): super(SSDLoss, self).__init__() self.num_classes = num_classes#类别总数,对于VOC数据集而言,是21类 def _