2014年R-CNN算法被提出,基本奠定了two-stage方式在目標檢測領域的應用。它的算法結構如下圖
算法步驟如下:
R-CNN較傳統的目標檢測算法獲得了50%的性能提升,在使用VGG-16模型作為物體識別模型情況下,在voc2007數據集上可以取得66%的準確率,已經算還不錯的壹個成績了。其最大的問題是速度很慢,內存占用量很大,主要原因有兩個
針對R-CNN的部分問題,2015年微軟提出了Fast R-CNN算法,它主要優化了兩個問題。
R-CNN和fast R-CNN均存在壹個問題,那就是 由選擇性搜索來生成候選框,這個算法很慢 。而且R-CNN中生成的2000個左右的候選框全部需要經過壹次卷積神經網絡,也就是需要經過2000次左右的CNN網絡,這個是十分耗時的(fast R-CNN已經做了改進,只需要對整圖經過壹次CNN網絡)。這也是導致這兩個算法檢測速度較慢的最主要原因。
faster R-CNN 針對這個問題, 提出了RPN網絡來進行候選框的獲取,從而擺脫了選擇性搜索算法,也只需要壹次卷積層操作,從而大大提高了識別速度 。這個算法十分復雜,我們會詳細分析。它的基本結構如下圖
主要分為四個步驟:
使用VGG-16卷積模型的網絡結構:
卷積層采用的VGG-16模型,先將PxQ的原始圖片,縮放裁剪為MxN的圖片,然後經過13個conv-relu層,其中會穿插4個max-pooling層。所有的卷積的kernel都是3x3的,padding為1,stride為1。pooling層kernel為2x2, padding為0,stride為2。
MxN的圖片,經過卷積層後,變為了(M/16) x (N/16)的feature map了。
faster R-CNN拋棄了R-CNN中的選擇性搜索(selective search)方法,使用RPN層來生成候選框,能極大的提升候選框的生成速度。RPN層先經過3x3的卷積運算,然後分為兩路。壹路用來判斷候選框是前景還是背景,它先reshape成壹維向量,然後softmax來判斷是前景還是背景,然後reshape恢復為二維feature map。另壹路用來確定候選框的位置,通過bounding box regression實現,後面再詳細講。兩路計算結束後,挑選出前景候選框(因為物體在前景中),並利用計算得到的候選框位置,得到我們感興趣的特征子圖proposal。
卷積層提取原始圖像信息,得到了256個feature map,經過RPN層的3x3卷積後,仍然為256個feature map。但是每個點融合了周圍3x3的空間信息。對每個feature map上的壹個點,生成k個anchor(k默認為9)。anchor分為前景和背景兩類(我們先不去管它具體是飛機還是汽車,只用區分它是前景還是背景即可)。anchor有[x,y,w,h]四個坐標偏移量,x,y表示中心點坐標,w和h表示寬度和高度。這樣,對於feature map上的每個點,就得到了k個大小形狀各不相同的選區region。
對於生成的anchors,我們首先要判斷它是前景還是背景。由於感興趣的物體位於前景中,故經過這壹步之後,我們就可以舍棄背景anchors了。大部分的anchors都是屬於背景,故這壹步可以篩選掉很多無用的anchor,從而減少全連接層的計算量。
對於經過了3x3的卷積後得到的256個feature map,先經過1x1的卷積,變換為18個feature map。然後reshape為壹維向量,經過softmax判斷是前景還是背景。此處reshape的唯壹作用就是讓數據可以進行softmax計算。然後輸出識別得到的前景anchors。
另壹路用來確定候選框的位置,也就是anchors的[x,y,w,h]坐標值。如下圖所示,紅色代表我們當前的選區,綠色代表真實的選區。雖然我們當前的選取能夠大概框選出飛機,但離綠色的真實位置和形狀還是有很大差別,故需要對生成的anchors進行調整。這個過程我們稱為bounding box regression。
假設紅色框的坐標為[x,y,w,h], 綠色框,也就是目標框的坐標為[Gx, Gy,Gw,Gh], 我們要建立壹個變換,使得[x,y,w,h]能夠變為[Gx, Gy,Gw,Gh]。最簡單的思路是,先做平移,使得中心點接近,然後進行縮放,使得w和h接近。如下:
我們要學習的就是dx dy dw dh這四個變換。由於是線性變換,我們可以用線性回歸來建模。設定loss和優化方法後,就可以利用深度學習進行訓練,並得到模型了。對於空間位置loss,我們壹般采用均方差算法,而不是交叉熵(交叉熵使用在分類預測中)。優化方法可以采用自適應梯度下降算法Adam。
得到了前景anchors,並確定了他們的位置和形狀後,我們就可以輸出前景的特征子圖proposal了。步驟如下:
1,得到前景anchors和他們的[x y w h]坐標。
2,按照anchors為前景的不同概率,從大到小排序,選取前pre_nms_topN個anchors,比如前6000個
3,剔除非常小的anchors。
4,通過NMS非極大值抑制,從anchors中找出置信度較高的。這個主要是為了解決選取交疊問題。首先計算每壹個選區面積,然後根據他們在softmax中的score(也就是是否為前景的概率)進行排序,將score最大的選區放入隊列中。接下來,計算其余選區與當前最大score選區的IOU(IOU為兩box交集面積除以兩box並集面積,它衡量了兩個box之間重疊程度)。去除IOU大於設定閾值的選區。這樣就解決了選區重疊問題。
5,選取前post_nms_topN個結果作為最終選區proposal進行輸出,比如300個。
經過這壹步之後,物體定位應該就基本結束了,剩下的就是物體識別了。
和fast R-CNN中類似,這壹層主要解決之前得到的proposal大小形狀各不相同,導致沒法做全連接。全連接計算只能對確定的shape進行運算,故必須使proposal大小形狀變為相同。通過裁剪和縮放的手段,可以解決這個問題,但會帶來信息丟失和圖片形變問題。我們使用ROI pooling可以有效的解決這個問題。
ROI pooling中,如果目標輸出為MxN,則在水平和豎直方向上,將輸入proposal劃分為MxN份,每壹份取最大值,從而得到MxN的輸出特征圖。
ROI Pooling層後的特征圖,通過全連接層與softmax,就可以計算屬於哪個具體類別,比如人,狗,飛機,並可以得到cls_prob概率向量。同時再次利用bounding box regression精細調整proposal位置,得到bbox_pred,用於回歸更加精確的目標檢測框。
這樣就完成了faster R-CNN的整個過程了。算法還是相當復雜的,對於每個細節需要反復理解。faster R-CNN使用resNet101模型作為卷積層,在voc2012數據集上可以達到83.8%的準確率,超過yolo ssd和yoloV2。其最大的問題是速度偏慢,每秒只能處理5幀,達不到實時性要求。
針對於two-stage目標檢測算法普遍存在的運算速度慢的缺點, yolo創造性的提出了one-stage。也就是將物體分類和物體定位在壹個步驟中完成。 yolo直接在輸出層回歸bounding box的位置和bounding box所屬類別,從而實現one-stage。通過這種方式, yolo可實現45幀每秒的運算速度,完全能滿足實時性要求 (達到24幀每秒,人眼就認為是連續的)。它的網絡結構如下圖:
主要分為三個部分:卷積層,目標檢測層,NMS篩選層。
采用Google inceptionV1網絡,對應到上圖中的第壹個階段,***20層。這壹層主要是進行特征提取,從而提高模型泛化能力。但作者對inceptionV1進行了改造,他沒有使用inception module結構,而是用壹個1x1的卷積,並聯壹個3x3的卷積來替代。(可以認為只使用了inception module中的壹個分支,應該是為了簡化網絡結構)
先經過4個卷積層和2個全連接層,最後生成7x7x30的輸出。先經過4個卷積層的目的是為了提高模型泛化能力。yolo將壹副448x448的原圖分割成了7x7個網格,每個網格要預測兩個bounding box的坐標(x,y,w,h)和box內包含物體的置信度confidence,以及物體屬於20類別中每壹類的概率(yolo的訓練數據為voc2012,它是壹個20分類的數據集)。所以壹個網格對應的參數為(4x2+2+20) = 30。如下圖
其中前壹項表示有無人工標記的物體落入了網格內,如果有則為1,否則為0。第二項代表bounding box和真實標記的box之間的重合度。它等於兩個box面積交集,除以面積並集。值越大則box越接近真實位置。
分類信息: yolo的目標訓練集為voc2012,它是壹個20分類的目標檢測數據集 。常用目標檢測數據集如下表:
| Name | # Images (trainval) | # Classes | Last updated |
| --------------- | ------------------- | --------- | ------------ |
| ImageNet | 450k | 200 | 2015 |
| COCO | 120K | 90 | 2014 |
| Pascal VOC | 12k | 20 | 2012 |
| Oxford-IIIT Pet | 7K | 37 | 2012 |
| KITTI Vision | 7K | 3 | |
每個網格還需要預測它屬於20分類中每壹個類別的概率。分類信息是針對每個網格的,而不是bounding box。故只需要20個,而不是40個。而confidence則是針對bounding box的,它只表示box內是否有物體,而不需要預測物體是20分類中的哪壹個,故只需要2個參數。雖然分類信息和confidence都是概率,但表達含義完全不同。
篩選層是為了在多個結果中(多個bounding box)篩選出最合適的幾個,這個方法和faster R-CNN 中基本相同。都是先過濾掉score低於閾值的box,對剩下的box進行NMS非極大值抑制,去除掉重疊度比較高的box(NMS具體算法可以回顧上面faster R-CNN小節)。這樣就得到了最終的最合適的幾個box和他們的類別。
yolo的損失函數包含三部分,位置誤差,confidence誤差,分類誤差。具體公式如下:
誤差均采用了均方差算法,其實我認為,位置誤差應該采用均方差算法,而分類誤差應該采用交叉熵。由於物體位置只有4個參數,而類別有20個參數,他們的累加和不同。如果賦予相同的權重,顯然不合理。故yolo中位置誤差權重為5,類別誤差權重為1。由於我們不是特別關心不包含物體的bounding box,故賦予不包含物體的box的置信度confidence誤差的權重為0.5,包含物體的權重則為1。
Faster R-CNN準確率mAP較高,漏檢率recall較低,但速度較慢。而yolo則相反,速度快,但準確率和漏檢率不盡人意。SSD綜合了他們的優缺點,對輸入300x300的圖像,在voc2007數據集上test,能夠達到58 幀每秒( Titan X 的 GPU ),72.1%的mAP。
SSD網絡結構如下圖:
和yolo壹樣,也分為三部分:卷積層,目標檢測層和NMS篩選層
SSD論文采用了VGG16的基礎網絡,其實這也是幾乎所有目標檢測神經網絡的慣用方法。先用壹個CNN網絡來提取特征,然後再進行後續的目標定位和目標分類識別。
這壹層由5個卷積層和壹個平均池化層組成。去掉了最後的全連接層。SSD認為目標檢測中的物體,只與周圍信息相關,它的感受野不是全局的,故沒必要也不應該做全連接。SSD的特點如下。
每壹個卷積層,都會輸出不同大小感受野的feature map。在這些不同尺度的feature map上,進行目標位置和類別的訓練和預測,從而達到 多尺度檢測 的目的,可以克服yolo對於寬高比不常見的物體,識別準確率較低的問題。而yolo中,只在最後壹個卷積層上做目標位置和類別的訓練和預測。這是SSD相對於yolo能提高準確率的壹個關鍵所在。
如上所示,在每個卷積層上都會進行目標檢測和分類,最後由NMS進行篩選,輸出最終的結果。多尺度feature map上做目標檢測,就相當於多了很多寬高比例的bounding box,可以大大提高泛化能力。
和faster R-CNN相似,SSD也提出了anchor的概念。卷積輸出的feature map,每個點對應為原圖的壹個區域的中心點。以這個點為中心,構造出6個寬高比例不同,大小不同的anchor(SSD中稱為default box)。每個anchor對應4個位置參數(x,y,w,h)和21個類別概率(voc訓練集為20分類問題,在加上anchor是否為背景,***21分類)。如下圖所示:
另外,在訓練階段,SSD將正負樣本比例定位1:3。訓練集給定了輸入圖像以及每個物體的真實區域(ground true box),將default box和真實box最接近的選為正樣本。然後在剩下的default box中選擇任意壹個與真實box IOU大於0.5的,作為正樣本。而其他的則作為負樣本。由於絕大部分的box為負樣本,會導致正負失衡,故根據每個box類別概率排序,使正負比例保持在1:3。SSD認為這個策略提高了4%的準確率
另外,SSD采用了數據增強。生成與目標物體真實box間IOU為0.1 0.3 0.5 0.7 0.9的patch,隨機選取這些patch參與訓練,並對他們進行隨機水平翻轉等操作。SSD認為這個策略提高了8.8%的準確率。
和yolo的篩選層基本壹致,同樣先過濾掉類別概率低於閾值的default box,再采用NMS非極大值抑制,篩掉重疊度較高的。只不過SSD綜合了各個不同feature map上的目標檢測輸出的default box。
SSD基本已經可以滿足我們手機端上實時物體檢測需求了,TensorFlow在Android上的目標檢測官方模型ssd_mobilenet_v1_android_export.pb,就是通過SSD算法實現的。它的基礎卷積網絡采用的是mobileNet,適合在終端上部署和運行。
針對yolo準確率不高,容易漏檢,對長寬比不常見物體效果差等問題,結合SSD的特點,提出了yoloV2。它主要還是采用了yolo的網絡結構,在其基礎上做了壹些優化和改進,如下
網絡采用DarkNet-19:19層,裏面包含了大量3x3卷積,同時借鑒inceptionV1,加入1x1卷積核全局平均池化層。結構如下
yolo和yoloV2只能識別20類物體,為了優化這個問題,提出了yolo9000,可以識別9000類物體。它在yoloV2基礎上,進行了imageNet和coco的聯合訓練。這種方式充分利用imageNet可以識別1000類物體和coco可以進行目標位置檢測的優點。當使用imageNet訓練時,只更新物體分類相關的參數。而使用coco時,則更新全部所有參數。
YOLOv3可以說出來直接吊打壹切圖像檢測算法。比同期的DSSD(反卷積SSD), FPN(feature pyramid networks)準確率更高或相仿,速度是其1/3.。
YOLOv3的改動主要有如下幾點:
不過如果要求更精準的預測邊框,采用COCO AP做評估標準的話,YOLO3在精確率上的表現就弱了壹些。如下圖所示。
當前目標檢測模型算法也是層出不窮。在two-stage領域, 2017年Facebook提出了mask R-CNN 。CMU也提出了A-Fast-RCNN 算法,將對抗學習引入到目標檢測領域。Face++也提出了Light-Head R-CNN,主要探討了 R-CNN 如何在物體檢測中平衡精確度和速度。
one-stage領域也是百花齊放,2017年首爾大學提出 R-SSD 算法,主要解決小尺寸物體檢測效果差的問題。清華大學提出了 RON 算法,結合 two stage 名的方法和 one stage 方法的優勢,更加關註多尺度對象定位和負空間樣本挖掘問題。
目標檢測領域的深度學習算法,需要進行目標定位和物體識別,算法相對來說還是很復雜的。當前各種新算法也是層不出窮,但模型之間有很強的延續性,大部分模型算法都是借鑒了前人的思想,站在巨人的肩膀上。我們需要知道經典模型的特點,這些tricks是為了解決什麽問題,以及為什麽解決了這些問題。這樣才能舉壹反三,萬變不離其宗。綜合下來,目標檢測領域主要的難點如下:
壹文讀懂目標檢測AI算法:R-CNN,faster R-CNN,yolo,SSD,yoloV2
從YOLOv1到v3的進化之路
SSD-Tensorflow超詳細解析壹:加載模型對圖片進行測試? /darknet/yolo/ ? /pjreddie/darknet
C#項目參考:/AlturosDestinations/Alturos.Yolo
項目實踐貼個圖。