python ssd目标检测_解读目标检测之SSD:Single Shot MultiBox Detector
注:md文件,Typora書寫,md兼容程度github=CSDN>知乎,若有不兼容處麻煩移步其他平臺,github文檔供下載。
發表在CSDN:https://blog.csdn.net/hancoder/article/
發表在知乎專欄:https://zhuanlan.zhihu.com/c_1088438808227254272
上傳在github:https://github.com/FermHan/Learning-Notes
[TOC]
SSD
SSD:Single Shot MultiBox Detector
作者:Wei Liu
前言
背景知識:faster rcnn與YOLO,不熟悉可參考本人csdn。faster rcnn發展史:https://blog.csdn.net/hancoder/article/details/87917174 。YOLO:https://blog.csdn.net/hancoder/article/details/87994678 ,知乎專欄也有。
標題解釋:SSD:Single Shot MultiBox Detector
Single shot:SSD是one-stage方法,單階段表示定位目標和分類的任務是在網絡的一次前向傳遞中完成的。而faster rcnn是雙階段的,先通過CNN得到候選框roi,然后再進行分類與回歸。 MultiBox:SSD是多框預測。 Detector:物體檢測器,并分類在faster rcnn中,anchors只作用在最后的conv5_3的特征圖上,這對檢測小物體及位置來說是有不足的,所以SSD想在多個特征圖上用anchors回歸檢測物體。高層特征圖的語義信息豐富對分類有益,而低層特征圖語義信息少但位置信息多,利于定位。
SSD有多好:速度與mAP對比:
SSD:59 FPS with mAP 74.3% on VOC2007 test, Faster R-CNN: 7 FPS with mAP 73.2% YOLO: 45 FPS with mAP 63.4%框架介紹
如圖,下半部分是YOLO的結果,他只利用conv5特征圖進行回歸分類來目標檢測。缺點:小目標丟失,位置信息有丟失。
結構圖的上半部分是SSD采樣金字塔結構,綜合conv4_3、conv7、conv8_2、conv9_2、conv10_2、conv11_2這些層的feature map進行目標檢測,同時進行softmax分類和位置回歸。圖上用的是1個3×3整體卷積出來位置與分類,代碼里是2個3×3分別卷積,whatever,原理都一樣這也不是重點。加入了先驗框。
什么是金字塔結構:這里無需復雜理解,只知道它如上圖結構圖那樣,經過池化后圖像逐漸縮小即可。想進一步閱讀比SSD更復雜的金字塔結構可以參考本人FPN博客:https://blog.csdn.net/hancoder/article/details/89048870SSD創新點
單階段
YOLOv1也是單階段,但SSD比YOLO快還準。
多特征圖上預測
YOLO主要利用conv5_3上的信息進行預測,而SSD利用了多個特征圖:conv4_3、conv7、conv8_2、conv9_2、conv10_2、conv11_2。
劃分特征圖
r如果是YOLO,會把特征圖均分成7×7,分割后的每個小塊叫一個cell單元,然后以每個cell單元為中心,像faster rcnn那樣,預設一些anchors。不同的是SSD中把anchors錨稱作了priors或default boxes,而且SSD因為在很后面的特征圖上操作,所以是以每個像素為單位劃分的。
prior的具體設置如下
| 特征圖 | feature_size | prior_per_cell | Total_num |
| ----------- | ------------ | ---------------------- | --------- |
| conv4_3 | 38×38 | 4 | 5776 |
| conv7 | 19×19 | 6 | 2166 |
| conv8_2 | 10×10 | 6 | 600 |
| conv9_2 | 5×5 | 6 | 150 |
| conv10_2 | 3×3 | 4 | 36 |
| conv11_2 | 1×1 | 4 | 4 |
| 輸入300×300 | | 總和對應的即圖上的8732 | 8732 |
此外,因為faster rcnn中是在單個特征圖conv5_3上放置anchors,所以anchors所在特征圖相對原圖的比例是不變的,都是1/16。所以faster rcnn的scale統一定3個值即可。但是SSD是在多個特征圖上進行的,所以后文我們需要介紹在不同特征圖上的priors的scale是如何定義的。
prior的scale與ratio
下面來看下SSD選擇anchor的方法。首先每個點cell都會有一大一小兩個正方形的anchor,小方形的邊長用min_size來表示,大方形的邊長用sqrt(min_size*max_size)來表示(min_size與max_size的值每一層都不同)。同時還有多個長方形的anchor,長方形anchor的數目在不同層級會有差異,他們的長寬可以用下面的公式來表達,ratio的數目就決定了某層上每一個點對應的長方形anchor的數目。
在faster rcnn中有scale和ratio兩個數值,而SSD中,每個feature map上的scale的算法是
$s_k=s_{min}+ {{s_{max}-s_{min}}over{m-1}}(k-1),k∈[1,m]$m代表預測時feature map的數量,如SSD300的m=6,分別是conv4_3、conv7、conv8_2、conv9_2、conv10_2、conv11_2。在faster rcnn中scale可能是一個具體的大小,SSD中代表的是相對輸入圖像的比例。
smax和smin代表最低層和最高層分別有scale:0.2和0.9。$s_{min}=0.2,s_{max}=0.9$。例如最高層回歸出的每個基礎框的尺寸大小是0.9×300=370。
第k層的min_size=Sk,第k層的max_size=Sk+1。(注意區分smin和min_size是不同的東西)
SSD按照如下規則生成prior box:
- 以feature map上每個點的中點為中心,生成N(4或6)個同心的prior box
- 兩個正方形prior box變成分別為: $minsize,sqrt{minsize×maxsize}$,其中 $minsize_k=s_k300 , maxsize_k=s_{k+1}*300?$
- 此外還有4個正方形,長寬為:$width=minsize×sqrt{ratio} , heitght=minsize×1/sqrt{ratio}$,其中$ratio={2,3,1/2,1/3}$。(論文中的1是正方形)
注:以上是作者論文中給的計算各層anchor尺寸的方法,但在作者源碼中給的計算anchor方法有點差異,沒有和論文的方法完全對應上。管他呢,反正這個東西都是超參數,差不多就行。
| 特征圖 | min_size | max_size |
| -------- | -------- | -------- |
| conv4_3 | 30 | 60 |
| conv7 | 60 | 111 |
| conv8_2 | 111 | 162 |
| conv9_2 | 162 | 213 |
| conv10_2 | 213 | 264 |
| conv11_2 | 264 | 315 |
預設好anchoris后的如何卷積訓練
如結構圖,上半部分的橫線上有3×3×(N×(classes+4))的字樣(N為4或6),指的是在各個特征圖上用3×3卷積,得出的通道數代表:每個cell預設了N個框,每個框有classes個類別,每個框有4個位置坐標信息。從這里我們也可以得知SSD與YOLOv1不同,SSD對于每個單元的每個先驗框,其都輸出一套獨立的檢測值,
訓練與loss
給priors賦label
訓練時每個框要有gt才能訓練,即每個框要有label。關于給框賦label的操作我在我之前的論文Faster rcnn、FPN和YOLO中已多次提及了,這里簡單引用一下我之前寫的,賦label的原理都是一樣的,不管是在RPN前背景分類還是在fast rcnn具體分類中。
RPN訓練時需要有anchor的前背景類標。對anchor進行label的原理和Faster R-CNN里一模一樣,詳情可以去本人博客https://blog.csdn.net/hancoder/article/details/87917174的RPNlabel部分查看。反正就是與gt的IoU>0.7就是正類label=1,IoU<0.3是負類背景label=0,其余介于0.3和0.7直接的都扔掉不參與訓練label=-1。在faster rcnn中拿256個anchors訓練后得到W×H×9個roi。loss的計算:
SSD的loss和常規目標檢測的loss一樣:分類loss+位置回歸loss
N是匹配的默認框的個數,$alpha=1$confidence類別loss:采用交叉熵損失
$x_{ij}^p=1$代表第i個default框與第j個真實框關于類別p相匹配,不匹配的$x_{ij}^p=0$。前半個式子是pisitive,后半個是negative根據上面的賦label策略,一定有$Sigma_ix_{ij}^p>=1?$,這個式子的物體含義是任一編號為 j 的框gt,至少有1個默認框與其匹配,即每個gt框可能賦給了多個默認框。
SSD的類別是1背景+c個類別,1+c個置信度,第一個置信度指的是不含目標或者屬于背景的評分。后面的c個累唄置信度其實包含1個背景,即實際類別c-1個,自己注意體會即可。置信度最高的類別即邊框的類別。
location位置loss:
定位誤差即fast rcnn里的smooth L1 loss,坐標分別算的是中心坐標與寬高。l是預測框相關的數值,g^是真實框g相關的數值。d是默認default框$d=(d^{cx},d^{cy},d^w,d^h)$,預測框為$b=(b^{cx},b^{cy},b^w,b^h)$無論是l還是g都是需要編碼的,即我們超參默認框之后,我們的g^和l都是相對于默認框的位置來進行編碼,可以理解為與默認框的距離/默認框的長度,這種編碼方式文中叫做offset。具體編碼方式如下
上面稱為編碼encode,預測時我們需要反向這個過程,即進行解碼decode,從預測值l中得到邊界框的真實位置b
variance_encoded_in_target來控制兩種模式,當其為True時,表示variance被包含在預測值中,就是上面那種情況。但是如果是Fasle(大部分采用這種方式,訓練更容易?),就需要手動設置超參數variance,用來對ll的4個值進行放縮,此時邊界框需要這樣解碼:
SSD的其他一些trick
Hard negative mining負樣本挖掘
在生成一系列的 predictions 之后,會產生很多個符合 ground truth box 的 predictions boxes,但同時,不符合 ground truth boxes 也很多,而且這個 negative boxes,遠多于 positive boxes。這會造成 negative boxes、positive boxes 之間的不均衡。訓練時難以收斂。
解決措施:先隨機抽取一定數目負框,然后排序抽得分高的若干個框。選擇最高的幾個,保證最后 negatives、positives 的比例在 3:1。
本文通過實驗發現,這樣的比例可以更快的優化,訓練也更穩定。
Data augmentation數據增強
實驗部分
a trous Algorithm
此部分內容借鑒了其他博客。
基于VGG16,預訓練過。移除掉drpoout層和FC8,用SGD以0.001學習率,0.9動量,0.0005權重衰減,32batch size微調。
然后借鑒了DeepLab-LargeFOV,分別將VGG16的全連接層fc6和fc7轉換成3×3卷積層conv6和1×1卷積層conv7,同時
將池化層pool5由原來的2×2?s2變成3×3?s1(猜想是不想reduce特征圖大小),為了配合這種變化,采用了一種a trous Algorithm(hole filling algorithm),其實就是conv6采用擴展卷積或帶孔卷積(Dilation Conv),其在不增加參數與模型復雜度的條件下指數級擴大卷積的視野,其使用擴張率(dilation rate)參數,來表示擴張的大小,如下圖7所示,(a)是普通的3×3卷積,其視野就是3×3,(b)是擴張率為2,此時視野變成7×7,(c)擴張率為4時,視野擴大為15×15,但是視野的特征更稀疏了。Conv6采用3×3大小但dilation rate=6的擴展卷積。
另附兩個關于a trous Algorithm(hole filling algorithm)的解讀
博客 1:http://www.cnblogs.com/jianyingzhou/p/5386222.html
最早用的就是 deeplab 的文章了,Semantic Image Segmentation with Deep Convolutional Nets and Fully Connected CRFS 這篇文章和 fcn 不同的是,在最后產生 score map 時,不是進行upsampling,而是采用了 hole algorithm,就是在 pool4 和 pool 5層,步長由 2 變成 1,必然輸出的 score map 變大了,但是 receptive field 也變小了,為了不降低 receptive field,怎么做呢?利用 hole algorithm,將卷積 weights 膨脹擴大,即原來卷積核是 3x3,膨脹后,可能變成 7x7 了,這樣 receptive field 變大了,而 score map 也很大,即輸出變成 dense 的了。這么做的好處是,輸出的 score map 變大了,即是 dense 的輸出了,而且 receptive field 不會變小,而且可以變大。這對做分割、檢測等工作非常重要。
博客 2:http://blog.csdn.net/tangwei2014/article/details/50453334
既想利用已經訓練好的模型進行 fine-tuning,又想改變網絡結構得到更加 dense 的 score map.這個解決辦法就是采用 Hole 算法。如下圖 (a) (b) 所示,在以往的卷積或者 pooling 中,一個 filter 中相鄰的權重作用在 feature map 上的位置都是物理上連續的。如下圖 (c) 所示,為了保證感受野不發生變化,某一層的 stride 由 2 變為 1 以后,后面的層需要采用 hole 算法,具體來講就是將連續的連接關系是根據 hole size 大小變成 skip 連接的(圖 (c) 為了顯示方便直接畫在本層上了)。不要被 (c) 中的 padding 為 2 嚇著了,其實 2 個 padding 不會同時和一個 filter 相連。
pool4 的 stride 由 2 變為 1,則緊接著的 conv5_1, conv5_2 和 conv5_3 中 hole size 為 2。接著 pool5 由 2 變為 1 , 則后面的 fc6 中 hole size 為 4。
Additional Notes On SSD
SSD的論文還作了以下的觀察:
- 更多的default boxes會帶來更精確的檢測,但耗時增加
- 由于detector以多種分辨率運行于特征上,因此在多個圖層上使用MultiBox也會導致更好的檢測
- 80%的時間花在基礎VGG-16網絡上:這意味著,使用更快,同樣精確的網絡,SSD的性能可能會更好
- SSD將具有相似類別的對象(例如動物)混淆。這可能是因為定位是基于多個類的
- SSD-500(使用512x512輸入圖像的最高分辨率版本)在Pascal VOC2007上實現了最佳的mAP,達到了76.8%,但是速度降低到22 fps。因此SSD-300在59 fps下具有74.3 mAP更好的折衷。
- SSD在較小的對象上產生較差的性能,因為它們可能不會出現在所有功能地圖中。增加輸入圖像分辨率緩解了這個問題,但并未完全解決這個問題
代碼
keras代碼地址:https://github.com/pierluigiferrari/ssd_keras/blob/master/models/keras_ssd300.py
代碼只大概閱讀,沒有進行逐行研究,這里給出僅供參考。
基礎網絡
x特征抽取
fc6給conv4_3加上了個L2:因為該層比較靠前,其norm較大,所以在其后面增加了一個L2 Normalization層
# Feed conv4_3 into the L2 normalization layer conv4_3_norm = L2Normalization(gamma_init=20, name='conv4_3_norm')(conv4_3)分類與定位
### Build the convolutional predictor layers on top of the base networkanchors
### Generate the anchor boxes (called "priors" in the original Caffe/C++ implementation, so I'll keep their layer names)reshape
### Reshape 為后面concat做準備,分別讓最后一個維度為類別數,4個坐標,concatenate
### Concatenate the predictions from the different layers置信度softmax
# The box coordinate predictions will go into the loss function just the way they are,預測結果合并
# Concatenate the class and box predictions and the anchors to one large predictions vector總結
SSD雖然在多個特征圖上進行分類回歸,但是對小目標的識別仍比較差,還達不到faster rcnn的水準。這主要是因為小尺寸的目標多用較低層級的anchor來訓練(因為小尺寸目標在較低層級IOU較大),較低層級的特征非線性程度不夠,無法訓練到足夠的精確度。
參考:
解析:https://blog.csdn.net/xiaohu2022/article/details/79833786
https://www.jianshu.com/p/0903b160d554
解析推薦:https://blog.csdn.net/u010167269/article/details/52563573
a trous algorithm: http://liangchiehchen.com/projects/DeepLab.html
解析:https://blog.csdn.net/u010167269/article/details/52563573
各個方法對比:http://host.robots.ox.ac.uk:8080/leaderboard/displaylb.php?cls=mean&challengeid=11&compid=4
各個方法對比:https://handong1587.github.io/deep_learning/2015/10/09/object-detection.html
代碼:https://github.com/pierluigiferrari/ssd_keras/blob/master/models/keras_ssd300.py
總結
以上是生活随笔為你收集整理的python ssd目标检测_解读目标检测之SSD:Single Shot MultiBox Detector的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: sigmoid函数求导_交叉熵损失函数的
- 下一篇: 学生网页设计代码成品 大学生汽车网页代做