目標檢測|YOLOv2原理與實現(附YOLOv3)

2021-02-13 機器學習算法工程師

在前面的一篇文章中,我們詳細介紹了YOLOv1的原理以及實現過程。這篇文章接著介紹YOLOv2的原理以及實現,YOLOv2的論文全名為YOLO9000: Better, Faster, Stronger,它斬獲了CVPR 2017 Best Paper Honorable Mention。在這篇文章中,作者首先在YOLOv1的基礎上提出了改進的YOLOv2,然後提出了一種檢測與分類聯合訓練方法,使用這種聯合訓練方法在COCO檢測數據集和ImageNet分類數據集上訓練出了YOLO9000模型,其可以檢測超過9000多類物體。所以,這篇文章其實包含兩個模型:YOLOv2和YOLO9000,不過後者是在前者基礎上提出的,兩者模型主體結構是一致的。YOLOv2相比YOLOv1做了很多方面的改進,這也使得YOLOv2的mAP有顯著的提升,並且YOLOv2的速度依然很快,保持著自己作為one-stage方法的優勢,YOLOv2和Faster R-CNN, SSD等模型的對比如圖1所示。這裡將首先介紹YOLOv2的改進策略,並給出YOLOv2的TensorFlow實現過程,然後介紹YOLO9000的訓練方法。近期,YOLOv3也放出來了,YOLOv3也在YOLOv2的基礎上做了一部分改進,我們在最後也會簡單談談YOLOv3所做的改進工作。

圖1:YOLOv2與其它模型在VOC 2007數據集上的效果對比

YOLOv1雖然檢測速度很快,但是在檢測精度上卻不如R-CNN系檢測方法,YOLOv1在物體定位方面(localization)不夠準確,並且召回率(recall)較低。YOLOv2共提出了幾種改進策略來提升YOLO模型的定位準確度和召回率,從而提高mAP,YOLOv2在改進中遵循一個原則:保持檢測速度,這也是YOLO模型的一大優勢。YOLOv2的改進策略如圖2所示,可以看出,大部分的改進方法都可以比較顯著提升模型的mAP。下面詳細介紹各個改進策略。

圖2:YOLOv2相比YOLOv1的改進策略

(1)Batch Normalization

Batch Normalization可以提升模型收斂速度,而且可以起到一定正則化效果,降低模型的過擬合。在YOLOv2中,每個卷積層後面都添加了Batch Normalization層,並且不再使用droput。使用Batch Normalization後,YOLOv2的mAP提升了2.4%。

(2)High Resolution Classifier

目前大部分的檢測模型都會在先在ImageNet分類數據集上預訓練模型的主體部分(CNN特徵提取器),由於歷史原因,ImageNet分類模型基本採用大小為

的圖片作為輸入,解析度相對較低,不利於檢測模型。所以YOLOv1在採用分類模型預訓練後,將解析度增加至,並使用這個高解析度在檢測數據集上finetune。但是直接切換解析度,檢測模型可能難以快速適應高解析度。所以YOLOv2增加了在ImageNet數據集上使用來finetune分類網絡這一中間過程(10 epochs),這可以使得模型在檢測數據集上finetune之前已經適用高解析度輸入。使用高解析度分類器後,YOLOv2的mAP提升了約4%。

(3)Convolutionlal With Anchor Boxes

在YOLOv1中,輸入圖片最終被劃分為7*7網格,每個單元格預測2個邊界框。YOLOv1最後採用的是全連接層直接對邊界框進行預測,其中邊界框的寬與高是相對整張圖片大小的,而由於各個圖片中存在不同尺度和長寬比(scales and ratios)的物體,YOLOv1在訓練過程中學習適應不同物體的形狀是比較困難的,這也導致YOLOv1在精確定位方面表現較差。YOLOv2借鑑了Faster R-CNN中RPN網絡的先驗框(anchor boxes,prior boxes,SSD也採用了先驗框)策略。RPN對CNN特徵提取器得到的特徵圖(feature map)進行卷積來預測每個位置的邊界框以及置信度(是否含有物體),並且各個位置設置不同尺度和比例的先驗框,所以RPN預測的是邊界框相對於先驗框的offsets值(其實是transform值,詳細見Faster R_CNN論文),採用先驗框使得模型更容易學習。所以YOLOv2移除了YOLOv1中的全連接層而採用了卷積和anchor boxes來預測邊界框。為了使檢測所用的特徵圖解析度更高,移除其中的一個pool層。在檢測模型中,YOLOv2不是採481*418圖片作為輸入,而是採用416*416大小。因為YOLOv2模型下採樣的總步長為32,對於416*416大小的圖片,最終得到的特徵圖大小為13*13,維度是奇數,這樣特徵圖恰好只有一個中心位置。對於一些大物體,它們中心點往往落入圖片中心位置,此時使用特徵圖的一個中心點去預測這些物體的邊界框相對容易些。所以在YOLOv2設計中要保證最終的特徵圖有奇數個位置。對於YOLOv1,每個cell都預測2個boxes,每個boxes包含5個值:前4個值是邊界框位置與大小,最後一個值是置信度(confidence scores,包含兩部分:含有物體的概率以及預測框與ground truth的IOU)。但是每個cell只預測一套分類概率值(class predictions,其實是置信度下的條件概率值),供2個boxes共享。YOLOv2使用了anchor boxes之後,每個位置的各個anchor box都單獨預測一套分類概率值,這和SSD比較類似(但SSD沒有預測置信度,而是把background作為一個類別來處理)。

使用anchor boxes之後,YOLOv2的mAP有稍微下降(這裡下降的原因,我猜想是YOLOv2雖然使用了anchor boxes,但是依然採用YOLOv1的訓練方法)。YOLOv1隻能預測98個邊界框,而YOLOv2使用anchor boxes之後可以預測上千個邊界框。所以使用anchor boxes之後,YOLOv2的召回率大大提升,由原來的81%升至88%。

(4)Dimension Clusters

在Faster R-CNN和SSD中,先驗框的維度(長和寬)都是手動設定的,帶有一定的主觀性。如果選取的先驗框維度比較合適,那麼模型更容易學習,從而做出更好的預測。因此,YOLOv2採用k-means聚類方法對訓練集中的邊界框做了聚類分析。因為設置先驗框的主要目的是為了使得預測框與ground truth的IOU更好,所以聚類分析時選用box與聚類中心box之間的IOU值作為距離指標: 

圖3為在VOC和COCO數據集上的聚類分析結果,隨著聚類中心數目的增加,平均IOU值(各個邊界框與聚類中心的IOU的平均值)是增加的,但是綜合考慮模型複雜度和召回率,作者最終選取5個聚類中心作為先驗框,其相對於圖片的大小如右邊圖所示。對於兩個數據集,5個先驗框的width和height如下所示(來源:YOLO源碼的cfg文件):

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)。對比兩個數據集,也可以看到COCO數據集上的物體相對小點。這個策略作者並沒有單獨做實驗,但是作者對比了採用聚類分析得到的先驗框與手動設置的先驗框在平均IOU上的差異,發現前者的平均IOU值更高,因此模型更容易訓練學習。

圖3:數據集VOC和COCO上的邊界框聚類分析結果

(5) New Network:Darknet-19

YOLOv2採用了一個新的基礎模型(特徵提取器),稱為Darknet-19,包括19個卷積層和5個maxpooling層,如圖4所示。Darknet-19與VGG16模型設計原則是一致的,主要採用3*3卷積,採用2*2的maxpooling層之後,特徵圖維度降低2倍,而同時將特徵圖的channles增加兩倍。與NIN(Network in Network)類似,Darknet-19最終採用global avgpooling做預測,並且在3*3卷積之間使用1*1卷積來壓縮特徵圖channles以降低模型計算量和參數。Darknet-19每個卷積層後面同樣使用了batch norm層以加快收斂速度,降低模型過擬合。在ImageNet分類數據集上,Darknet-19的top-1準確度為72.9%,top-5準確度為91.2%,但是模型參數相對小一些。使用Darknet-19之後,YOLOv2的mAP值沒有顯著提升,但是計算量卻可以減少約33%。

圖4:Darknet-19模型結構

(6) Direct location prediction

前面講到,YOLOv2借鑑RPN網絡使用anchor boxes來預測邊界框相對先驗框的offsets。邊界框的實際中心位置,需要根據預測的坐標偏移值,先驗框的尺度以及中心坐標(特徵圖每個位置的中心點)來計算:

 但是上面的公式是無約束的,預測的邊界框很容易向任何方向偏移,如當時邊界框將向右偏移先驗框的一個寬度大小,而當時邊界框將向左偏移先驗框的一個寬度大小,因此每個位置預測的邊界框可以落在圖片任何位置,這導致模型的不穩定性,在訓練時需要很長時間來預測出正確的offsets。所以,YOLOv2棄用了這種預測方式,而是沿用YOLOv1的方法,就是預測邊界框中心點相對於對應cell左上角位置的相對偏移值,為了將邊界框中心點約束在當前cell中,使用sigmoid函數處理偏移值,這樣預測的偏移值在(0,1)範圍內(每個cell的尺度看做1)。總結來看,根據邊界框預測的4個offsets,可以按如下公式計算出邊界框實際位置和大小: 

其中為cell的左上角坐標,如圖5所示,在計算時每個cell的尺度為1,所以當前cell的左上角坐標為。由於sigmoid函數的處理,邊界框的中心位置會約束在當前cell內部,防止偏移過多。而是先驗框的寬度與長度,前面說過它們的值也是相對於特徵圖大小的,在特徵圖中每個cell的長和寬均為1。這裡記特徵圖的大小為(在文中是),這樣我們可以將邊界框相對於整張圖片的位置和大小計算出來(4個值均在0和1之間): 

如果再將上面的4個值分別乘以圖片的寬度和長度(像素點值)就可以得到邊界框的最終位置和大小了。這就是YOLOv2邊界框的整個解碼過程。約束了邊界框的位置預測值使得模型更容易穩定訓練,結合聚類分析得到先驗框與這種預測方法,YOLOv2的mAP值提升了約5%。

圖5:邊界框位置與大小的計算示例圖

(7)Fine-Grained Features  

YOLOv2的輸入圖片大小為416*416,經過5次maxpooling之後得到13*13大小的特徵圖,並以此特徵圖採用卷積做預測。13*13大小的特徵圖對檢測大物體是足夠了,但是對於小物體還需要更精細的特徵圖(Fine-Grained Features)。因此SSD使用了多尺度的特徵圖來分別檢測不同大小的物體,前面更精細的特徵圖可以用來預測小物體。YOLOv2提出了一種passthrough層來利用更精細的特徵圖。YOLOv2所利用的Fine-Grained Features是26*26大小的特徵圖(最後一個maxpooling層的輸入),對於Darknet-19模型來說就是大小為26*26*512的特徵圖。passthrough層與ResNet網絡的shortcut類似,以前面更高解析度的特徵圖為輸入,然後將其連接到後面的低解析度特徵圖上。前面的特徵圖維度是後面的特徵圖的2倍,passthrough層抽取前面層的每個2*2的局部區域,然後將其轉化為channel維度,對於26*26*512的特徵圖,經passthrough層處理之後就變成了13*13*2048的新特徵圖(特徵圖大小降低4倍,而channles增加4倍,圖6為一個實例),這樣就可以與後面的13*13*1024特徵圖連接在一起形成13*13*3072的特徵圖,然後在此特徵圖基礎上卷積做預測。在YOLO的C源碼中,passthrough層稱為reorg layer。在TensorFlow中,可以使用tf.extract_image_patches或者tf.space_to_depth來實現passthrough層:

out = tf.extract_image_patches(in, [1, stride, stride, 1], [1, stride, stride, 1], [1,1,1,1], padding="VALID")

out = tf.space_to_depth(in, 2)

圖6:passthrough層實例

另外,作者在後期的實現中借鑑了ResNet網絡,不是直接對高分辨特徵圖處理,而是增加了一個中間卷積層,先採用64個1*1卷積核進行卷積,然後再進行passthrough處理,這樣26*26*512的特徵圖得到13*13*256的特徵圖。這算是實現上的一個小細節。使用Fine-Grained Features之後YOLOv2的性能有1%的提升。

(8)Multi-Scale Training

由於YOLOv2模型中只有卷積層和池化層,所以YOLOv2的輸入可以不限於416*416大小的圖片。為了增強模型的魯棒性,YOLOv2採用了多尺度輸入訓練策略,具體來說就是在訓練過程中每間隔一定的iterations之後改變模型的輸入圖片大小。由於YOLOv2的下採樣總步長為32,輸入圖片大小選擇一系列為32倍數的值:輸入圖片最小為320*320,此時對應的特徵圖大小為10*10(不是奇數了,確實有點尷尬),而輸入圖片最大為608*608,對應的特徵圖大小為19*19,在訓練過程,每隔10個iterations隨機選擇一種輸入圖片大小,然後只需要修改對最後檢測層的處理就可以重新訓練。 

圖7:Multi-Scale Training

採用Multi-Scale Training策略,YOLOv2可以適應不同大小的圖片,並且預測出很好的結果。在測試時,YOLOv2可以採用不同大小的圖片作為輸入,在VOC 2007數據集上的效果如下圖所示。可以看到採用較小解析度時,YOLOv2的mAP值略低,但是速度更快,而採用高分辨輸入時,mAP值更高,但是速度略有下降,對於544*544,mAP高達78.6%。注意,這只是測試時輸入圖片大小不同,而實際上用的是同一個模型(採用Multi-Scale Training訓練)。 

圖8:YOLOv2在VOC 2007數據集上的性能對比

總結來看,雖然YOLOv2做了很多改進,但是大部分都是借鑑其它論文的一些技巧,如Faster R-CNN的anchor boxes,YOLOv2採用anchor boxes和卷積做預測,這基本上與SSD模型(單尺度特徵圖的SSD)非常類似了,而且SSD也是借鑑了Faster R-CNN的RPN網絡。從某種意義上來說,YOLOv2和SSD這兩個one-stage模型與RPN網絡本質上無異,只不過RPN不做類別的預測,只是簡單地區分物體與背景。在two-stage方法中,RPN起到的作用是給出region proposals,其實就是作出粗糙的檢測,所以另外增加了一個stage,即採用R-CNN網絡來進一步提升檢測的準確度(包括給出類別預測)。而對於one-stage方法,它們想要一步到位,直接採用「RPN」網絡作出精確的預測,要因此要在網絡設計上做很多的tricks。YOLOv2的一大創新是採用Multi-Scale Training策略,這樣同一個模型其實就可以適應多種大小的圖片了。

YOLOv2的訓練主要包括三個階段。第一階段就是先在ImageNet分類數據集上預訓練Darknet-19,此時模型輸入為224*224,共訓練160個epochs。然後第二階段將網絡的輸入調整為448*448,繼續在ImageNet數據集上finetune分類模型,訓練10個epochs,此時分類模型的top-1準確度為76.5%,而top-5準確度為93.3%。第三個階段就是修改Darknet-19分類模型為檢測模型,並在檢測數據集上繼續finetune網絡。網絡修改包括(網路結構可視化):移除最後一個卷積層、global avgpooling層以及softmax層,並且新增了三個3*3*2014卷積層,同時增加了一個passthrough層,最後使用1*1卷積層輸出預測結果,輸出的channels數為:,和訓練採用的數據集有關係。由於anchors數為5,對於VOC數據集輸出的channels數就是125,而對於COCO數據集則為425。這裡以VOC數據集為例,最終的預測矩陣為T(shape為),可以先將其reshape為

,其中為邊界框的位置和大小

為邊界框的置信度,而為類別預測值。

圖9:YOLOv2訓練的三個階段

圖10:YOLOv2結構示意圖

YOLOv2的網絡結構以及訓練參數我們都知道了,但是貌似少了點東西。仔細一想,原來作者並沒有給出YOLOv2的訓練過程的兩個最重要方面,即先驗框匹配(樣本選擇)以及訓練的損失函數,難怪Ng說YOLO論文很難懂,沒有這兩方面的說明我們確實不知道YOLOv2到底是怎麼訓練起來的。不過默認按照YOLOv1的處理方式也是可以處理,我看了YOLO在TensorFlow上的實現darkflow(見yolov2/train.py),發現它就是如此處理的:和YOLOv1一樣,對於訓練圖片中的ground truth,若其中心點落在某個cell內,那麼該cell內的5個先驗框所對應的邊界框負責預測它,具體是哪個邊界框預測它,需要在訓練中確定,即由那個與ground truth的IOU最大的邊界框預測它,而剩餘的4個邊界框不與該ground truth匹配。YOLOv2同樣需要假定每個cell至多含有一個grounth truth,而在實際上基本不會出現多於1個的情況。與ground truth匹配的先驗框計算坐標誤差、置信度誤差(此時target為1)以及分類誤差,而其它的邊界框只計算置信度誤差(此時target為0)。YOLOv2和YOLOv1的損失函數一樣,為均方差函數。但是我看了YOLOv2的源碼(訓練樣本處理與loss計算都包含在文件region_layer.c中,YOLO源碼沒有任何注釋,反正我看了是直搖頭),並且參考國外的blog以及allanzelener/YAD2K(Ng深度學習教程所參考的那個Keras實現)上的實現,發現YOLOv2的處理比原來的v1版本更加複雜。先給出loss計算公式:

我們來一點點解釋,首先W,H分別指的是特徵圖(13*13)的寬與高,而A指的是先驗框數目(這裡是5),各個值是各個loss部分的權重係數。第一項loss是計算background的置信度誤差,但是哪些預測框來預測背景呢,需要先計算各個預測框和所有ground truth的IOU值,並且取最大值Max_IOU,如果該值小於一定的閾值(YOLOv2使用的是0.6),那麼這個預測框就標記為background,需要計算noobj的置信度誤差。第二項是計算先驗框與預測寬的坐標誤差,但是只在前12800個iterations間計算,我覺得這項應該是在訓練前期使預測框快速學習到先驗框的形狀。第三大項計算與某個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計算平方根相似的效果(參考YOLO v2 損失函數源碼分析)。

最終的YOLOv2模型在速度上比YOLOv1還快(採用了計算量更少的Darknet-19模型),而且模型的準確度比YOLOv1有顯著提升,詳情見paper。

YOLOv2在TensorFlow上實現

這裡參考YOLOv2在Keras上的復現(見yhcc/yolo2),使用TensorFlow實現YOLOv2在COCO數據集上的test過程。首先是定義YOLOv2的主體網絡結構Darknet-19:

def darknet(images, n_last_channels=425):
   """Darknet19 for YOLOv2"""
   net = conv2d(images, 32, 3, 1, name="conv1")
   net = maxpool(net, name="pool1")
   net = conv2d(net, 64, 3, 1, name="conv2")
   net = maxpool(net, name="pool2")
   net = conv2d(net, 128, 3, 1, name="conv3_1")
   net = conv2d(net, 64, 1, name="conv3_2")
   net = conv2d(net, 128, 3, 1, name="conv3_3")
   net = maxpool(net, name="pool3")
   net = conv2d(net, 256, 3, 1, name="conv4_1")
   net = conv2d(net, 128, 1, name="conv4_2")
   net = conv2d(net, 256, 3, 1, name="conv4_3")
   net = maxpool(net, name="pool4")
   net = conv2d(net, 512, 3, 1, name="conv5_1")
   net = conv2d(net, 256, 1, name="conv5_2")
   net = conv2d(net, 512, 3, 1, name="conv5_3")
   net = conv2d(net, 256, 1, name="conv5_4")
   net = conv2d(net, 512, 3, 1, name="conv5_5")
   shortcut = net
   net = maxpool(net, name="pool5")
   net = conv2d(net, 1024, 3, 1, name="conv6_1")
   net = conv2d(net, 512, 1, name="conv6_2")
   net = conv2d(net, 1024, 3, 1, name="conv6_3")
   net = conv2d(net, 512, 1, name="conv6_4")
   net = conv2d(net, 1024, 3, 1, name="conv6_5")
   # ----
   net = conv2d(net, 1024, 3, 1, name="conv7_1")
   net = conv2d(net, 1024, 3, 1, name="conv7_2")
   # shortcut
   shortcut = conv2d(shortcut, 64, 1, name="conv_shortcut")
   shortcut = reorg(shortcut, 2)
   net = tf.concat([shortcut, net], axis=-1)
   net = conv2d(net, 1024, 3, 1, name="conv8")
   # detection layer
   net = conv2d(net, n_last_channels, 1, batch_normalize=0,
                activation=None, use_bias=True, name="conv_dec")
   return net

然後實現對Darknet-19模型輸出的解碼:

def decode(detection_feat, feat_sizes=(13, 13), num_classes=80,
          anchors=None):
   """decode from the detection feature"""
   H, W = feat_sizes
   num_anchors = len(anchors)
   detetion_results = tf.reshape(detection_feat, [-1, H * W, num_anchors,
                                       num_classes + 5])

   bbox_xy = tf.nn.sigmoid(detetion_results[:, :, :, 0:2])
   bbox_wh = tf.exp(detetion_results[:, :, :, 2:4])
   obj_probs = tf.nn.sigmoid(detetion_results[:, :, :, 4])
   class_probs = tf.nn.softmax(detetion_results[:, :, :, 5:])

   anchors = tf.constant(anchors, dtype=tf.float32)

   height_ind = tf.range(H, dtype=tf.float32)
   width_ind = tf.range(W, dtype=tf.float32)
   x_offset, y_offset = tf.meshgrid(height_ind, width_ind)
   x_offset = tf.reshape(x_offset, [1, -1, 1])
   y_offset = tf.reshape(y_offset, [1, -1, 1])

   # decode
   bbox_x = (bbox_xy[:, :, :, 0] + x_offset) / W
   bbox_y = (bbox_xy[:, :, :, 1] + y_offset) / H
   bbox_w = bbox_wh[:, :, :, 0] * anchors[:, 0] / W * 0.5
   bbox_h = bbox_wh[:, :, :, 1] * anchors[:, 1] / H * 0.5

   bboxes = tf.stack([bbox_x - bbox_w, bbox_y - bbox_h,
                      bbox_x + bbox_w, bbox_y + bbox_h], axis=3)

   return bboxes, obj_probs, class_probs

我將YOLOv2的官方訓練權重文件轉換了TensorFlow的checkpoint文件(下載連結),具體的測試demo都放在我的GitHub上了,感興趣的可以去下載測試一下,至於train的實現就自己折騰吧,相對會棘手點。

圖11:YOLOv2在自然圖片上的測試

YOLO9000

YOLO9000是在YOLOv2的基礎上提出的一種可以檢測超過9000個類別的模型,其主要貢獻點在於提出了一種分類和檢測的聯合訓練策略。眾多周知,檢測數據集的標註要比分類數據集打標籤繁瑣的多,所以ImageNet分類數據集比VOC等檢測數據集高出幾個數量級。在YOLO中,邊界框的預測其實並不依賴於物體的標籤,所以YOLO可以實現在分類和檢測數據集上的聯合訓練。對於檢測數據集,可以用來學習預測物體的邊界框、置信度以及為物體分類,而對於分類數據集可以僅用來學習分類,但是其可以大大擴充模型所能檢測的物體種類。

作者選擇在COCO和ImageNet數據集上進行聯合訓練,但是遇到的第一問題是兩者的類別並不是完全互斥的,比如"Norfolk terrier"明顯屬於"dog",所以作者提出了一種層級分類方法(Hierarchical classification),主要思路是根據各個類別之間的從屬關係(根據WordNet)建立一種樹結構WordTree,結合COCO和ImageNet建立的WordTree如下圖所示:


圖12:基於COCO和ImageNet數據集建立的WordTree

WordTree中的根節點為"physical object",每個節點的子節點都屬於同一子類,可以對它們進行softmax處理。在給出某個類別的預測概率時,需要找到其所在的位置,遍歷這個path,然後計算path上各個節點的概率之積。

圖13:ImageNet與WordTree預測的對比

在訓練時,如果是檢測樣本,按照YOLOv2的loss計算誤差,而對於分類樣本,只計算分類誤差。在預測時,YOLOv2給出的置信度就是,同時會給出邊界框位置以及一個樹狀概率圖。在這個概率圖中找到概率最高的路徑,當達到某一個閾值時停止,就用當前節點表示預測的類別。

通過聯合訓練策略,YOLO9000可以快速檢測出超過9000個類別的物體,總體mAP值為19,7%。我覺得這是作者在這篇論文作出的最大的貢獻,因為YOLOv2的改進策略亮點並不是很突出,但是YOLO9000算是開創之舉。

YOLOv3

近期,YOLOv3發布了,但是正如作者所說,這僅僅是他們近一年的一個工作報告(TECH REPORT),不算是一個完整的paper,因為他們實際上是把其它論文的一些工作在YOLO上嘗試了一下。相比YOLOv2,我覺得YOLOv3最大的變化包括兩點:使用殘差模型和採用FPN架構。YOLOv3的特徵提取器是一個殘差模型,因為包含53個卷積層,所以稱為Darknet-53,從網絡結構上看,相比Darknet-19網絡使用了殘差單元,所以可以構建得更深。另外一個點是採用FPN架構(Feature Pyramid Networks for Object Detection)來實現多尺度檢測。YOLOv3採用了3個尺度的特徵圖(當輸入為416*416時):(13*13),(26*26),(52*52),VOC數據集上的YOLOv3網絡結構如圖15所示,其中紅色部分為各個尺度特徵圖的檢測結果。YOLOv3每個位置使用3個先驗框,所以使用k-means得到9個先驗框,並將其劃分到3個尺度特徵圖上,尺度更大的特徵圖使用更小的先驗框,和SSD類似。

圖14:YOLOv3所用的Darknet-53模型

圖15 YOLOv3網絡結構示意圖(VOC數據集)

YOLOv3與其它檢測模型的對比如下圖所示,可以看到在速度上YOLOv3完勝其它方法,雖然AP值並不是最好的(如果比較AP-0.5,YOLOv3優勢更明顯)。

圖16:YOLOv3在COCO測試集與其它檢測算法對比圖

從YOLO的三代變革中可以看到,在目標檢測領域比較好的策略包含:設置先驗框,採用全卷積做預測,採用殘差網絡,採用多尺度特徵圖做預測。期待未來有更好的策略出現。本人水平有限,文中難免出現錯誤,歡迎指正!

Darknet官網.

thtrieu/darkflow.

You Only Look Once: Unified, Real-Time Object Detection.

YOLO9000: Better, Faster, Stronger.

YOLOv3: An Incremental Improvement.

yhcc/yolo2.

pytorch-yolo2.

Training Object Detection (YOLOv2) from scratch using Cyclic Learning Rates.

allanzelener/YAD2K.

marvis/pytorch-yolo3.

機器學習算法全棧工程師

                            一個用心的公眾號

長按,識別,加關注

進群,學習,得幫助

你的關注,我們的熱度,

我們一定給你學習最大的幫助

免費課程福利



相關焦點

  • 目標檢測︱自有數據YOLOv3訓練,最簡單的keras實現教程
    該項目集合了從 2013 年 11 月提出的 R-CNN 至在近期舉辦的 ECCV2018 上發表的 RFBNet 等四十多篇關於目標檢測的論文,相當全面。一般目標檢測問題本身的定義為:給定任意一張圖像,確定其中是否存在任何預定義類別的形義目標實例;如果存在,就返回其空間位置和覆蓋範圍。目標(object,也可譯為「對象」或「物體」)是指可以被看見和觸碰的有形事物。
  • 目標檢測 | 在自己數據集上利用YOLOv3實現目標檢測訓練全流程
    該文件表示的是你的檢測網絡的結構,類似caffe的prototxt文件。  [YOLOv3的cfg文件](https://github.com/qiu931110/darknet/blob/master/cfg/yolov3.cfg[無上採樣YOLOv3的cfg文件]https://github.com/qiu931110/darknet/blob/master/cfg/yolov3_change.cfg如下文件中規定了當前目標檢測網絡中的類別數量為
  • 一個目標檢測的 Hello World項目(手把手帶你搭建yolov3)
    本文主要介紹的是使用Pytorch搭建YOLOv3目標檢測網絡,並從頭開始訓練自定義數據集。/utils文件夾下的gen_classes.py腳本,並可以統計數據集中存在的待檢測目標,並將目標名稱寫入到classes.names,生成的classes.names文件被保存與./data/voc2007/train文件夾下:cd utils/ # 進入到utils文件夾python gen_classes.py # 運行腳本.
  • 使用YOLOv3訓練自己數據的目標檢測
    點擊我愛計算機視覺標星,更快獲取CVML新技術YOLOv3是當前計算機視覺中最為流行的實時目標檢測算法之一。
  • 實戰 | keras-yolov3 + Kalman-Filter 進行人體多目標追蹤(含代碼)
    +Kalman-Filter 的人體多目標跟蹤算法。算法的缺陷是不夠穩定,筆者本項目嘗試的是keras-yolov3,在開闊場景沒問題,但是在一切人密度較大,遮擋物較多,像素不夠高清的視頻上發現檢測器容易遺漏物體,前兩幀可以檢測,後面幾幀斷了,然後又續上了。
  • 如何用自己的數據訓練YOLOv3目標檢測器
    在工業界,即使精度稍差,YOLO往往也會比一些Two-Stage的目標檢測器更受青睞,因為它是真的很快,完全能滿足實時性的應用要求。YOLO最新的版本是YOLOv3,主要改進是提升了小目標檢測的效果。YOLOv3官方的權重是在COCO數據集上訓練的,總共有80類目標,但是在實際應用中,我們往往需要檢測特定的目標。比如在自動駕駛應用中,我們需要檢測的目標有汽車、行人、自行車、交通燈、交通標誌等。
  • 基於PaddleDetection的錐桶檢測並在Gazebo環境中實現部署
    實現在X86 Linux環境中的部署。項目開始前,咱們先介紹一下本項目使用到的兩個工具:PaddleDetection是飛槳的目標檢測開發套件,模塊化集成了主流的目標檢測算法,並向用戶提供了豐富且自由的接口實現數據增強、自定義網絡模塊、損失函數、訓練配置等。
  • 手把手教你訓練自己的yolov3
    前面說了一下如果想要訓練一個自己的yolov3目標檢測模型,除了交代的數據處理外,接下來就是根據自己的情況進行參數配置,訓練模型了,
  • 進擊的YOLOv3,目標檢測網絡的巔峰之作 | 內附實景大片
    訓練和檢測都很快論文中做了詳盡的對比。 和前輩們比,YOLO 的速度非常快,比 R-CNN 快 1000 倍,比 Fast R-CNN 快 100 倍。 和同輩們比,YOLOv3-608 檢測準確率比 DSSD 更高,接近 FPN,但是檢測時間卻只用了後面兩者的三分之一不到。
  • 目標檢測 | Yolo1算法原理總結
    文章介紹了yolo算法原理的幾個基本概念1. 什麼是grid cell 如下圖,Yolo算法把圖像劃分成7×7的網格,每個網格就是grid cell。非極大值抑制算法原理若滿足條件的預測框有很多個,我們需要用非極大值抑制算法選擇最優預測框,若兩個矩形框都包含了相同類的物體,且兩個矩形框的重疊度較高,則選擇置信度較高的矩形框,刪除置信度較低的矩形框6.
  • 【從零開始學習YOLOv3】5. 網絡模型的構建
    而且作者也提供了多個cfg文件來進行網絡構建,比如:yolov3.cfg、yolov3-tiny.cfg、yolov3-spp.cfg、csresnext50-panet-spp.cfg文件(提供的yolov3-spp-pan-scale.cfg文件,在代碼級別還沒有提供支持)。
  • 本周優秀開源項目分享:基於yolov3的輕量級人臉檢測、增值稅發票OCR識別 等8大項目
    yolo-face-with-landmark 使用pytroch實現的基於yolov3的輕量級人臉檢測
  • YOLO之外的另一選擇,手機端97FPS的Anchor-Free目標檢測模型NanoDet現已開源~
    Android Demo項目地址(提供訓練代碼到安卓部署一站式解決方案):https://github.com/RangiLyu/nanodet深度學習目標檢測已經發展了許多年,從Two-stage到One-stage,從Anchor-base到Anchor-free,再到今年的用Transformer做目標檢測,各種方法百花齊放,但是在移動端目標檢測算法上,yolo系列和SSD等Anchor-base的模型一直佔據著主導地位。
  • 【模型訓練】目標檢測實現分享四:詳解 YOLOv4 算法實現
    本文是目標檢測類算法實現分享的第四篇,前面已經寫過三篇,感興趣的同學可以查閱:  (1) 《【模型訓練】目標檢測實現分享一:詳解 YOLOv1 算法實現》;  (2) 《【模型訓練】目標檢測實現分享二
  • 1.8M超輕量目標檢測模型NanoDet,比YOLO跑得快,上線兩天Star量超200
    這個項目對單階段檢測模型三大模塊(Head、Neck、Backbone)進行輕量化,得到模型大小僅 1.8m、速度超快的輕量級模型 NanoDet-m。目標檢測一直是計算機視覺領域的一大難題,其目標是找出圖像中的所有感興趣區域,並確定這些區域的位置和類別。目標檢測中的深度學習方法已經發展了很多年,並出現了不同類型的檢測方法。
  • 1.8M 超輕量目標檢測模型 NanoDet,比 YOLO 跑得快,上線兩天 Star 量超 200
    目標檢測一直是計算機視覺領域的一大難題,其目標是找出圖像中的所有感興趣區域,並確定這些區域的位置和類別。目標檢測中的深度學習方法已經發展了很多年,並出現了不同類型的檢測方法。目前,深度學習目標檢測方法主要分為兩大類,分別是兩階段式和單階段式目標檢測算法。兩階段式目標檢測框架首先生成候選區域,然後將其分類成不同的目標類別,代表模型有 R-CNN、Fast R-CNN 等;單階段式目標檢測框架將目標檢測任務視為一個統一的端到端回歸問題,代表模型有 MultiBox、YOLO、SSD 等。這類框架通常結構更簡單,檢測速度也更快。
  • 目標檢測新方式 | class-agnostic檢測器用於目標檢測(附論文下載連結)
    ,然而,由於創建和注釋檢測數據集的難度和成本,訓練過的模型檢測到數量有限的目標類型,未知目標被視為背景內容。目標檢測模型在定位和分類訓練期間顯示目標時表現良好,然而,由於創建和注釋檢測數據集的難度和成本,訓練過的模型檢測到數量有限的目標類型,未知目標被視為背景內容。
  • tensorflow使用object detection實現目標檢測超詳細全流程(視頻+圖像集檢測)
    使用tensorflow object detection進行訓練檢測。參考原始代碼:https://github.com/tensorflow/models/tree/master/research本文以mobilenet-ssd-v2為例進行處理,通過換模型即可實現faster RCNN等的訓練檢測。
  • 原理講解-項目實戰<->Mtcnn+Mobilent實現人臉口罩檢測
    整體實現流程        1.什麼是 Mtcnn        2.什麼是Mobilent        3. 代碼下載和環境設置         4.數據集和模型的訓練一、一般口罩佩戴檢測的兩種方案第一種:直接利用SSD和Yolo這種one-stage目標檢測算法,在檢測到人臉的同時判斷是否佩戴了口罩。