一文看懂YOLO v3

論文地址:https://pjreddie.com/media/files/papers/YOLOv3.pdf
論文:YOLOv3: An Incremental Improvement

YOLO系列的目標檢測算法可以說是目標檢測史上的宏篇鉅作,接下來我們來詳細介紹一下YOLO v3算法內容,v3的算法是在v1和v2的基礎上形成的,所以有必要先回憶: 一文看懂YOLO v2,一文看懂YOLO v2。

網絡結構

從這兒盜了張圖,這張圖很好的總結了YOLOV3的結構,讓我們對YOLO有更加直觀的理解。


DBL:代碼中的Darknetconv2d_BN_Leaky,是yolo_v3的基本組件。就是卷積+BN+Leaky relu。
resn:n代表數字,有res1,res2, … ,res8等等,表示這個res_block裏含有多少個res_unit。不懂resnet請戳這兒
concat:張量拼接。將darknet中間層和後面的某一層的上採樣進行拼接。拼接的操作和殘差層add的操作是不一樣的,拼接會擴充張量的維度,而add只是直接相加不會導致張量維度的改變。

後面我們一起分析網絡一些細節與難懂的地方

backbone:darknet-53

爲了達到更好的分類效果,作者自己設計訓練了darknet-53。作者在ImageNet上實驗發現這個darknet-53,的確很強,相對於ResNet-152和ResNet-101,darknet-53不僅在分類精度上差不多,計算速度還比ResNet-152和ResNet-101強多了,網絡層數也比他們少。


Yolo_v3使用了darknet-53的前面的52層(沒有全連接層),yolo_v3這個網絡是一個全卷積網絡,大量使用殘差的跳層連接,並且爲了降低池化帶來的梯度負面效果,作者直接摒棄了POOLing,用conv的stride來實現降採樣。在這個網絡結構中,使用的是步長爲2的卷積來進行降採樣。

爲了加強算法對小目標檢測的精確度,YOLO v3中採用類似FPN的upsample和融合做法(最後融合了3個scale,其他兩個scale的大小分別是26×26和52×52),在多個scale的feature map上做檢測。

作者在3條預測支路採用的也是全卷積的結構,其中最後一個卷積層的卷積核個數是255,是針對COCO數據集的80類:3*(80+4+1)=255,3表示一個grid cell包含3個bounding box,4表示框的4個座標信息,1表示objectness score。

output

所謂的多尺度就是來自這3條預測之路,y1,y2和y3的深度都是255,邊長的規律是13:26:52。yolo v3設定的是每個網格單元預測3個box,所以每個box需要有(x, y, w, h, confidence)五個基本參數,然後還要有80個類別的概率。所以3×(5 + 80) = 255。這個255就是這麼來的。

下面我們具體看看y1,y2,y3是如何而來的。
網絡中作者進行了三次檢測,分別是在32倍降採樣,16倍降採樣,8倍降採樣時進行檢測,這樣在多尺度的feature map上檢測跟SSD有點像。在網絡中使用up-sample(上採樣)的原因:網絡越深的特徵表達效果越好,比如在進行16倍降採樣檢測,如果直接使用第四次下采樣的特徵來檢測,這樣就使用了淺層特徵,這樣效果一般並不好。如果想使用32倍降採樣後的特徵,但深層特徵的大小太小,因此yolo_v3使用了步長爲2的up-sample(上採樣),把32倍降採樣得到的feature map的大小提升一倍,也就成了16倍降採樣後的維度。同理8倍採樣也是對16倍降採樣的特徵進行步長爲2的上採樣,這樣就可以使用深層特徵進行detection。

作者通過上採樣將深層特徵提取,其維度是與將要融合的特徵層維度相同的(channel不同)。如下圖所示,85層將13×13×256的特徵上採樣得到26×26×256,再將其與61層的特徵拼接起來得到26×26×768。爲了得到channel255,還需要進行一系列的3×3,1×1卷積操作,這樣既可以提高非線性程度增加泛化性能提高網絡精度,又能減少參數提高實時性。52×52×255的特徵也是類似的過程。


從圖中,我們可以看出y1,y2,y3的由來。

Bounding Box

YOLO v3的Bounding Box由YOLOV2又做出了更好的改進。在yolo_v2和yolo_v3中,都採用了對圖像中的object採用k-means聚類。 feature map中的每一個cell都會預測3個邊界框(bounding box) ,每個bounding box都會預測三個東西:(1)每個框的位置(4個值,中心座標tx和ty,,框的高度bh和寬度bw),(2)一個objectness prediction ,(3)N個類別,coco數據集80類,voc20類。

三次檢測,每次對應的感受野不同,32倍降採樣的感受野最大,適合檢測大的目標,所以在輸入爲416×416時,每個cell的三個anchor box爲(116 ,90); (156 ,198); (373 ,326)。16倍適合一般大小的物體,anchor box爲(30,61); (62,45); (59,119)。8倍的感受野最小,適合檢測小目標,因此anchor box爲(10,13); (16,30); (33,23)。所以當輸入爲416×416時,實際總共有(52×52+26×26+13×13)×3=10647個proposal box。

感受一下9種先驗框的尺寸,下圖中藍色框爲聚類得到的先驗框。黃色框式ground truth,紅框是對象中心點所在的網格。


這裏注意bounding box 與anchor box的區別:
Bounding box它輸出的是框的位置(中心座標與寬高),confidence以及N個類別。
anchor box只是一個尺度即只有寬高。

LOSS Function

YOLOv3重要改變之一:No more softmaxing the classes。
YOLO v3現在對圖像中檢測到的對象執行多標籤分類。
早期YOLO,作者曾用softmax獲取類別得分並用最大得分的標籤來表示包含再邊界框內的目標,在YOLOv3中,這種做法被修正。

softmax來分類依賴於這樣一個前提,即分類是相互獨立的,換句話說,如果一個目標屬於一種類別,那麼它就不能屬於另一種。

但是,當我們的數據集中存在人或女人的標籤時,上面所提到的前提就是去了意義。這就是作者爲什麼不用softmax,而用logistic regression來預測每個類別得分並使用一個閾值來對目標進行多標籤預測。比閾值高的類別就是這個邊界框真正的類別。

用簡單一點的語言來說,其實就是對每種類別使用二分類的logistic迴歸,即你要麼是這種類別要麼就不是,然後便利所有類別,得到所有類別的得分,然後選取大於閾值的類別就好了。

logistic迴歸用於對anchor包圍的部分進行一個目標性評分(objectness score),即這塊位置是目標的可能性有多大。這一步是在predict之前進行的,可以去掉不必要anchor,可以減少計算量。

如果模板框不是最佳的即使它超過我們設定的閾值,我們還是不會對它進行predict。
不同於faster R-CNN的是,yolo_v3只會對1個prior進行操作,也就是那個最佳prior。而logistic迴歸就是用來從9個anchor priors中找到objectness score(目標存在可能性得分)最高的那一個。logistic迴歸就是用曲線對prior相對於 objectness score映射關係的線性建模。

xy_loss = object_mask * box_loss_scale * K.binary_crossentropy(raw_true_xy, raw_pred[..., 0:2],
                                                                       from_logits=True)
wh_loss = object_mask * box_loss_scale * 0.5 * K.square(raw_true_wh - raw_pred[..., 2:4])
confidence_loss = object_mask * K.binary_crossentropy(object_mask, raw_pred[..., 4:5], from_logits=True) + \
                          (1 - object_mask) * K.binary_crossentropy(object_mask, raw_pred[..., 4:5],
                                                                    from_logits=True) * ignore_mask
class_loss = object_mask * K.binary_crossentropy(true_class_probs, raw_pred[..., 5:], from_logits=True)

xy_loss = K.sum(xy_loss) / mf
wh_loss = K.sum(wh_loss) / mf
confidence_loss = K.sum(confidence_loss) / mf
class_loss = K.sum(class_loss) / mf
loss += xy_loss + wh_loss + confidence_loss + class_loss

以上是一段keras框架描述的yolo v3 的loss_function代碼。忽略恆定係數不看,可以從上述代碼看出:除了w, h的損失函數依然採用總方誤差之外,其他部分的損失函數用的是二值交叉熵。最後加到一起。那麼這個binary_crossentropy又是個什麼玩意兒呢?就是一個最簡單的交叉熵而已,一般用於二分類,這裏的兩種二分類類別可以理解爲"對和不對"這兩種。

參考文章:
https://towardsdatascience.com/yolo-v3-object-detection-53fb7d3bfe6b
https://blog.csdn.net/yanzi6969/article/details/80505421
https://blog.csdn.net/chandanyan8568/article/details/81089083
https://blog.csdn.net/leviopku/article/details/82660381
https://blog.csdn.net/u014380165/article/details/80202337

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章