YOLO v1的詳解與復現

yolov1是一個快速的one-stage目標檢測器,獨樹一幟的用劃分網格的策略實現目標檢測,本文將詳細解釋yolov1算法,並簡述如何用pytorch復現該算法。pytorch-yolov1 github 本文屬於做者的理解,不免出現錯誤或者瑕疵,還請諒解與指正。git

基本思想

簡單回顧一下目標檢測的作法,1.採用滑動窗口,對每一個窗口分類和位置修正;2.RPN的方式先提取候選區域,特徵圖對應候選區域範圍通過roipooling獲得所需特徵;3.SSD繼承RPN相似的anchor機制,設定預設框並對每一個預設框賦予groundtruth,全卷積網絡訓練目標。github

yolo將輸入圖像劃分爲 $ S\times S $ 的網格,物體的中心落在哪個網格內,這個網格就負責預測該物體的置信度,類別以及位置。算法

網絡最後的輸出是 $ S\times S\times 30 $ 的數據塊,yolov1是含有全鏈接層的,這個數據塊能夠經過reshape獲得。也就是說,輸出其實已經丟失了位置信息(在v2,v3中用全卷積網絡,每一個輸出點都能有各自對應的感覺野範圍)。這麼一看,yolov1根據每張圖像的目標label,編碼出一個 $ S\times S\times 30 $ 的數據塊,而後讓卷積網絡去擬合這個target,簡單粗暴。網絡

來看看 $ S\times S\times 30 $ 的數據塊的具體含義。框架

  • $ S\times S $是圖像位置,好比第一行第二列的網格,回到原圖的位置也是如此。(有全鏈接層的時候,其實隨意,只要你預測時每一個位置的網格對應你編碼時的網格就能夠。全卷積層因爲每一個點的感覺野的問題,最好是一一對應,不然原理上說不通,效果應該會差不少)ide

  • 30的通道上分別是兩個box的cxcy,wh,confidence,這就佔了10個,再加上20個類別正好是30函數

cxcy表示物體的中心點座標與對應網格左上角的誤差,注意歸一化到0-1,須要除以網格大小;wh是物體相對於圖片的大小,也在0-1之間;confidence是 \(P(object) \times IOU_{truth}^{pred}\)其中IOU在訓練過程當中是在線計算的學習

網絡結構

網絡結構在分類網絡的基礎上改進,v1的結構很簡單,在v2,v3中,或者其餘檢測網絡中,廣泛會用特徵層跨層鏈接融合,分層檢測不一樣尺度大小目標的思路。主要是考慮淺層特徵語義信息不充分,而小目標在深層特徵圖丟失的問題吧(我的理解)。編碼

爲了方便使用pytorch的預訓練模型,我採用了resnet50,刪除stage5後的全局池化和全鏈接層,增長一個帶有空洞卷積的網絡block(模仿detnet網絡,增長感覺野而不改變輸出特徵圖大小)。spa

輸入圖像大小爲448時,輸出大小爲14,因此個人網格設計要密集一點,這也是我增長空洞卷積block的緣由,我擔憂輸出點的感覺野範圍不夠而影響大目標的檢測,實際狀況可能不會,未驗證。

損失函數

yolov1的損失函數全是均方偏差,須要理解的是其含義。

首先要明確兩個概念,一是網格中有無目標,二是網格中的一個目標只有一個box負責(responsible)另外一個box也算沒有目標,根據在線計算IOU的大小肯定哪個負責。

confidence損失:負責檢測的box的label是在線計算的IOU,不負責和無目標的都爲0,爲了平衡,加入\(\lambda _{noobj}\)

位置損失:容易理解,負責檢測的纔有位置損失,其餘的都不需回傳損失,也就不須要計算,此外小目標對於預測wh的偏差更敏感,用開根的方法緩解。舉例來講,大小爲10和大小爲100的目標,預測大小分別爲20和110,損失同樣可是顯然小目標檢測的更差一些,開根後,\((\sqrt{20} - \sqrt{10})^{2} = 1.7\),而\((\sqrt{110} - \sqrt{100})^{2} = 0.24\),至關於強化了小目標的wh的損失。

類別損失:容易理解,含有目標的網格纔有類別損失,其餘都不須要回傳損失,也就不須要計算。默認網格只出現一種類別,這固然是有缺陷的。yolov1對於一些彙集的目標,檢測效果會很差。其實彙集目標自己也算很難檢測的狀況吧。

復現總結

有了yolov1的基本概念,就能夠開始寫本身的檢測器了,我採用了pytorch0.2的框架(等待1.0中),下面介紹一些重要的點。

數據流

數據流是指送入訓練的每個batch,通常都是(imgs_tensor,target_tensor),img部分須要作一些數據加強,好比顏色抖動,隨機裁剪,平移變換,水平反轉,作完數據加強最好可視化一下輸出結果,確保box_label通過變換後是正確的。數據加強完後,根據box_label進行編碼(就是按照yolo的思想生成$ S\times S\times 30 $ 的數據塊做爲target,含有目標的confidence先設置爲1,用於區別不含目標的,IOU target在線計算)。

網絡結構

在resnet50基礎上按前文所述改進,輸出爲(batch_size, C, H, W),爲了與以後的Yololoss匹配,改變一下順序爲 (batch_size, H, W, C),C爲30。

YOLOLoss

pred_tensor和target_tensor形狀一致,經過mask選取對應部分分別計算mesloss,最後按照公式相加起來。好在只須要寫出前向傳播過程就能夠了。

數據塊在30個通道上的含義爲(cx,cy,w,h,contain_obj,cx,cy,w,h,contain_obj,cls1,cls2,...,cls20)

預測

網絡的輸出是 $ S\times S\times 30 $ 的數據塊,首先用一個閾值選取含有目標的box,再用一個閾值篩選\(confidence\times P(cls)\),篩選後的框的cxcy從距離所在網格左上角的誤差解碼爲相對於圖像左上角的距離,最後由NMS去除一些重疊的框。

NMS是大部分深度學習目標檢測網絡所須要的,大體算法流程爲:

1.對全部預測框的置信度降序排序
2.選出置信度最高的預測框,確認其爲正確預測(下次就沒有他了,已經被確認了),並計算他與其餘預測框的IOU
3.根據2中計算的IOU去除重疊度高的,IOU>threshold就刪除
4.剩下的預測框返回第1步,直到沒有剩下的爲止

結果展現

相關文章
相關標籤/搜索