最早由RGB在論文《Training Region-based Object Detectors with Online Hard Example Mining》中提出,用於fast-rcnn訓練中,具有一定訓練效果;
論文地址:https://arxiv.org/pdf/1604.03540.pdf
實驗地址:https://github.com/firrice/OHEM
主要思想:一個batch的輸入經過網絡的前向傳播后,有一些困難樣本loss較大,我們可以對loss進行降序排序,取前K個認為是hard example,然后有兩種方案:
(1)第一種比較簡單,最終loss只取前K個,其他置0,然后進行BP:
一個例子如下:
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中依然會為之分配內存,為了提升效率引入下面第二種方案。
(2)第二種方案,以fast-rcnn的pipeline為例,訓練兩個ROI net的副本,權值共享,如下:

具體來說:
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,來更新整個網絡
