title: YOLOv3
date: 2021-07-08 16:58:38
tags: no
YOLOv3的網絡結構圖

YOLOv3采用了Darknet53的backbone(采用了Resnet的殘差結構),其輸出為3張不同尺度的特征圖(采用了SSD的思想)。特征圖越小,每個grid cell對應的感受野越大,對應大目标的檢測。
拿上圖中右下角 ( 255 ∗ 13 ∗ 13 ) (2551313) (255∗13∗13)的特征圖為例, 13 ∗ 13 是特征圖大小,255可以拆分為 3 ∗ ( 4 + 1 + 80 ) ,3表示一個grid cell對應3個anchor,4表示anchor的中心坐标xy和寬高wh,1表示該anchor是否包含目标的置信度,80表示coco資料集的80個類别。
anchor的選擇與yolov2一樣,采用了kmeans的思想。不同的是這裡的K值為9。聚類後,尺寸最大的三個框配置設定給特征圖最小的(感受野大),用來檢測大目标;最小的3個框分給特征圖最大的(感受野小),用以檢測小目标;剩下的3個框分給中間尺寸的特征圖。
是以,yolov3的輸出次元是 B a t c h ∗ 3 ∗ ( 4 + 1 + 80 ) ∗ ( 13 ∗ 13 + 26 ∗ 26 + 52 ∗ 52 ) 。
YOLOv3損失函數的全貌
先了解anchor、置信度和類别機率
1.anchor box
1.1了解
anchor box其實就是從訓練集的所有ground truth box中統計(使用k-means)出來的在訓練集中最經常出現的幾個box形狀和尺寸。(有助于模型快速收斂)
anchor box其實就是對預測的對象範圍進行限制,并加入了尺寸先驗經驗,進而實作多尺度學習的目的。
-
怎麼在實際的模型中加入anchor box的先驗經驗呢?
最終負責預測grid cell中對象的box的最小單元是bounding box,那我們可以讓一個grid cell輸出(預測)多個bounding box,然後每個bounding box負責預測不同的形狀不就行了?比如前面例子中的3個不同形狀的anchor box,我們的一個grid cell會輸出3個參數相同的bounding box,第一個bounding box負責預測的形狀與anchor box 1類似的box,其他兩個bounding box依次類推。作者在YOLOv3中取消了v2之前每個grid cell隻負責預測一個對象的限制,也就是說grid cell中的三個bounding box都可以預測對象,當然他們應該對應不同的ground truth。那麼如何在訓練中确定哪個bounding box負責某個ground truth呢?方法是求出每個grid cell中每個anchor box與ground truth box的IOU(交并比),IOU最大的anchor box對應的bounding box就負責預測該ground truth,也就是對應的對象,後面還會提到負責預測的問題。
-
怎麼告訴模型第一個bounding box負責預測的形狀與anchor box 1類似,第二個bounding box負責預測的形狀與anchor box 2類似?
YOLO的做法是不讓bounding box直接預測實際box的寬和高(w,h),而是将預測的寬和高分别與anchor box的寬和高綁定,這樣不管一開始bounding box輸出的(w,h)是怎樣的,經過轉化後都是與anchor box的寬和高相關,這樣經過很多次懲罰訓練後,每個bounding box就知道自己該負責怎樣形狀的box預測了。這個綁定的關系是什麼?就涉及到了anchor box的計算。
1.2計算
前提需要知道,
c_x和c_y的坐标是(0,0) (0,1),(0,2),(0,3)…(0,13),(1,0),(1,1),(1,2),(1,3)…(1,13)等等
bouding box的輸出應當為:t_x和t_y和t_w和t_h
而真實的預測box應當是:b_x和b_y和b_w和b_h
剛剛說的綁定關系就是
其中,a_w和a_h為anchor box的寬和高,
t_w和t_h為bounding box直接預測出的寬和高,
b_w和b_h為轉換後預測的實際寬和高,
這裡的綁定隻和w和h有關,與x,y無關,但是和grid_cell的歸屬有關
既然提到了最終預測的寬和高公式,那我們也就直接帶出最終預測輸出的box中心坐标(bx,by)的計算公式:
前面提到過box中心坐标總是落在相應的grid cell中的,是以bounding box直接預測出的tx和ty也是相對grid cell來說的,要想轉換成最終輸出的絕對坐标,需要下面的轉換公式:
σ符号是sigmoid
p_w實際就是上面的a_w(anchor_w)
-
訓練
關于box參數的轉換還有一點值得一提,作者在訓練中并不是将t_x,t_y,t_w,t_h轉換為b_x,b_y,b_w,b_h後與ground truth box的對應參數求誤差,而是使用上述公式的逆運算将ground truth box的參數轉換為與t_x,t_y,t_w,t_h對應的資料進行誤差運算
下圖為對應的資料表達
2.置信度(confidence)
我懶了,一個公式就表明吧
3.對象條件類别機率(conditional class probabilities)
對象條件類别機率是一組機率的數組,數組的長度為目前模型檢測的類别種類數量,它的意義是當bounding box認為目前box中有對象時,要檢測的所有類别中每種類别的機率.
其實這個和分類模型最後使用softmax函數輸出的一組類别機率是類似的,隻是二者存在兩點不同:
- YOLO的對象類别機率中沒有background一項,也不需要,因為對background的預測已經交給置信度了,是以它的輸出是有條件的,那就是在置信度表示目前box有對象的前提下,是以條件機率的數學形式為Pr(classi∣Object);
- 分類模型中最後輸出之前使用softmax求出每個類别的機率,也就是說各個類别之間是互斥的,而YOLOv3算法的每個類别機率是單獨用邏輯回歸函數(sigmoid函數)計算得出了,是以每個類别不必是互斥的,也就是說一個對象可以被預測出多個類别。這個想法其實是有一些YOLO9000的意思的,因為YOLOv3已經有9000類似的功能,不同隻是不能像9000一樣,同時使用分類資料集和對象檢測資料集,且類别之間的詞性是有從屬關系的。
剖析損失函數
根據pytorch的代碼,Yolov3的損失函數主要包括3個部分:
- 對于正例,bounding box和ground true之間的位置坐标(x,y)和大小(w,h)的差異,采用MSE損失函數 『對應損失函數圖中的1,2兩行』
- 對于正例和負例,計算置信度和真實之間的交叉熵 『對應損失函數圖中的3,4兩行』
- 對于正例,計算80個類别次元與target的one-hot向量間的交叉熵損失 『對應損失函數圖中的第5行』
參數I_ij^obj:
表示第i個grid_cell的第j個anchor box負責檢測這個obj,如果負責則值 == 1,否則==0。
參數I_ij^noobj:
表示第i個grid_cell的第j個anchor box不負責檢測這個obj,如果不負責則值 == 1,否則==0。
負責的含義指:那第 i i i個網格的 B B B個anchor box中與該對象的ground truth box的IOU在所有的anchor box(與一個grid cell中所有bounding box對應,COCO資料集中是9個)與ground truth box的IOU中最大,那它就負責預測這個對象,因為這個形狀、尺寸最符合目前這個對象,此時就算負責檢測這個obj但是代碼裡,隻有max IOU才是正樣本,而小于門檻值IOU的則屬于負樣本
參數置信度C_i^j
訓練中,hat_C_ij表示真實值,hat_C_ij的取值是由grid cell的bounding box有沒有負責預測某個對象決定的。如果負責,那麼值 == 1,否則==0.
如何确定某個grid cell的bounding box是否負責預測該grid cell中的對象:前面在說明anchor box的時候提到每個bounding box負責預測的形狀是依據與其對應的anchor box相關的,那這個anchor box與該對象的ground truth box的IOU在所有的anchor box(與一個grid cell中所有bounding box對應,COCO資料集中是9個)與ground truth box的IOU中最大,那它就負責預測這個對象,因為這個形狀、尺寸最符合目前這個對象,這時hat_C_i^j=1
(其實我在想,為什麼要加入負樣本??)
(因為這個anchor box不負責目标,那麼這個anchor box産生的bounding box的坐标,寬高,分類都不重要,也就不需要計算坐标,寬高,分類的損失函數,但是置信度仍然重要,因為置信度還可以表示這個anchor box産生的bounding box中并不包含對象,是以仍然需要計算置信度損失函數的。)
(沒懂)
-
中心坐标誤差
實際上,網絡輸出的應當是 t_x 和 t_y ,然後通過 σ ( t x ) 和 σ ( t y ) ,再乘以步長,就映射到了 416 ∗ 416 大小的圖上的目标了,是以在計算誤差的時候,其實也是用的這一項 σ ( t x ) ∗ s t r i d e \和 σ ( t y ) ∗ s t r i d e 和真實目标經過resize到 416 ∗ 416 上的目标的大小,去計算誤差。
整個這一項表示的是:當第 i 個網格的第 j 個anchor box負責某一個真實目标時,那麼這個anchor box所産生的bounding box就應該去和真實目标的box去比較,計算得到中心坐标誤差。
『實際上我們産生一個疑問,sigmoid後再乘stride會不會有點奇怪,sigmoid不是線性的呀』
-
置信度誤差
損失函數分為兩部分:有物體,沒有物體,其中沒有物體損失部分還增加了權重系數。添權重重系數的原因是,對于一幅圖像,一般而言大部分内容是不包含待檢測物體的,這樣會導緻沒有物體的計算部分貢獻會大于有物體的計算部分,這會導緻網絡傾向于預測單元格不含有物體。是以,我們要減少沒有物體計算部分的貢獻權重,比如取值為:0.5。
另外,這裡有個例外,當某個bounding box不負責對應grid cell中ground truth box的預測,但是又與該ground truth box的IOU大于設定的門檻值時(論文中是0.5,darknet中針對COCO資料集使用的是0.7),忽略該bounding box所有輸出的對loss的誤差貢獻,包括置信度誤差。其他情況(負責某個對象即IOU最大的,不負責對象即IOU不是最大,而且IOU<0.5)要計算置信度誤差。
(kao,我對代碼的了解是正确的,好開心)
-
分類誤差
交叉熵,暫時沒什麼好說的
-----時間7.8晚上,估計跑完代碼後還要補充。。。。