1. 程式人生 > >YOLOv2--論文學習筆記(演算法詳解)

YOLOv2--論文學習筆記(演算法詳解)

主要包括三個部分:Better,Faster,Stronger,其中前面兩部分基本上講的是YOLO v2,最後一部分講的是YOLO9000。

Better

這部分細節很多,要詳細瞭解的話還是需要結合原始碼來看。
本篇論文是YOLO作者為了改進原有的YOLO演算法所寫的。

YOLO有兩個缺點:
(1)定位不準確
(2)和基於region proposal的方法相比召回率較低。

因此YOLOv2主要是要在這兩方面做提升。另外YOLOv2並不是通過加深或加寬網路達到效果提升,反而是簡化了網路。
下面就是使用的一些手段。

1、Batch Normalization

BN(Batch Normalization)層簡單講就是對網路的每一層的輸入都做了歸一化,這樣網路就不需要每層都去學資料的分佈,收斂會快點。作者在YOLOv2種為每個卷積層都添加了BN層,由於BN可以規範模型,所以加入BN後就把dropout去掉了,實驗證明添加了BN層可以提高2%的mAP。

2、High Resolution Classifier

現在基本跑個分類或目標檢測模型都不會從隨機初始化所有引數開始,所以一般都是用預訓練的網路來fine-tuning自己的網路,而且預訓練的網路基本上都是在ImageNet資料集上跑的,一方面資料量大,另一方面訓練時間久,而且也比較容易得到。

YOLOv1在預訓練的時候用的是224*224的輸入,一般預訓練的分類模型都是在ImageNet資料集上進行的,然後在檢測的時候採用448*448的輸入。這會導致從分類模型切換到檢測模型的時候,模型還要適應影象解析度的改變。
YOLOv2中將預訓練分成兩步:先用224*224的輸入從頭開始訓練網路,大概160個epoch

,然後再將輸入調整到448*448,再訓練10個epoch。**注意這兩步都是在ImageNet資料集上操作。**最後再在檢測的資料集上fine-tuning,也就是檢測的時候用448*448的影象作為輸入就可以順利過渡了。

3、Convolutional With Anchor Boxes

YOLOv1是利用全連線層直接預測bounding box的座標。
YOLOv2則借鑑了Faster R-CNN的思想,引入anchor。

YOLOv2做了以下改變:
(1)刪掉全連線層和最後一個pooling層,使得最後的卷積層可以有更高解析度的特徵;
(2)縮減網路,用416*416大小的輸入代替原來448*448

。這樣做是希望希望得到的特徵圖都有奇數大小的寬和高,奇數大小的寬和高會使得每個特徵圖在劃分cell的時候就只有一箇中心cell。因為大的目標一般會佔據影象的中心,所以希望用一箇中心cell去預測,而不是4箇中心cell。網路最終將416*416的輸入下采樣32倍變為13*13大小的feature map輸出,檢視.cfg檔案可以看到有8個pooling層。

YOLOv1中將輸入影象分成7*7的網格,每個網格預測2個bounding box,一共只有7*7*2=98個box
YOLOv2中引入anchor boxes,輸出feature map大小為13*13,每個cell有5個anchor box預測得到5個bounding box,一共有13*13*5=845個box。增加box數量是為了提高目標的定位準確率。

4、Dimension Clusters

Faster R-CNN中anchor box的大小和比例是按經驗設定的,然後網路會在訓練過程中調整anchor box的尺寸。
如果一開始就能選擇到合適尺寸的anchor box,那肯定可以幫助網路更好地預測。所以作者採用k-means的方式對訓練集的bounding boxes做聚類,試圖找到合適的anchor box。

作者發現採用標準的k-means(即用歐式距離來衡量差異),在box的尺寸比較大的時候其誤差也更大,而我們希望的是誤差和box的尺寸沒有太大關係。所以通過IOU定義了距離函式,使得誤差和box的大小無關:
設定先驗框的主要目的是為了使得預測框與ground truth的IOU更好,所以聚類分析師使用box與聚類中的box之間的IOU值作為距離指標。
在VOC和COCO資料集上的聚類分析結果,隨著聚類中心數目的增加,平均IOU值(各個邊界框與聚類中心的IOU的平均值)是增加的,但是綜合考慮模型複雜度和召回率,作者最終選取5個聚類中心作為先驗框

對於兩個資料集,5個先驗框的width和height如下

COCO: (0.57273, 0.677385), (1.87446, 2.06253), (3.33843, 5.47434), (7.88282, 3.52778), (9.77052, 9.16828)
VOC: (1.3221, 1.73145), (3.19275, 4.00944), (5.05587, 8.09892), (9.47112, 4.84053), (11.2364, 10.0071)

這裡先驗框的大小具體指什麼作者在論文中並沒有說明,從程式碼實現上看,應該是相對於13*13的特徵圖的大小。
在這裡插入圖片描述
在這裡插入圖片描述

實驗對比:
(1)採用聚類分析得到的先驗框比手動設定的先驗框平均IOU值更高,因此模型更容易訓練學習。
(2)僅選取5種box就能達到Faster RCNN的9種box的效果。

5、Direct Location prediction

這部分細節很多
作者在引入anchor box的時候遇到的第二個問題:模型不穩定,尤其是在訓練剛開始的時候。作者認為這種不穩定主要來自預測box的中心座標(x,y)值。
在基於region proposal的目標檢測演算法中,是通過預測txty來得到(x,y)值,也就是預測的是offsets。
論文這裡公式是錯的,應該是“+”號。依據是下文中的例子,以及Faster R-CNN中的公式。

在這裡插入圖片描述

這個公式是無約束的,預測的邊界框很容易向任何方向偏移。
tx=1時,box將向右偏移一個anchor box的寬度;
tx=-1時,box將向左偏移一個anchor box的寬度;
因此,每個位置預測的邊界框可以落在圖片任何位置,這導致模型的不穩定性,在訓練時需要很長時間來預測出正確的offsets。

YOLOv2中沒有采用這種預測方式,而是沿用了YOLOv1的方法,就是預測邊界框中心點相對於對應cell左上角位置的相對偏移值。
網路在最後一個卷積層輸出13*13的feature map,有13*13個cell,每個cell有5個anchor box來預測5個bounding box,每個bounding box預測得到5個值。
分別為:tx、ty、tw、th和to(類似YOLOv1的confidence)
為了將bounding box的中心點約束在當前cell中,使用sigmoid函式將tx、ty歸一化處理,將值約束在0~1,這使得模型訓練更穩定。

在這裡插入圖片描述
在這裡插入圖片描述

6、Fine-Grained Features

細粒度特徵
這裡添加了一個直通層(passthrough layer),即就是原始碼中的reorg layer,將前面一層的26*26的特徵圖和本層13*13的特徵圖進行連線,與ResNet網路的shortcut類似,以前面更高解析度的特徵圖為輸入,然後將其連線到後面的低解析度特徵圖上。
13*13的特徵圖上做預測,雖然對於大目標已經足夠了,但對小目標不一定足夠好,這裡合併前面大一點的特徵圖可以有效的檢測小目標。
具體操作:對於26*26*512的特徵圖,經passthrough層處理之後就變成了13*13*2048的新特徵圖(特徵圖大小變為1/4,而通道數變為以前的4倍),然後與後面的13*13*1024特徵圖連線在一起形成13*13*3072的特徵圖,最後在該特徵圖上卷積做預測。

7、Multi-Scale Training

YOLOv2中只有卷積層和池化層,因此不需要固定的輸入圖片的大小。
為了讓模型更有魯棒性,作者引入了多尺度訓練。就是在訓練過程中,每迭代一定的次數,改變模型的輸入圖片大小。

注意:這一步是在檢測資料集上fine-tuning時候採用的,不要跟前面在Imagenet資料集上的兩步預訓練分類模型混淆。

具體操作:在訓練時,每10個batch?確定不是10個epoch?網路就會隨機選擇另一種size的輸入。

網路輸入是416*416,經過5次max pooling之後會輸出13*13的feature map,也就是下采樣32倍,因此作者採用32的倍數作為輸入的size,具體採用320、352、384、416、448、480、512、544、576、608共10種size。

輸入圖片大小為320*320時,特徵圖大小為10*10,輸入圖片大小為608*608時,特徵圖大小為19*19
每次改變輸入圖片大小還需要對最後檢測層進行處理,然後開始訓練。

在這裡插入圖片描述

這種網路訓練方式使得相同網路可以對不同解析度的影象做檢測。

在輸入size較大時,訓練速度較慢,在輸入size較小時,訓練速度較快,而multi-scale training又可以提高準確率,因此算是準確率和速度都取得一個不錯的平衡。

Faster

YOLOv1,作者採用的訓練網路是基於GooleNet,GooleNet在計算複雜度上要優於VGG16,但是在ImageNet上的top-5準確率要稍低於VGG16。
YOLOv2,作者採用了新的分類模型作為基礎網路,那就是Darknet-19

1、Darknet-19

網路包含19個卷積層和5個max pooling層,而在YOLOv1中採用的GooleNet,包含24個卷積層和2個全連線層,因此Darknet-19整體上卷積卷積操作比YOLOv1中用的GoogleNet要少,這是計算量減少的關鍵。最後用average pooling層代替全連線層進行預測。
在這裡插入圖片描述

2、Training for Classification

這部分前面有提到,就是訓練處理的小trick。
這裡的Training for Classification都是在ImageNet上進行預訓練。
YOLOv2的訓練主要包括三個階段

第一階段:在ImageNet分類資料集上從頭開始預訓練Darknet-19,訓練160個epoch。輸入影象的大小是224*224,初始學習率為0.1。另外在訓練的時候採用了標準的資料增加方式比如隨機裁剪,旋轉以及色度,亮度的調整等。
第二階段:將網路的輸入調整為448*448,繼續在ImageNet資料集上fine-tuning分類模型,訓練10個epoch。引數的除了epoch和learning rate改變外,其他都沒變,這裡learning rate改為0.001

3、Training for Detection

第三階段:修改Darknet-19分類模型為檢測模型,並在檢測資料集上繼續fine-tuning網路。
網路修改包括:移除最後一個卷積層、global avgpooling層以及softmax層,新增了三個332014卷積層,同時增加了一個passthrough層,最後使用1*1卷積層輸出預測結果。輸出通道數計算如下。
對於VOC資料,每個cell預測num=5個bounding box,每個bounding box有5個座標值和20個類別值,所以每個cell有125個filter。即:filter_num = num * (classes + 5) = 5 * (20 + 5) = 125

注意
(1)這裡filter_num的計算和YOLOv1不同,在YOLOv1中filter_num = classes + num * (coords + confidence) = 20 + 2 * (4 + 1) = 30,在YOLOv1中,類別概率是由cell來預測的,一個cell對應的兩個box的類別概率是一樣的,但是在YOLOv2中,類別概率是屬於box的,每個box對應一個類別概率,而不是由cell決定,因此這邊每個box對應25個預測值(5個座標加20個類別值)。
(2)YOLOv2和YOLOv3的計算方式是一致的。

YOLOv2訓練的三個階段如下圖所示
在這裡插入圖片描述
YOLOv2的結構示意圖如下
在這裡插入圖片描述

論文裡沒有說明先驗框匹配和loss是怎麼做的,所以有很多細節就需要去挖掘一下!

查資料有人蔘考YOLO在TensorFlow上的實現darkflow(見yolov2/train.py)給出瞭解釋(見文後Reference,寫的非常好,這裡為了連貫我直接貼出來):

(1)和YOLOv1一樣,對於訓練圖片中的ground truth,若其中心點落在某個cell內,那麼該cell內的5個先驗框所對應的邊界框負責預測它,具體是哪個邊界框預測它,需要在訓練中確定,即由那個與ground truth的IOU最大的邊界框預測它,而剩餘的4個邊界框不與該ground truth匹配。YOLOv2同樣需要假定每個cell至多含有一個grounth truth,而在實際上基本不會出現多於1個的情況。與ground truth匹配的先驗框計算座標誤差、置信度誤差(此時target為1)以及分類誤差,而其它的邊界框只計算置信度誤差(此時target為0)。

(2)YOLOv2和YOLOv1的損失函式一樣,為均方差函式。但是看了YOLOv2的原始碼(訓練樣本處理與loss計算都包含在檔案region_layer.c中),並且參考國外的blog以及allanzelener/YAD2K(Ng深度學習教程所參考的那個Keras實現)上的實現,發現YOLOv2的處理比原來的v1版本更加複雜。

(1)W,H分別指的是特徵圖(13*13)的寬與高;
(2)A指的是先驗框數目(這裡是5);
(3)各個λ值是各個loss的權重係數,參考YOLOv1的loss;
(4)第一項loss是計算background的置信度誤差,但是哪些預測框來預測背景呢,需要先計算各個預測框和所有ground truth的IOU值,並且取最大值Max_IOU,如果該值小於一定的閾值(YOLOv2使用的是0.6),那麼這個預測框就標記為background,需要計算noobj的置信度誤差;
(5)第二項是計算先驗框與預測寬的座標誤差,但是隻在前12800個iterations間計算,我覺得這項應該是在訓練前期使預測框快速學習到先驗框的形狀;
(6)第三大項計算與某個ground truth匹配的預測框各部分loss值,包括座標誤差、置信度誤差以及分類誤差。
先說一下匹配原則,對於某個ground truth,首先要確定其中心點要落在哪個cell上,然後計算這個cell的5個先驗框與ground truth的IOU值(YOLOv2中bias_match=1),計算IOU值時不考慮座標,只考慮形狀,所以先將先驗框與ground truth的中心點都偏移到同一位置(原點),然後計算出對應的IOU值,IOU值最大的那個先驗框與ground truth匹配,對應的預測框用來預測這個ground truth。
在計算obj置信度時,在YOLOv1中target=1,而YOLOv2增加了一個控制引數rescore,當其為1時,target取預測框與ground truth的真實IOU值。對於那些沒有與ground truth匹配的先驗框(與預測框對應),除去那些Max_IOU低於閾值的,其它的就全部忽略,不計算任何誤差。這點在YOLOv3論文中也有相關說明:YOLO中一個ground truth只會與一個先驗框匹配(IOU值最好的),對於那些IOU值超過一定閾值的先驗框,其預測結果就忽略了。這和SSD與RPN網路的處理方式有很大不同,因為它們可以將一個ground truth分配給多個先驗框。
儘管YOLOv2和YOLOv1計算loss處理上有不同,但都是採用均方差來計算loss。
另外需要注意的一點是,在計算boxes的和誤差時,YOLOv1中採用的是平方根以降低boxes的大小對誤差的影響,而YOLOv2是直接計算,但是根據ground truth的大小對權重係數進行修正:l.coord_scale * (2 - truth.w*truth.h),這樣對於尺度較小的boxes其權重係數會更大一些,起到和YOLOv1計算平方根相似的效果。

Stronger

帶標註的檢測資料集量比較少,而帶標註的分類資料集量比較大,因此YOLO9000主要通過結合分類和檢測資料集使得訓練得到的檢測模型可以檢測約9000類物體。
一方面要構造資料集(採用WordTree解決),另一方面要解決模型訓練問題(採用Joint classification and detection)。

Reference