你真的讀懂yolo了嗎?
作者: stone,就職于百度,計算機視覺
來源:https://zhuanlan.zhihu.com/p/37850811
yolo v1(以下都稱為yolo)算比較舊的算法了,不過近來想整理一下yolo系列算法,所以先從yolo開始整理。發(fā)現(xiàn)網(wǎng)上關(guān)于yolo的文章基本都是照著原文翻譯,很多背后的原理沒有講清楚,所以本文盡量用最通俗易懂的語言來解釋yolo。如果有理解不對的地方,歡迎指正。
一、yolo思想
廢話不多說,直接開始講yolo算法的思想。首先從最初的目標檢測開始講起。
1. 從目標檢測講起
首先假設(shè)深度學習還沒用于目標檢測,我們還不知道那么多目標檢測算法。

我們先看一下目標檢測要做什么事情。目標檢測就是要找出圖片中物體的bounding box(邊界框),并判定框內(nèi)物體的類別。比如上圖中有一只貓,那我們要將這只貓用一個bounding box框出來(bounding box可以用左上角坐標(x,y)和矩形的寬高(w,h)來表示)。
對于這種任務(wù)我們要怎么做?一個很自然的想法就是,我把圖片喂給深度模型,讓網(wǎng)絡(luò)學習吐出bounding box的xywh四個值以及圖片的類別就好了。這么做貌似是可以的,但考慮這么一種情況:如果圖片上除了一只貓之外還有一只狗,甚至更多的物體,我們都想把它們框出來,那么這時候網(wǎng)絡(luò)就不僅僅要輸出貓的預(yù)測,還有輸出其他物體的預(yù)測。這個時候我們發(fā)現(xiàn),模型的輸出的維度是沒辦法固定的,圖片中存在的物體越多,模型輸出的維度就越大。所以這種思路行不通。
2. yolo的思想
既然模型的輸出需要固定維度的,那么我們能不能設(shè)計一個固定維度大小的輸出,并且輸出的維度足夠大,足以囊括圖像中的所有物體呢?答案是可以的!yolo就是這么做的。yolo固定維度的辦法是把模型的輸出劃分成網(wǎng)格形狀,每個網(wǎng)格中的cell(格子)都可以輸出物體的類別和bounding box的坐標,如下圖所示(yolo實際上還可以預(yù)測多個bounding box的類別和confidence,這里只講思想,所以可以先忽略這個,后面會詳細講到)。

但問題的關(guān)鍵是,我們怎么知道cell需要預(yù)測圖片中的哪個物體呢?這個其實取決于你怎么去設(shè)置模型的訓練目標,說白一點就是,你要教它去預(yù)測哪個物體。具體來說,yolo是這么做的:
將輸入圖像按照模型的輸出網(wǎng)格(比如7x7大小)進行劃分,劃分之后就有很多小cell了。我們再看圖片中物體的中心是落在哪個cell里面,落在哪個cell哪個cell就負責預(yù)測這個物體。比如下圖中,狗的中心落在了紅色cell內(nèi),則這個cell負責預(yù)測狗。這么說可能不太容易理解,下面進行更具體的介紹。

實際上,“物體落在哪個cell,哪個cell就負責預(yù)測這個物體” 要分兩個階段來看,包括訓練和測試。
訓練階段。在訓練階段,如果物體中心落在這個cell,那么就給這個cell打上這個物體的label(包括xywh和類別)。也就是說我們是通過這種方式來設(shè)置訓練的label的。換言之,我們在訓練階段,就教會cell要預(yù)測圖像中的哪個物體。
測試階段。因為你在訓練階段已經(jīng)教會了cell去預(yù)測中心落在該cell中的物體,那么cell自然也會這么做。
以上就是yolo最核心的思想。不過原文都是按照測試階段來解說的,不容易讓人理解。其實,知道訓練階段的意義更重要,因為訓練階段你告訴網(wǎng)絡(luò)去預(yù)測什么,然后測試階段才能按照你訓練階段教它的去做,如果你只知道測試階段網(wǎng)絡(luò)輸出的意義,你就很可能會問:憑什么物體的中心落在這個cell它就負責預(yù)測這個物體?
二、模型
講完了思想,我們來講具體的流程。
1.模型架構(gòu)
首先講網(wǎng)絡(luò)架構(gòu)。網(wǎng)絡(luò)架構(gòu)沒什么好講的,直接看圖就好了。

從圖中可以看到,yolo網(wǎng)絡(luò)的輸出的網(wǎng)格是7x7大小的,另外,輸出的channel數(shù)目為30。一個cell內(nèi),前20個元素是類別概率值,然后2個元素是邊界框confidence,最后8個元素是邊界框的 (x, y,w,h) 。

也就是說,每個cell有兩個predictor,每個predictor分別預(yù)測一個bounding box的xywh和相應(yīng)的confidence。但分類部分的預(yù)測卻是共享的。正因為這個,同個cell是沒辦法預(yù)測多個目標的。
現(xiàn)在考慮兩個問題:
假設(shè)類別預(yù)測不是共享的,cell中兩個predictor都有各自的類別預(yù)測,這樣能否在一個cell中預(yù)測兩個目標?
為什么要預(yù)測兩個bounding box?
對于第一個問題,答案是否定的。如果一個cell要預(yù)測兩個目標,那么這兩個predictor要怎么分工預(yù)測這兩個目標?誰負責誰?不知道,所以沒辦法預(yù)測。而像faster rcnn這類算法,可以根據(jù)anchor與ground truth的IOU大小來安排anchor負責預(yù)測哪個物體,所以后來yolo2也采用了anchor思想,同個cell才能預(yù)測多個目標。
對于第二個問題,既然我們一個cell只能預(yù)測一個目標,為什么還要預(yù)測兩個bounding box(或者更多)?這個還是要從訓練階段怎么給兩個predictor安排訓練目標來說。在訓練的時候會在線地計算每個predictor預(yù)測的bounding box和ground truth的IOU,計算出來的IOU大的那個predictor,就會負責預(yù)測這個物體,另外一個則不預(yù)測。這么做有什么好處?我的理解是,這樣做的話,實際上有兩個predictor來一起進行預(yù)測,然后網(wǎng)絡(luò)會在線選擇預(yù)測得好的那個predictor(也就是IOU大)來進行預(yù)測。通俗一點說,就是我找一堆人來并行地干一件事,然后我選干的最好的那個。
2.模型輸出的意義
Confidence預(yù)測
首先看cell預(yù)測的bounding box中condifence這個維度。confidence表示:cell預(yù)測的bounding box包含一個物體的置信度有多高并且該bounding box預(yù)測準確度有多大,用公式表示為:
。這個也要分兩個階段來考慮。
對于訓練階段來說,我們要給每個bounding box的confidence打label,那么這個label怎么算? 其實很簡單,如果一個物體中心沒有落在cell之內(nèi),那么每個bounding box的
,IOU就沒有算的必要了,因為
肯定等于0,因此confidence的label就直接設(shè)置為0。如果物體的中心落在了這個cell之內(nèi),這個時候
,因此confidence變成了
。注意這個IOU是在訓練過程中不斷計算出來的,網(wǎng)絡(luò)在訓練過程中預(yù)測的bounding box每次都不一樣,所以和ground truth計算出來的IOU每次也會不一樣。對于預(yù)測階段,網(wǎng)絡(luò)只輸出一個confidence值,它實際上隱含地包含了
。
對于第2點,有人私信問說,在測試階段,輸出的confidece怎么算?還是通過計算嗎?可是如果這樣的話,測試階段根本沒有g(shù)round truth,那怎么計算IOU?
實際上,在測試階段,網(wǎng)絡(luò)只是輸出了confidece這個值,但它已經(jīng)包含了,并不需要分別計算Pr(object)和IOU(也沒辦法算)。為什么?因為你在訓練階段你給confidence打label的時候,給的是
這個值,你在測試的時候,網(wǎng)絡(luò)吐出來的也就是這個值。
Bounding box預(yù)測
bounding box的預(yù)測包括xywh四個值。xy表示bounding box的中心相對于cell左上角坐標偏移,寬高則是相對于整張圖片的寬高進行歸一化的。偏移的計算方法如下圖所示。

xywh為什么要這么表示呢?實際上經(jīng)過這么表示之后,xywh都歸一化了,它們的值都是在0-1之間。我們通常做回歸問題的時候都會將輸出進行歸一化,否則可能導致各個輸出維度的取值范圍差別很大,進而導致訓練的時候,網(wǎng)絡(luò)更關(guān)注數(shù)值大的維度。因為數(shù)值大的維度,算loss相應(yīng)會比較大,為了讓這個loss減小,那么網(wǎng)絡(luò)就會盡量學習讓這個維度loss變小,最終導致區(qū)別對待。
類別預(yù)測
除此之外,還有一個物體類別,物體類別是一個條件概率
。這個怎么理解?也可以分兩個階段來看。
對于訓練階段,也就是打label階段,怎么打label呢?對于一個cell,如果物體的中心落在了這個cell,那么我們給它打上這個物體的類別label,并設(shè)置概率為1。換句話說,這個概率是存在一個條件的,這個條件就是cell存在物體。
對于測試階段來說,網(wǎng)絡(luò)直接輸出
,就已經(jīng)可以代表有物體存在的條件下類別概率。但是在測試階段,作者還把這個概率乘上了confidence。
論文中的公式是這樣的:

也就是說我們預(yù)測的條件概率還要乘以confidence。為什么這么做呢?舉個例子,對于某個cell來說,在預(yù)測階段,即使這個cell不存在物體(即confidence的值為0),也存在一種可能:輸出的條件概率
,但將confidence和
乘起來就變成0了。這個是很合理的,因為你得確保cell中有物體(即confidence大),你算類別概率才有意義。
三、訓練
最后要講的是訓練階段的loss。

關(guān)于loss,需要特別注意的是需要計算loss的部分。并不是網(wǎng)絡(luò)的輸出都算loss,具體地說:
有物體中心落入的cell,需要計算分類loss,兩個predictor都要計算confidence loss,預(yù)測的bounding box與ground truth IOU比較大的那個predictor需要計算xywh loss。
特別注意:沒有物體中心落入的cell,只需要計算confidence loss。
另外,我們發(fā)現(xiàn)每一項loss的計算都是L2 loss,即使是分類問題也是。所以說yolo是把分類問題轉(zhuǎn)為了回歸問題。
——The End——
求分享 求點贊 求在看!??!

計算嗎?可是如果這樣的話,測試階段根本沒有g(shù)round truth,那怎么計算IOU?
,并不需要分別計算Pr(object)和IOU(也沒辦法算)。為什么?因為你在訓練階段你給confidence打label的時候,給的是
這個值,你在測試的時候,網(wǎng)絡(luò)吐出來的也就是這個值。