最先由RGB在论文《Training Region-based Object Detectors with Online Hard Example Mining》中提出,用于fast-rcnn训练中,具备必定训练效果;git
论文地址:https://arxiv.org/pdf/1604.03540.pdfgithub
实验地址:https://github.com/firrice/OHEM网络
主要思想:一个batch的输入通过网络的前向传播后,有一些困难样本loss较大,咱们能够对loss进行降序排序,取前K个认为是hard example,而后有两种方案:spa
(1)第一种比较简单,最终loss只取前K个,其余置0,而后进行BP:code
一个例子以下:component
def ohem_loss(output , label, loss_class , K_hard): batch_size = output.size()[0] loss = loss_class(output , label) sorted_loss , index = torch.sort(loss , descending = True) if(K_hard < batch_size): hard_index = index[ : K_hard] final_loss = loss[hard_index].sum() / K_hard else: final_loss = loss.sum() / batch_size return final_loss
第一种的缺点是虽然置0,但BP中依然会为之分配内存,为了提高效率引入下面第二种方案。blog
(2)第二种方案,以fast-rcnn的pipeline为例,训练两个ROI net的副本,权值共享,以下:排序
具体来讲:ip
1 将Fast RCNN分红两个components:ConvNet和RoINet. ConvNet为共享的底层卷积层,RoINet为RoI Pooling后的层,包括全链接层;内存
2 对于每张输入图像,经前向传播,用ConvNet得到feature maps(这里为RoI Pooling层的输入);
3 将事先计算好的proposals,经RoI Pooling层投影到feature maps上,获取固定的特征输出做为全链接层的输入;
须要注意的是,论文说,为了减小显存以及后向传播的时间,这里的RoINet是有两个的,它们共享权重,
RoINet1是只读(只进行forward),RoINet2进行forward和backward:
a 将原图的全部props扔到RoINet1,计算它们的loss(这里有两个loss:cls和det);
b 根据loss从高到低排序,以及利用NMS,来选出前K个props(K由论文里的N和B参数决定)
为何要用NMS? 显然对于那些高度overlap的props经RoI的投影后,
其在feature maps上的位置和大小是差很少同样的,容易致使loss double counting问题
c 将选出的K个props(能够理解成hard examples)扔到RoINet2,
这时的RoINet2和Fast RCNN的RoINet同样,计算K个props的loss,并回传梯度/残差给ConvNet,来更新整个网络