本文結構如下: yolo v1基本思路、網絡結構、網絡訓練、網絡預測
一、基本思路
yolo v1 是one stage的目標檢測算法,將一張圖片分爲個網格,每個網格負責預測中心點落在此網格內的目標。每個網格會預測個bounding box,個類別概率值。
一張圖片的預測結果有個值。
在PASCAL VOC 數據集上評估模型,,最終得到7×7×30的tensor。
如下圖所示:狗的中心在紅色網格內,由該網格來負責預測這隻狗。
每個的大小和位置可以通過四個值來表示,其中的值是相對於每個網格的,的值是想對於整張圖片的。
中 的取值爲0或者1.
若目標的中心在網格內,則 的取值爲1;
若目標的中心不在網格內,則 的取值爲0;
注意: 必須是目標的中心在網格內,若僅僅只是目標的一部分在網格內, 的取值仍然爲0。
二、網絡結構
整個網絡先進行特徵提取,再進行分類和迴歸。
yolo網絡由24層卷積+2層全連接層組成。使用1×1卷積可以降維,從而較少網絡的參數和計算量。使用PASCAL VOC 數據集來評估模型,所以網絡的最後輸出爲7×7×30=1470。
最後一層使用線性激活函數,其它層均使用leaky Relu激活函數。
三、網絡訓練
網絡的訓練分爲2部分。
(1)先預訓練一個分類網絡,使用上述網絡的前20個卷積層+average-pool+全連接層在ImageNet進行訓練,網絡輸入爲(224×224×3)。
(2)訓練完成後,再訓練檢測網絡,在預訓練網絡的基礎上+4層卷積層+2層全連接層,將網絡的輸入變爲(448×448×3)。這部分增加4層卷積層是爲了網絡的性能更好。
網絡輸出:
bbox->
爲什麼將 ?
實際上較小的邊界框的座標誤差應該要比較大的邊界框要更敏感。爲了保證這一點,將網絡的邊界框的寬與高預測改爲對其平方根的預測
loss函數
一個網格中會預測多個bbox,在訓練時,只選擇IOU最大的那個bbox來負責預測該目標,其他bbox的值被設爲0。
意爲:第個網格內存在目標,且該目標由此網格內的第個bbox來負責預測。
不同的部分採取不同的權重,其中, ; 因爲大部分網格中沒有目標,所以的值設置的小一些,
因大部分網格中沒有目標,所以,上式中1,2,3,5行的結果大部分爲0,4行不爲0。
四、網絡預測
第三步詳細過程如下:
對於98個boxes,首先將小於置信度閾值的值歸0,然後分類別地對類別置信度值採用NMS。
non_max_suppression
一個目標可能有多個預測框,通過NMS可以去除多餘的預測框,確保一個目標只有一個預測框。NMS是通過類別置信度來篩選的。
計算公式如下:
其中, 爲bbox置信度 ;爲類別概率。
原理: 首先從所有的預測框中找到置信度最大的那個bbox,然後挨個計算其與剩餘bbox的IOU,如果其值大於一定閾值(重合度過高),那麼就將該剩餘bbox剔除;然後對剩餘的預測框重複上述過程,直到處理完所有的檢測框。
def _non_max_suppression(self, scores, boxes):
"""Non max suppression"""
# https://github.com/xiaohu2015/DeepLearning_tutorials/blob/master/ObjectDetections/yolo/yolo.py
# scores :[S*S*B, C] ; boxes:[S*S*B, 4]
# for each class
for c in range(self.C):
sorted_idxs = np.argsort(scores[:, c])
last = len(sorted_idxs) - 1
while last > 0:
# scores[sorted_idxs[last], c]爲一個類中scores最大的值
if scores[sorted_idxs[last], c] < 1e-6:
break
for i in range(last):
if scores[sorted_idxs[i], c] < 1e-6:
continue
# 將兩個bbox的IOU值 與 iou_threshold 進行比較
if self._iou(boxes[sorted_idxs[i]], boxes[sorted_idxs[last]]) > self.iou_threshold:
scores[sorted_idxs[i], c] = 0.0
last -= 1
總結
輸入圖片被劃分爲7x7個網格。網格只是物體中心點位置的劃分之用,並不是對圖片進行切片,不會讓網格脫離整體的關係。
下一篇將通過分析yolo源碼加深對yolo算法的理解。
參考資料: