Focal loss and RetinaNet
這是一篇論文閱讀筆記
論文連結:https://arxiv.org/abs/1708.02002
程式碼連結:https://github.com/facebookresearch/Detectron
首先,提一個問題,為什麼one stage方法精度比two stage方法精度低?
這個問題是本篇論文討論與解決的主要問題.
作者總結道,一個很重要的因素是因為在one stage方法中,正負樣本的不均衡。
那麼one stage方法為什麼正負樣本就不均衡了呢?
這裡舉個例子:
首先來看一個典型的one stage方法,SSD。在SSD中,首先按照一定的規律產生Prior,大約會產生約10,000的候選區域,由於其實規律的取樣,所以相對來說比較稠密、冗餘,即使後面在分類的時候採用了hard example mining(對分數進行排序,取前面部分),但是仍然會存在較多的簡單樣本,使得正負樣本不均衡。
相比較two stage方法,我們已Faster R-CNN為代表,在Faster R-CNN中,首先利用RPN網路產生目標框候選區域,約會生成1000-2000的候選框,這就過濾掉了大部分的簡單負樣本,然後在分類過程中,使用正負樣本1:3或者OHEM方法使得正負樣本更為均衡。
簡單總結two stage的優勢在於:
-
其採用兩個階段的級聯,這樣rpn階段就可以將候選區域數量控制在1-2k左右,相比於one-stage要減少很多。
-
mini-batch取樣,取樣並不是隨便取樣的,而是根究正樣本的位置進行取樣(比如將負樣本的設定為與ground-truth的IOU在0.1-0.3之間的),這樣可以幹掉一大部分簡單樣本,另外在正負樣本比例上的選擇,比如1:3,同樣在打破平衡性。
正負樣本類別不均衡帶來的問題:
- 訓練低效,過多的負樣本,對於檢測框沒有作用。 (training is inefficient as most locations are easy negatives that contribute no useful learning signal)
- 過多簡單的負樣本會壓制訓練,使得訓練效果不好。(enmasse the easy nagatives can overwhelm training and lead to degenerate models.)
為了解決這個問題,作者提出了Focal Loss , 並且設計了RetinaNet
一個解決正負樣本的方法:Focal Loss
Focal Loss是在交叉熵損失基礎上修改的,所以這裡有必要先回顧一下交叉熵損失(cross entropy loss)
交叉熵損失的公式如下,這裡給的是簡單的Binary CrossEntropy Loss,就是隻有兩個類別。
簡化一下,我們定義 如下:
則,交叉熵損失可以表示成:
當然為了更好的分析這個函式,我們將他的影象畫出來,下面的影象中的藍色的線就是該函式的曲線了,可以發現,計算是概率比較大的簡單樣本 >> 0.5,依然存在一定的loss,所以當這種樣本的數量較多的時候,累計起來就會比較大了,甚至會超過那些概率較小的樣本(hard example),導致對於那些hard example的學習效果不佳,這也就是為什麼正負樣本不均衡會導致學習效果不佳,太多的簡單樣本,累加起來,會產生較大的影響,量變產生質變。
那麼我們該如何平衡交叉熵損失呢
最簡單的方法就是在交叉熵損失前面新增一個超引數,變成:
這樣就會將這條曲線往下拉一些,使得當概率較大的時候,其影響減小。
Focal Loss Definition
借鑑了上面的方法,所以Focal Loss並沒有真正改變正負樣本的比例,而是修改了easy/hard example的損失權重,當然 取固定值當然不好,所以作者做了個自適應,完整的Focal Loss定義如下:
其中 作為調節引數,控制著縮放的比例,不同的\gamma對應的曲線,如上圖figure 1所示。
Focal Loss有兩個好處:
- 如果一個樣本分類錯誤了,概率很小( 很小),這樣相乘的係數(1- )就接近於1,對樣本原本的分類影響不大。
- 起到了平滑的作用,作者的實驗中,其等於2的效果最好。
舉個例子:
取 ==2,假如分類的概率是 =0.9,則原來的loss=-log(0.9) =0.046,-(1-0.9)^2 * log(0.9) = 0.00046,縮小了約100倍,加入分類概率是 =0.968,那麼就會縮小約1000倍,如果概率小於0.5,如:p=0.4 , -log(0.4) == 0.39, -(1-0.4)^2 * log(0.4) = 0.14,只是減少了不到3倍。
另外,還可以增加一個引數 ,來平衡一下倍數,如下:
這樣,即使存在大量的簡單樣本,但是由於其帶來的損失已經非常小了,所以對整體的影響也不會很大,也就不會對hard example產生較大的影響了。
基於Focal Loss 設計的 RetinaNet Detector
先來一張網路結構圖:
相信對FPN比較熟悉的同學會發現,這跟FPN好像啊。
沒錯,作者的backbone採用的就是FPN,下面對這個網路逐一介紹一下:
-
backbone:FPN
RetinaNet的backbone採用Resnet-FPN接面構,並在P3-P7上建立影象金子塔 代表其縮放比例是 倍。同時作者指出,FPN接面構還是很有用的,最開始作者只使用Resnet最後一層的feature,結果AP(準確率)並不高。
-
anchors:
作者在原來的基礎上,新增了3個size,{ , , }
-
正負樣本的定義
IOU > 0.5 為正樣本。
IOU [0, 0.4) 為負樣本。
IOU [0.4, 0.5] 不要了。這裡負樣本的閾值被提到了0.4(大部分都是0.3),不知道是不是作者有意為之,來證明自己的網路可以容納更多的正負樣本不均衡。但是這樣其實也帶來了更多的hard examples.
檢測部分,當然是正樣本去檢測就行了。
-
分類分支:
對於每一個FPN分支,都會有一個預測分支與之對應,瞭解SSD的小夥伴對這裡應該不會陌生,分類分支包括4組3*3卷積+ReLU,最後接KA個3*3卷積。K代表類別,A代表anchor的數量。相比較於RPN網路,這裡的網路更深了。
有一句話沒有理解:parameters of this subnet are shared across all pyramid levels. -
box regression分支:
首先,box regression與分類分支並沒有共享網路,結構與分類分支基本一致,只是在最後的卷積核的數量是4A個,因為要對每個anchor預測4個座標。
在inference過程中,為了提高速度,RetinaNet只使用前1000的Prior去進行座標迴歸,並且最後對所有的預測結果進行非極大值抑制,並設定閾值為0.5進行過濾,最終得到預測結果。
Focal Loss使用在分類分支中。
在訓練的過程中,RetinaNet直接使用約100k左右的anchor進行訓練,而不需要想SSD那樣使用OHEM或者像RCNN系列那樣提取候選區域,最終的loss是這100K的focal loss的和,並且作者表示,在 =2, =0.25的時候,網路效果最佳。
-
引數初始化
FPN部分參考FPN的初始化方法,其他的新添層,w採用高斯分佈, =0.01, b=0, 最後一個卷積層 b = pi = 0.1
實驗部分
下表是一些對比實驗
- ( a ) 是對crossentropy loss使用不同的係數的結果,可見當 =0.75的時候,表現最好。
- ( b ) 是使用focal loss的對比結果,其中加粗的為最好的效果。
- ( c ) 是使用不同比例、大小的anchor的結果對比。
- ( d ) 是對OHEM的對比結果,作者分別對OHEM設定不同的比例,以及使用focal loss的結果,結果顯示使用OHEM並沒有特別大的變化,但是使用focal loss精度提升明顯,這也說明了focal loss的作用。
- ( e ) 是對不同尺度影象的精度以及速度的對比。
為了分析Focal Loss的效果,作者選取了大量的正負樣本,然後分別計算Focal Loss,然後對其進行normalize操作,使其和是1,其累計分佈如下圖所示:
其橫軸是樣本的數量百分比,縱座標是累計誤差,可見, 對於負樣本的影響相對較大,特別是當 取2的時候,負樣本的loss大部分的損失都是很小的,只有一小部分的loss比較大,這也說明了focal loss起到了對簡單負樣本的抑制作用,使得大部分負樣本沒有作用。
下面是網路的檢測精度,以及速度,以及與state of the art網路的對比。
觀察下面兩張圖,可以發現AP不太一樣,主要原因是,其採用了一些策略,比如尺度變換等。
以上是對Focal Loss以及RetinaNet的一些理解,如果有不對的地方,歡迎指正