YOLO9000演算法詳解
【原文:https://www.2cto.com/kf/201709/681474.html】
YOLO9000是CVPR2017的最佳論文提名。首先講一下這篇文章一共介紹了YOLOv2和YOLO9000兩個模型,二者略有不同。前者主要是YOLO的升級版,後者的主要檢測網路也是YOLOv2,同時對資料集做了融合,使得模型可以檢測9000多類物體。而提出YOLO9000的原因主要是目前檢測的資料集資料量較小,因此利用數量較大的分類資料集來幫助訓練檢測模型。
接下來基本上按照文章的順序來解讀一下演算法,這樣讀起來也比較清晰。主要包括三個部分:Better,Faster,Stronger,其中前面兩部分基本上講的是YOLOv2,最後一部分講的是YOLO9000。
Better
這部分細節很多,想要詳細瞭解的話建議還是看原始碼。
很明顯,本篇論文是YOLO作者為了改進原有的YOLO演算法所寫的。YOLO有兩個缺點:一個缺點在於定位不準確,另一個缺點在於和基於region proposal的方法相比召回率較低。因此YOLOv2主要是要在這兩方面做提升。另外YOLOv2並不是通過加深或加寬網路達到效果提升,反而是簡化了網路。大概看一下YOLOv2的表現:YOLOv2演算法在VOC 2007資料集上的表現為67 FPS時,MAP為76.8,在40FPS時,MAP為78.6.
1、Batch Normalization
BN(Batch Normalization)層簡單講就是對網路的每一層的輸入都做了歸一化,這樣網路就不需要每層都去學資料的分佈,收斂會快點。原來的YOLO演算法是沒有BN層的,因此在YOLOv2中作者為每個卷積層都新增了BN層。另外由於BN可以規範模型,所以本文加入BN後就把dropout去掉了。實驗證明新增了BN層可以提高2%的mAP。關於BN的具體介紹可以參考gooleNet的文章。
2、High Resolution Classifier
首先fine-tuning的作用不言而喻,現在基本跑個classification或detection的模型都不會從隨機初始化所有引數開始,所以一般都是用預訓練的網路來finetuning自己的網路,而且預訓練的網路基本上都是在ImageNet資料集上跑的,一方面資料量大,另一方面訓練時間久,而且這樣的網路都可以在相應的github上找到。
原來的YOLO網路在預訓練的時候採用的是224*224的輸入(這是因為一般預訓練的分類模型都是在ImageNet資料集上進行的),然後在detection的時候採用448*448的輸入,這會導致從分類模型切換到檢測模型的時候,模型還要適應影象解析度的改變。而YOLOv2則將預訓練分成兩步:先用224*224的輸入從頭開始訓練網路,大概160個epoch(表示將所有訓練資料迴圈跑160次),然後再將輸入調整到448*448,再訓練10個epoch。注意這兩步都是在ImageNet資料集上操作。最後再在檢測的資料集上fine-tuning,也就是detection的時候用448*448的影象作為輸入就可以順利過渡了。作者的實驗表明這樣可以提高几乎4%的MAP。
3、Convolutional With Anchor Boxes
原來的YOLO是利用全連線層直接預測bounding box的座標,而YOLOv2借鑑了Faster R-CNN的思想,引入anchor。首先將原網路的全連線層和最後一個pooling層去掉,使得最後的卷積層可以有更高解析度的特徵;然後縮減網路,用416*416大小的輸入代替原來448*448。這樣做的原因在於希望得到的特徵圖都有奇數大小的寬和高,奇數大小的寬和高會使得每個特徵圖在劃分cell的時候就只有一個center cell(比如可以劃分成7*7或9*9個cell,center cell只有一個,如果劃分成8*8或10*10的,center cell就有4個)。為什麼希望只有一個center cell呢?因為大的object一般會佔據影象的中心,所以希望用一個center cell去預測,而不是4個center cell去預測。網路最終將416*416的輸入變成13*13大小的feature map輸出,也就是縮小比例為32。
我們知道原來的YOLO演算法將輸入影象分成7*7的網格,每個網格預測兩個bounding box,因此一共只有98個box,但是在YOLOv2通過引入anchor boxes,預測的box數量超過了1千(以輸出feature map大小為13*13為例,每個grid cell有9個anchor box的話,一共就是13*13*9=1521個,當然由後面第4點可知,最終每個grid cell選擇5個anchor box)。順便提一下在Faster RCNN在輸入大小為1000*600時的boxes數量大概是6000,在SSD300中boxes數量是8732。顯然增加box數量是為了提高object的定位準確率。
作者的實驗證明:雖然加入anchor使得MAP值下降了一點(69.5降到69.2),但是提高了recall(81%提高到88%)。
4、Dimension Clusters
我們知道在Faster R-CNN中anchor box的大小和比例是按經驗設定的,然後網路會在訓練過程中調整anchor box的尺寸。但是如果一開始就能選擇到合適尺寸的anchor box,那肯定可以幫助網路越好地預測detection。所以作者採用k-means的方式對訓練集的bounding boxes做聚類,試圖找到合適的anchor box。
另外作者發現如果採用標準的k-means(即用歐式距離來衡量差異),在box的尺寸比較大的時候其誤差也更大,而我們希望的是誤差和box的尺寸沒有太大關係。所以通過IOU定義瞭如下的距離函式,使得誤差和box的大小無關:
如下圖Figure2,左邊是聚類的簇個數核IOU的關係,兩條曲線分別代表兩個不同的資料集。在分析了聚類的結果並平衡了模型複雜度與recall值,作者選擇了K=5,這也就是Figure2中右邊的示意圖是選出來的5個box的大小,這裡紫色和黑色也是分別表示兩個不同的資料集,可以看出其基本形狀是類似的。而且發現聚類的結果和手動設定的anchor box大小差別顯著。聚類的結果中多是高瘦的box,而矮胖的box數量較少。
Table1中作者採用的5種anchor(Cluster IOU)的Avg IOU是61,而採用9種Anchor Boxes的Faster RCNN的Avg IOU是60.9,也就是說本文僅選取5種box就能達到Faster RCNN的9中box的效果。
5、Direct Location prediction
作者在引入anchor box的時候遇到的第二個問題:模型不穩定,尤其是在訓練剛開始的時候。作者認為這種不穩定主要來自預測box的(x,y)值。我們知道在基於region proposal的object detection演算法中,是通過預測下圖中的tx和ty來得到(x,y)值,也就是預測的是offset。另外關於文中的這個公式,個人認為應該把後面的減號改成加號,這樣才能符合公式下面的example。這裡xa和ya是anchor的座標,wa和ha是anchor的size,x和y是座標的預測值,tx和ty是偏移量。文中還特地舉了一個例子:A prediction of tx = 1 would shift the box to the right by the width of the anchor box, a prediction of tx = 1 would shift it to the left by the same amount.
這裡貼一下Faster R-CNN裡面的公式,和上面這個公式將減號變成加號是一致的。
在這裡作者並沒有採用直接預測offset的方法,還是沿用了YOLO演算法中直接預測相對於grid cell的座標位置的方式。
前面提到網路在最後一個卷積層輸出13*13大小的feature map,然後每個cell預測5個bounding box,然後每個bounding box預測5個值:tx,ty,tw,th和to(這裡的to類似YOLOv1中的confidence)。看下圖,tx和ty經過sigmoid函式處理後範圍在0到1之間,這樣的歸一化處理也使得模型訓練更加穩定;cx和cy表示一個cell和影象左上角的橫縱距離;pw和ph表示bounding box的寬高,這樣bx和by就是cx和cy這個cell附近的anchor來預測tx和ty得到的結果。
如果對上面的公式不理解,可以看Figure3,首先是cx和cy,表示grid cell與影象左上角的橫縱座標距離,黑色虛線框是bounding box,藍色矩形框就是預測的結果。
6、Fine-Grained Features
這裡主要是新增了一個層:passthrough layer。這個層的作用就是將前面一層的26*26的feature map和本層的13*13的feature map進行連線,有點像ResNet。這樣做的原因在於雖然13*13的feature map對於預測大的object以及足夠了,但是對於預測小的object就不一定有效。也容易理解,越小的object,經過層層卷積和pooling,可能到最後都不見了,所以通過合併前一層的size大一點的feature map,可以有效檢測小的object。
7、Multi-Scale Training
為了讓YOLOv2模型更加robust,作者引入了Muinti-Scale Training,簡單講就是在訓練時輸入影象的size是動態變化的,注意這一步是在檢測資料集上fine tune時候採用的,不要跟前面在Imagenet資料集上的兩步預訓練分類模型混淆,本文細節確實很多。具體來講,在訓練網路時,每訓練10個batch(文中是10個batch,個人認為會不會是筆誤,不應該是10個epoch?),網路就會隨機選擇另一種size的輸入。那麼輸入影象的size的變化範圍要怎麼定呢?前面我們知道本文網路本來的輸入是416*416,最後會輸出13*13的feature map,也就是說downsample的factor是32,因此作者採用32的倍數作為輸入的size,具體來講文中作者採用從{320,352,…,608}的輸入尺寸。
這種網路訓練方式使得相同網路可以對不同解析度的影象做detection。雖然在輸入size較大時,訓練速度較慢,但同時在輸入size較小時,訓練速度較快,而multi-scale training又可以提高準確率,因此算是準確率和速度都取得一個不錯的平衡。
Table3就是在檢測時,不同輸入size情況下的YOLOv2和其他object detection演算法的對比。可以看出通過multi-scale training的檢測模型,在測試的時候,輸入影象在尺寸變化範圍較大的情況下也能取得mAP和FPS的平衡。不過同時也可以看出SSD演算法的表現也十分搶眼。
總的看下這些技巧對mAP的貢獻:
High Resolution Classifier的提升非常明顯(近4%),另外通過結合dimension prior+localtion prediction這兩種方式引入anchor也能帶來近5%mAP的提升。
Faster
在YOLO中,作者採用的訓練網路是基於GooleNet,這裡作者將GooleNet和VGG16做了簡單的對比,GooleNet在計算複雜度上要優於VGG16(8.25 billion operation VS 30.69 billion operation),但是前者在ImageNet上的top-5準確率要稍低於後者(88% VS 90%)。而在YOLOv2中,作者採用了新的分類模型作為基礎網路,那就是Darknet-19。
1、Darknet-19
Table6是最後的網路結構:Darknet-19只需要5.58 billion operation。這個網路包含19個卷積層和5個max pooling層。最後用average pooling層代替全連線層進行預測。這個網路在ImageNet上取得了top-5的91.2%的準確率。而在YOLO中採用的GooleNet,包含24個卷積層和2個全連線層。
2、Training for Classification
這裡的2和3部分在前面有提到,就是訓練處理的小trick。這裡的training for classification都是在ImageNet上進行預訓練,主要分兩步:1、從頭開始訓練Darknet-19,資料集是ImageNet,訓練160個epoch,輸入影象的大小是224*224,初始學習率為0.1。另外在訓練的時候採用了標準的資料增加方式比如隨機裁剪,旋轉以及色度,亮度的調整等。2、再fine-tuning 網路,這時候採用448*448的輸入,引數的除了epoch和learning rate改變外,其他都沒變,這裡learning rate改為0.001,並訓練10個epoch。結果表明fine-tuning後的top-1準確率為76.5%,top-5準確率為93.3%,而如果按照原來的訓練方式,Darknet-19的top-1準確率是72.9%,top-5準確率為91.2%。因此可以看出第1,2兩步分別從網路結構和訓練方式兩方面入手提高了主網路的分類準確率。
3、Training for Detection
在前面第2步之後,就開始把網路移植到detection,並開始基於檢測的資料再進行fine-tuning。首先把最後一個卷積層去掉,然後新增3個3*3的卷積層,每個卷積層有1024個filter,而且每個後面都連線一個1*1的卷積層,1*1卷積的filter個數根據需要檢測的類來定。比如對於VOC資料,由於每個grid cell我們需要預測5個box,每個box有5個座標值和20個類別值,所以每個grid cell有125個filter(與YOLOv1不同,在YOLOv1中每個grid cell有30個filter,還記得那個7*7*30的矩陣嗎,而且在YOLOv1中,類別概率是由grid cell來預測的,也就是說一個grid cell對應的兩個box的類別概率是一樣的,但是在YOLOv2中,類別概率是屬於box的,每個box對應一個類別概率,而不是由grid cell決定,因此這邊每個box對應25個預測值(5個座標加20個類別值),而在YOLOv1中一個grid cell的兩個box的20個類別值是一樣的)。另外作者還提到將最後一個3*3*512的卷積層和倒數第二個卷積層相連。最後作者在檢測資料集上fine tune這個預訓練模型160個epoch,學習率採用0.001,並且在第60和90epoch的時候將學習率除以10,weight decay採用0.0005。
Stronger
這部分看得不是很懂,簡單介紹,歡迎指正。帶標註的檢測資料集量比較少,而帶標註的分類資料集量比較大,因此YOLO9000主要通過結合分類和檢測資料集使得訓練得到的檢測模型可以檢測約9000類物體,那麼這是怎麼做到的呢?一方面要構造資料集,另一方面要解決模型訓練問題,前者採用WordTree解決,後者採用Joint classification and detection。
先來介紹下怎麼做據集的融合,我們知道分類和檢測資料集存在較大差別:Detection datasets have only common objects and general labels, like “dog” or “boat”. Classification datasets have a much wider and deeper range of labels. ImageNet has more than a hundred breeds of dog, including “Norfolk terrier”, “Yorkshire terrier”, and “Bedlington terrier”.
ImageNet的標籤來自WordNet,這種結構不是tree,舉個例子,狗這個label即屬於犬科也屬於家畜,這就很複雜了,完全是個圖結構,因此作者採用WordTree來解決分類和檢測資料集的標籤問題,也就是說在這個樹裡面任意一個節點只能屬於唯一一個節點(跟WordNet是有區別的)。
這樣的話,在WordTree的某個節點上就可以計算該節點的一些條件概率值,比如在terrier這個節點,可以得到如下條件概率值:
如果要預測一個節點的概率,可以根據WordTree將該節點到根節點的條件概率依次相乘得到,如下式:
另外:
按照這種方式,就可以得到Figure5,也就是在Imagenet1k資料集上採用WordTree方式得到的類別(主要是增加了369箇中間節點,比如dog等)。然後作者分別在Figure5的兩個資料集上用相同訓練方法訓練Darknet-19模型,最後在Imagenet1k資料集上的top-1 accuracy為72.9%,top-5 accuracy為91.2%;在WordTree1k資料集上的top-1 accuracy為71.9%,top-5 accuracy為90.4%。在WordTree1k資料集上的準確率要稍低一點,主要是因為那些新的類別的影響。
介紹完了WordTree的原理,就可以用WordTree來融合分類和檢測的資料集了。Figure6是COCO和ImageNet資料集以及WordTree的示意圖。在WordTree中用顏色區分了COCO資料集和ImageNet資料集的label節點。
前面介紹完了如何融合分類和檢測的資料集,接下來就是訓練的問題了,文中採用的是Joint classification and detection,什麼意思呢?原文表述如下:During training we mix images from both detection and classification datasets. When our network sees an image labelled for detection we can backpropagate based on the full YOLOv2 loss function. When it sees a classification image we only backpropagate loss from the classification specific parts of the architecture.
這個joint classification and detection的直觀解釋就是:Using this joint training, YOLO9000 learns to find objects in images using the detection data in COCO and it learns to classify a wide variety of these objects using data from ImageNet.
另外YOLO9000的主網路基本和YOLOv2類似,只不過每個grid cell只採用3個box prior。
相關文章
- YOLO9000論文詳讀YOLO
- CTC演算法詳解演算法
- Manacher演算法詳解演算法
- 詳解BitMap演算法演算法
- KMP演算法詳解KMP演算法
- BitMap演算法詳解演算法
- 演算法 | 快速排序詳解演算法排序
- Kd Tree演算法詳解演算法
- Crypto演算法庫詳解演算法
- 尋路演算法之A*演算法詳解演算法
- YOLOP 多工演算法詳解YOLO演算法
- Python遞迴演算法詳解Python遞迴演算法
- Distributed Mutual Exclusion演算法詳解演算法
- Vue-diff演算法詳解Vue演算法
- MD5演算法詳解演算法
- Raft共識演算法詳解Raft演算法
- 詳解vue的diff演算法Vue演算法
- Paxos共識演算法詳解演算法
- python遺傳演算法(詳解)Python演算法
- DES演算法例項詳解演算法
- HTTPS詳解-加密演算法(一)HTTP加密演算法
- 什麼BRIEF演算法?BRIEF演算法詳解演算法
- 字串匹配演算法(二)-BM演算法詳解字串匹配演算法
- 模型壓縮-剪枝演算法詳解模型演算法
- AI美顏SDK演算法詳解AI演算法
- 詳解 BackPropagation 反向傳播演算法!反向傳播演算法
- A*尋路演算法詳細解讀演算法
- 【字串演算法】字典樹詳解字串演算法
- HTTPS詳解-加密演算法(二)完HTTP加密演算法
- 美顏SDK功能演算法詳解演算法
- 詳解裝置指紋核心演算法演算法
- sku演算法詳解及Demo~接上篇演算法
- 深入理解SVM,詳解SMO演算法演算法
- 遺傳演算法詳解與實驗演算法
- 二分查詢演算法詳解演算法
- 詳解虛擬DOM與Diff演算法演算法
- 十大排序演算法詳解排序演算法
- 「leetcode」78. 子集【回溯演算法】詳解!LeetCode演算法