YOLO算法的原理與實現

一、前言

  當咱們談起計算機視覺時,首先想到的就是圖像分類,沒錯,圖像分類是計算機視覺最基本的任務之一,可是在圖像分類的基礎上,還有更復雜和有意思的任務,如目標檢測,物體定位,圖像分割等,見圖1所示。其中目標檢測是一件比較實際的且具備挑戰性的計算機視覺任務,其能夠當作圖像分類與定位的結合,給定一張圖片,目標檢測系統要可以識別出圖片的目標並給出其位置,因爲圖片中目標數是不定的,且要給出目標的較精確位置,目標檢測相比分類任務更復雜。目標檢測的一個實際應用場景就是無人駕駛,若是可以在無人車上裝載一個有效的目標檢測系統,那麼無人車將和人同樣有了眼睛,能夠快速地檢測出前面的行人與車輛,從而做出實時決策。
 

 

   在介紹Yolo 算法以前,首先先介紹一下滑動窗口技術,這對咱們理解Yolo算法是有幫助的。採用滑動窗口的目標檢測算法思路很是簡單,它將檢測問題轉化爲了圖像分類問題。其基本原理就是採用不一樣大小和窗口在整張圖片上以必定的步長進行滑動,而後對這些窗口對應的區域作圖像分類,這樣就能夠實現對整張圖片的檢測了,以下圖3所示,如DPM就是採用這種思路。可是這個方法有致命的缺點,就是你並不知道要檢測的目標大小是什麼規模,因此你要設置不一樣大小的窗口去滑動,並且還要選取合適的步長。可是這樣會產生不少的子區域,而且都要通過分類器去作預測,這須要很大的計算量,因此你的分類器不能太複雜,由於要保證速度。解決思路之一就是減小要分類的子區域,這就是R-CNN的一個改進策略,其採用了selective search方法來找到最有可能包含目標的子區域(Region Proposal),其實能夠當作採用啓發式方法過濾掉不少子區域,這會提高效率。
 
 

二、滑動窗口與CNN

  在介紹Yolo算法以前,首先先介紹一下滑動窗口技術,這對咱們理解Yolo算法是有幫助的。採用滑動窗口的目標檢測算法思路很是簡單,它將檢測問題轉化爲了圖像分類問題。其基本原理就是採用不一樣大小和窗口在整張圖片上以必定的步長進行滑動,而後對這些窗口對應的區域作圖像分類,這樣就能夠實現對整張圖片的檢測了,以下圖3所示,如DPM就是採用這種思路。可是這個方法有致命的缺點,就是你並不知道要檢測的目標大小是什麼規模,因此你要設置不一樣大小的窗口去滑動,並且還要選取合適的步長。可是這樣會產生不少的子區域,而且都要通過分類器去作預測,這須要很大的計算量,因此你的分類器不能太複雜,由於要保證速度。解決思路之一就是減小要分類的子區域,這就是R-CNN的一個改進策略,其採用了selective search方法來找到最有可能包含目標的子區域(Region Proposal),其實能夠當作採用啓發式方法過濾掉不少子區域,這會提高效率。
 
 

  若是你使用的是CNN分類器,那麼滑動窗口是很是耗時的。可是結合卷積運算的特色,咱們可使用CNN實現更高效的滑動窗口方法。這裏要介紹的是一種全卷積的方法,簡單來講就是網絡中用卷積層代替了全鏈接層,如圖4所示。輸入圖片大小是16x16,通過一系列卷積操做,提取了2x2的特徵圖,可是這個2x2的圖上每一個元素都是和原圖是一一對應的,如圖上藍色的格子對應藍色的區域,這不就是至關於在原圖上作大小爲14x14的窗口滑動,且步長爲2,共產生4個字區域。最終輸出的通道數爲4,能夠當作4個類別的預測機率值,這樣一次CNN計算就能夠實現窗口滑動的全部子區域的分類預測。這實際上是overfeat算法的思路。之所能夠CNN能夠實現這樣的效果是由於卷積操做的特性,就是圖片的空間位置信息的不變性,儘管卷積過程當中圖片大小減小,可是位置對應關係仍是保存的。說點題外話,這個思路也被R-CNN借鑑,從而誕生了Fast R-CNN算法。html

 
  上面儘管能夠減小滑動窗口的計算量,可是隻是針對一個固定大小與步長的窗口,這是遠遠不夠的。Yolo算法很好的解決了這個問題,它再也不是窗口滑動了,而是直接將原始圖片分割成互不重合的小方塊,而後經過卷積最後生產這樣大小的特徵圖,基於上面的分析,能夠認爲特徵圖的每一個元素也是對應原始圖片的一個小方塊,而後用每一個元素來能夠預測那些中心點在該小方格內的目標,這就是Yolo算法的樸素思想。下面將詳細介紹Yolo算法的設計理念。
這就是Yolo算法的樸素思想。下面將詳細介紹Yolo算法的設計理念
 

三、設計理念

總體來看,Yolo算法採用一個單獨的CNN模型實現end-to-end的目標檢測,整個系統如圖5所示:首先將輸入圖片resize到448x448,而後送入CNN網絡,最後處理網絡預測結果獲得檢測的目標。相比R-CNN算法,其是一個統一的框架,其速度更快,並且Yolo的訓練過程也是end-to-end的。

 

   具體來講,Yolo的CNN網絡將輸入的圖片分割成S*S網格,而後每一個單元格負責去檢測那些中心點落在該格子內的目標,如圖6所示,能夠看到狗這個目標的中心落在左下角一個單元格內,那麼該單元格負責預測這個狗。每一個單元格會預測B個邊界框(bounding box)以及邊界框的置信度(confidence score)。所謂置信度其實包含兩個方面,一是這個邊界框含有目標的可能性大小,二是這個邊界框的準確度。前者記爲Pr(object),當該邊界框是背景時(即不包含目標),此時Pr(object)=0。而當該邊界框包含目標時,Pr(object)=1。邊界框的準確度能夠用預測框與實際框(ground truth)的IOU(intersection over union,交併比)來表徵,記爲IOU。所以置信度能夠定義爲Pr(object)*IOU。不少人可能將Yolo的置信度當作邊界框是否含有目標的機率,可是其實它是兩個因子的乘積,預測框的準確度也反映在裏面。邊界框的大小與位置能夠用4個值來表徵:(x,y,h,w),其中(x,y)是邊界框的中心座標,而和是邊界框的寬與高。還有一點要注意,中心座標的預測值(x,y)是相對於每一個單元格左上角座標點的偏移值,而且單位是相對於單元格大小的,單元格的座標定義如圖6所示。而邊界框的w和h預測值是相對於整個圖片的寬與高的比例,這樣理論上4個元素的大小應該在[0,1]範圍。這樣,每一個邊界框的預測值實際上包含5個元素:(x,y,w,h,c),其中前4個表徵邊界框的大小與位置,而最後一個值是置信度。算法

 

 

  總結一下,每一個單元格須要預測(B*5+C)個值。若是將輸入圖片劃分爲S*S網格,那麼最終預測值爲S*S*(B*5+C)大小的張量。整個模型的預測值結構以下圖所示。對於PASCALVOC數據,其共有20個類別,若是使用S=7,B=2,那麼最終的預測結果就是7*7*30大小的張量。在下面的網絡結構中咱們會詳細講述每一個單元格的預測值的分佈位置。網絡

 

 

 

四、網絡設計

Yolo採用卷積網絡來提取特徵,而後使用全鏈接層來獲得預測值。網絡結構參考GooLeNet模型,包含24個卷積層和2個全鏈接層,如圖8所示。對於卷積層,主要使用1x1卷積來作channle reduction,而後緊跟3x3卷積。對於卷積層和全鏈接層,採用Leaky ReLU激活函數:max(x,0)。可是最後一層卻採用線性激活函數。除了上面這個結構,文章還提出了一個輕量級版本Fast Yolo,其僅使用9個卷積層,而且卷積層中使用更少的卷積核。
 

 

 

 

 

 

 

五、網絡訓練

在訓練以前,先在ImageNet上進行了預訓練,其預訓練的分類模型採用圖8中前20個卷積層,而後添加一個average-pool層和全鏈接層。預訓練以後,在預訓練獲得的20層卷積層之上加上隨機初始化的4個卷積層和2個全鏈接層。因爲檢測任務通常須要更高清的圖片,因此將網絡的輸入從224x224增長到了448x448。整個網絡的流程以下圖所示:
 

 

 

  另一點時,因爲每一個單元格預測多個邊界框。可是其對應類別只有一個。那麼在訓練時,若是該單元格內確實存在目標,那麼只選擇與ground truth的IOU較大的那個邊界框來負責預測該目標,而其它邊界框認爲不存在目標。這樣設置的一個結果將會使一個單元格對應的邊界框更加專業化,其能夠分別適用不一樣大小,不一樣高寬比的目標,從而提高模型性能。你們可能會想若是一個單元格內存在多個目標怎麼辦,其實這時候Yolo算法就只能選擇其中一個來訓練,這也是Yolo算法的缺點之一。要注意的一點時,對於不存在對應目標的邊界框,其偏差項就是隻有置信度,左標項偏差是無法計算的。而只有當一個單元格內確實存在目標時,才計算分類偏差項,不然該項也是沒法計算的。 
綜上討論,最終的損失函數計算以下:

 

 

 

六、網絡預測

  在說明Yolo算法的預測過程以前,這裏先介紹一下非極大值抑制算法(non maximum suppression, NMS),這個算法不僅僅是針對Yolo算法的,而是全部的檢測算法中都會用到。NMS算法主要解決的是一個目標被屢次檢測的問題,如圖11中人臉檢測,能夠看到人臉被屢次檢測,可是其實咱們但願最後僅僅輸出其中一個較好的預測框,好比對於美女,只想要紅色那個檢測結果。那麼能夠採用NMS算法來實現這樣的效果:首先從全部的檢測框中找到置信度較大的那個框,而後挨個計算其與剩餘框的IOU,若是其值大於必定閾值(重合度太高),那麼就將該框剔除;而後對剩餘的檢測框重複上述過程,直處處理完全部的檢測框。Yolo預測過程也須要用到NMS算法。

 

  下面就來分析Yolo的預測過程,這裏咱們不考慮batch,認爲只是預測一張輸入圖片。根據前面的分析,最終的網絡輸出是7*7*30,可是咱們能夠將其分割成三個部分:類別機率部分爲[7,7,20],置信度部分爲[7,7,2,2],而邊界框部分爲[7,7,2,4](對於這部分不要忘記根據原始圖片計算出其真實值)。而後將前兩項相乘能夠獲得類別置信度值爲[7,7,2,20],這裏總共預測了7*7*2=98邊界框。
 
  全部的準備數據已經獲得了,那麼咱們先說第一種策略來獲得檢測框的結果,我認爲這是最正常與天然的處理。首先,對於每一個預測框根據類別置信度選取置信度較大的那個類別做爲其預測標籤,通過這層處理咱們獲得各個預測框的預測類別及對應的置信度值,其大小都是[7,7,2]。通常狀況下,會設置置信度閾值,就是將置信度小於該閾值的box過濾掉,因此通過這層處理,剩餘的是置信度比較高的預測框。最後再對這些預測框使用NMS算法,最後留下來的就是檢測結果。一個值得注意的點是NMS是對全部預測框一視同仁,仍是區分每一個類別,分別使用NMS。Ng在deeplearning.ai中講應該區分每一個類別分別使用NMS,可是看了不少實現,其實仍是同等對待全部的框,我以爲多是不一樣類別的目標出如今相同位置這種機率很低吧。
 

七、算法性能分析

  這裏看一下Yolo算法在PASCAL VOC 2007數據集上的性能,這裏Yolo與其它檢測算法作了對比,包括DPM,R-CNN,Fast R-CNN以及Faster R-CNN。其對比結果如表1所示。與實時性檢測方法DPM對比,能夠看到Yolo算法能夠在較高的mAP上達到較快的檢測速度,其中Fast Yolo算法比快速DPM還快,並且mAP是遠高於DPM。可是相比Faster R-CNN,Yolo的mAP稍低,可是速度更快。因此。Yolo算法算是在速度與準確度上作了折中。

Yolo在PASCAL VOC 2007上與其餘算法的對比 框架

  如今來總結一下Yolo的優缺點。首先是優勢,Yolo採用一個CNN網絡來實現檢測,是單管道策略,其訓練與預測都是end-to-end,因此Yolo算法比較簡潔且速度快。第二點因爲Yolo是對整張圖片作卷積,因此其在檢測目標有更大的視野,它不容易對背景誤判。其實我以爲全鏈接層也是對這個有貢獻的,由於全鏈接起到了attention的做用。另外,Yolo的泛化能力強,在作遷移時,模型魯棒性高。
 
  最後不得不談一下Yolo的缺點,首先Yolo各個單元格僅僅預測兩個邊界框,並且屬於一個類別。對於小物體,Yolo的表現會不如人意。這方面的改進能夠看SSD,其採用多尺度單元格。也能夠看Faster R-CNN,其採用了anchor boxes。Yolo對於在物體的寬高比方面泛化率低,就是沒法定位不尋常比例的物體。固然Yolo的定位不許確也是很大的問題。
相關文章
相關標籤/搜索