1. 程式人生 > >YOLO(You Only Look Once)--只需瞄一眼

YOLO(You Only Look Once)--只需瞄一眼

實習期間,想實現行人檢測任務,要求速度上比較快,因為要放在android端跑,因此選擇了YOLO。YOLO是一種基於端到端的檢測演算法,其特點就是快同時準確率還差強人意。
傳統的目標檢測方法基本都是基於滑窗的方式,RCNN系列也可以歸為滑窗的一種。而YOLO是一種採用全圖資訊來進行檢測的演算法,相比於Fast RCNN,YOLO的背景預測錯誤率低一半,但YOLO對小畫素的目標不敏感。
總結一下:

  1. 非常快。YOLO預測流程簡單,速度很快。基礎版在Titan X上可以達到45幀/s,快速版可以達到145幀/s,在無GPU的虛擬機器中檢測一張圖需要1.5s左右,需要速度快,但是對無GPU的Android端還是不夠。
  2. YOLO無需滑窗,無需候選窗,YOLO在訓練和預測過程中可以利用全圖資訊。Fast RCNN因檢測中無法看到全域性資訊,會出現錯誤的將背景中的斑塊檢測為目標的情況。
  3. YOLO可以學習到目標的概括資訊,具有一定普適性。採用自然圖片訓練YOLO,然後選擇藝術圖片來預測,YOLO的比DPM(Deformable Parts Models)和RCNN的準確率高得多。
  4. YOLO對相互靠近的物體,還有很小群體的檢測效果不好。這是因為一個格子中只能預測兩個框,並且屬於一類。而且,在預測時,同一類物體以不同長寬比出現時,YOLO的效果不好。在大小物體定位的處理上效果也不好。

1、大體流程
YOLO就是利用整張圖作為輸入,然後直接輸出迴歸bounding box的位置和類別。
這裡寫圖片描述


YOLO先將圖片分為個這裡寫圖片描述格子,如果一個目標的中心落在某個格子中,這個格子就負責檢測該目標。每個格子中要預測B個Bounding Box,且每個Bounding Box出了要回歸自身的位置(這裡寫圖片描述)之外,還要附帶預測一個condfidence值(置信值)。這個置信值代表了所預測的Bounding Box中包含目標的置信度和位置(這裡寫圖片描述)的準確度兩重資訊。其值的計算如下式:
這裡寫圖片描述
如果這個格子中有Object落在其中,則這裡寫圖片描述取1,否則取0。這裡寫圖片描述表示預測的Bounding Box和真實的Bounding Box之間的IOU值。

每個Bounding Box包含位置資訊(這裡寫圖片描述)和置信值(condfidence)5個值,同時每個格子還要預測出一個概率值C(如資料集為20類,則C的個數為20),代表這個格子包含某一個目標的概率,每一個格子只預測一類概率。在測試時,每個Bounding Box通過類別概率和Bounding Box的置信值相乘來得到特定類別的置信分數,如下式。
這裡寫圖片描述


則輸入一張圖,一共的這裡寫圖片描述格子,每個格子要預測B個Bounding Box,每個Bounding Box包含5個值,同時每個格子還要預測C個類別概率,因此輸出就是這裡寫圖片描述個tensor。(注:C是針對每個格子的,而condfidence是針對每個Bounding Box)。
舉例:在PASCAL VOC中,影象輸入為這裡寫圖片描述,取這裡寫圖片描述。則輸出的就是這裡寫圖片描述的tensor。

這裡寫圖片描述
2、具體細節
上述例子中,網路輸出為這裡寫圖片描述,即每個格子輸出30個tensor(2個Bounding Box一共8個位置值,2個置信值,還有20維的類別)。其中位置值(這裡寫圖片描述)中,這裡寫圖片描述代表與格子相關的Bounding Box的中心,在訓練時歸一化到0-1;這裡寫圖片描述表示Bounding Box的寬和高,在訓練時用影象的寬和高歸一化到0-1。
在實現時最重要的是怎樣設計損失函式,讓這個三方面得到很好的平衡。作者簡單粗暴的全部採用sum-squared error loss來做這件事。但是這種做法存在幾個問題:
一、8維的位置誤差和20維的分類誤差同等重要顯然不合理。
二、如果某個網格中沒有object,那個這個網格的置信值就為0,相對於較少有object的網格,這種做法太過暴力,這會導致網路不穩定甚至發散。
解決方法:
一、更重視8維的位置座標,在位置座標損失前面賦予更大的loss wights,記為這裡寫圖片描述。在PASCAL VOC訓練中取5.
二、對不包含object的Bounding Box的置信值的誤差,賦予小的loss wights,記為這裡寫圖片描述。在PASCAL VOC訓練中取0.5。
三、包含object的Bounding Box的置信值的誤差和類別的誤差,其loss wights正常取1。

對不同大小的box預測中,相比於大box預測偏一點,小box預測偏一點肯定更不能被忍受的。而sum-square error loss中對同樣的偏移loss是一樣。
為了緩和這個問題,作者用了一個比較取巧的辦法,就是將box的width和height取平方根代替原本的height和width。這個參考下面的圖很容易理解,小box的橫軸值較小,發生偏移時,反應到y軸上相比大box要大。
這裡寫圖片描述

一個格子要預測多個Bounding Box,希望的是每個Bounding Box專門負責預測某個object。具體就是當前預測的Bounding Box與ground truth box中哪個IoU大,就負責哪個。這種做法稱作box predictor的specialization。

整個loss如下:
這裡寫圖片描述

1、損失函式中,只有當Bounding Box中有object時才會對分類誤差進行懲罰。
2、只有當某個box predictor對某個ground truth box負責的時候,才會對box的coordinate error進行懲罰,而對哪個ground truth box負責就看其預測值和ground truth box的IoU是不是在那個cell的所有box中最大。

3、實現
實現的code主要是基於https://pjreddie.com/darknet/yolo/
A、首先下載code編譯
這裡寫圖片描述
B、下載網站提供訓練好的模型weights
這裡寫圖片描述
C、執行預測
這裡寫圖片描述
D、得到結果
這裡寫圖片描述

預測很簡單,本人也做了預測,在cpu上單張圖需要1.5s左右。網頁上也提供了訓練的步驟,需要下載製作好的資料集;若需要解決個人問題,則需要自己標定圖片,製作資料集。
接下來本人會自己製作資料來試驗一下,並簡單閱讀一下原始碼。