2. 詳細結構
DarkNet53
左半邊是darknet53,比起yolov2的darknet19加入了許多convolution layers和residual block,residual block是為了效仿ResNet在網路太深的時候難以學習時,跳過該層layer
Detection Input
抓取darknet53其中三層輸出來做detection,大小分別是52x52、26x26、13x13。所以每丟入一張 圖片到網路中,detection model將會針對這三種尺寸算出三個loss。
多尺度偵測
52x52是其中最大的feature map,解析度最高,能夠偵測到較小的物件,13x13是最小的feature map,解析度最低,能夠偵測較大的物體。
抓取darknet53其中三層輸出來做detection,大小分別是52x52、26x26、13x13。
所以每丟入一張 圖片到網路中,detection model將會針對這三種尺寸算出三個loss。
52x52是其中最大的feature map,能夠偵測到較小的物件,13x13是最小的feature map,能夠偵測較大的物體。
尺度融合
小feature map透過upsampling變成大feature map,並且跟大feature進行相加,把深層特徵跟淺層特徵融合,讓dection model一次能夠學到高維度和低維度的資訊。
3. 物件偵測
Anchor Box
直觀上偵測物件,會想用一個Boundingbox(Bbox)在一整張圖片上滑動,然後查看滑到的位子上有沒有物件,但這樣圖片上會有太多Bbox需要計算,而且大部分的Bbox重複的區域太多,容易發生很多Bbox框到同一個物件,或是大部分的Bbox都框不到物件的狀況。
Anchor Box的概念,是把圖片分成很多個Grid,每個Grid內生成固定數量的Bbox(以下以anchor稱呼),此時我們要做的事情,就是找到這些anchor中是否框到物件,並且依據物件的位子和大小更新這些現有anchor的位子和大小去符合物件就可以了。
在yolov3中,丟入的那個圖片大小分別為52 x 52、26 x 26以及13 x 13,並且設定每個grid中有3個anchor。由於尺度不同,所以設定的初始anchor大小也不同。
圖片原始輸入大小為416 x 416,在偵測時會把它變成以下三種尺度
13 x 13 (stride 32) 偵測大物件
在這個狀態下長寬從416變成13,縮小了32倍,所以GroundTruth的座標也會同步縮小32倍。可以想像成一個13 x 13的框框,在圖片上stride 32的結果。在原圖的anchor大小為(116 x 90)(156 x 198)(373 x 326),這些大小也要分別除以32,才有辦法放到13 x 13的feature map中。
26 x 26 (stride 16) 偵測中物件
在這個狀態下長寬從416變成26,縮小了16倍,所以GroundTruth的座標也會同步縮小16倍。可以想像成一個26 x 26的框框,在圖片上stride 16的結果。在原圖的anchor大小為(30 x 61)(62 x 45)(59 x 119),這些大小也要分別除以16,才有辦法放到26 x 26的feature map中。
52 x 52 (stride 8) 偵測小物件
在這個狀態下長寬從416變成52,縮小了8倍,所以GroundTruth的座標也會同步縮小8倍。可以想像成一個52 x 52的框框,在圖片上stride 8的結果。在原圖的anchor大小為(10 x 13)(16 x 30)(30 x 61),這些大小也要分別除以8,才有辦法放到52 x 52的feature map中。
dection model 輸出
下圖以13 x 13為例 :
- tx 預測中心點偏移量
- ty預測中心點偏移量
- tw預測寬度
- th預測高度,
- Po是否為物件
- P1~Pc屬於哪一個物件的信心程度(80種物件)
channel數為[5(tx、ty、tw、th、Po) + 80(80種物件)] x 3(3個anchor) = 255
- 大物件偵測tensor : 13 x 13 x 255
- 中物件偵測tensor : 26 x 26 x 255
- 小物件偵測tensor : 52 x 52 x 255 (解析度最大)
tx、ty、tw、th代表的意思
我們擁有的4個參數tx、ty、tw、th到底代表甚麼呢?
假設中心點座標為(1.3, 1.4),此時
- Cx = 1, Cy = 1 (左上角那個點的座標為1 , 1)
- sigmiod(tx) = 0.3, sigmiod(ty) = 0.4
- tw = log(Gw/Pw), 這裡的Pw是指預測出來的anchor應該要變多寬,與下圖Pw不是同一個,Gw代表GroundTruth的寬度W
- th = log(Gh/Ph), 這裡的Ph是指預測出來的anchor應該要變多高,與下圖Ph不是同一個,Gh代表GroundTruth的寬度h
- 圖中的Pw和Ph為anchor的框和高,要把他們調整的跟藍色框一樣大小
把tx和ty都取sigmoid是希望中心的變動不會跑出這個grid之外,sigmoid把值壓縮在0到1之間。
雖然論文裡面說tw是預測出來的寬度,但我們也可以說他其實是預測出Pw,接著跟groundtruth計算(Gw/Pw)後取log之後的結果也可以。取log是因為在訓練時會比較穩定,所以在還原真實寬度時,要把它變成e的次方還原回來。th也是相同道理。
計算anchor的Loss
在實際上,我們要想的問題是 :
如何把anchor更新到groundtruth的位置上
Gw、Gh為groundtruth的寬和高,Aw、Ah為anchor現在的寬和高
- tw^(tw的groundtruth) = log(Gw/Aw), 意思是anchor的寬度真正要被放大多少
- tw = log(Gw/Pw), 模型預測出來是Pw,所以他預測要放大Gw/Pw
- th^(th的groundtruth) = log(Gh/Ah), 意思是anchor的高度真正要被放大多少
- th = log(Gh/Ph), 模型預測出Ph,所以他預測要放大Gh/Ph
- 在W和H的Loss可以記成(tw-tw^)² + (th-th^)²
至於中心點座標比較麻煩,以上圖為例
- tx^ 不知道等於多少,但是我們知道sigmoid(tx^)是0.3,所以他groundtruth是用經過sigmoid的結果來看的,所以tx^=0.3
- tx = sigmoid(tx),把預測的結果tx丟到sigmiod裡面
- ty^ 不知道等於多少,但是我們知道sigmoid(ty^)是0.3,所以他groundtruth是用經過sigmoid的結果來看的,所以ty^= 0.3
- ty = sigmoid(ty),把預測的結果ty丟到sigmiod裡面
- X和Y偏移量的Loss可以記為 (tx^-sigmoid(tx))² -(ty^-sigmoid(ty))²
總結anchor座標的Loss :
(tw-tw^)² + (th-th^)² + (tx^-sigmoid(tx))² + (ty^-sigmoid(ty))²
Yolov3其他部分這裡就不講了,NMS那些其他人都講得很清楚,只有上面這些部分比較少人討論到。