主流的算法主要分爲兩個類型:ios
(1)tow-stagees6
R-CNN系列算法,其主要思路是先經過啓發式方法(selective search)或者CNN網絡(RPN)產生一些列稀疏的候選框,而後對這些候選框進行分類和迴歸。two-stage方法的優點是準確度高。算法
(2)one-stage網絡
如YOLO和SSD,主要思路是均勻的在圖片的不一樣位置進行密集抽樣,抽樣時能夠採用不一樣尺度和長寬比,而後利用CNN提取特徵後直接進行分類和迴歸,整個過程只須要一部,因此其優點是速度快。架構
均勻的密集採樣的一個重要缺點是訓練比較困難,這主要是由於正樣本與負樣本極其不平衡,致使模型準確度稍低,不一樣算法的性能如圖:app
SSD英文名是(Single Shot MultiBox Detector),single shot指的是SSD算法屬於one-stage方法,MultiBox說明SSD是多框預測。框架
上圖能夠看出SSD在準確度和速度(除了SSD512)上都比YOLO要好不少。dom
下圖是不一樣算法的基本框架圖,對於Faster R-CNN,其先經過CNN獲得候選框,而後再進行分類和迴歸,而Yolo與SSD能夠一步到位完成檢測。相比於YOLO,SSD採用CNN來直接進行檢測,而不是像YOLO那樣在全鏈接層以後再作檢測。ide
其實採用卷積直接作檢測只是SSD相比於YOLO的其中一個不一樣點,另外還有兩個重要的改變,一是SSD提取不一樣尺度的特徵圖來作檢測,大尺度特徵圖(較靠前的特徵圖)用來檢測小物體,小尺度特徵圖(較靠後的特徵圖,感覺野大)用來檢測大物體;二是SSD採用了不一樣尺度和長寬比的先驗框(Prior boxes, Default boxes,在Faster R-CNN中叫作錨,Anchors)。Yolo算法的缺點是難以檢測小目標,並且定位不許,可是這幾點重要的改進使得SSD在必定程度上克服這些缺點。函數
SSD和YOLO都是採用一個CNN網絡來進行檢測,可是卻採用了多尺度的特徵圖,其基本架構以下圖,下面將SSD核心設計理念總結爲如下三點:
所謂多尺度採用大小不一樣的特徵圖,CNN網絡通常前面的特徵圖比較大,後面會逐漸採用stride=2的卷積或者pool來下降特徵圖大小,下圖所示,一個比較大的特徵圖和一個比較小的特徵圖,他們都用來作檢測。這樣作的好處是比較大的特徵圖用來檢測相對較小的目標,而小的特徵圖負責檢測大目標,8x8的特徵圖能夠劃分更多的單元,可是其每一個單元的default box尺度比較小。
與Yolo最後採用全鏈接層不一樣,SSD直接採用卷積對不一樣的特徵圖來進行提取檢測結果。對於形狀爲的特徵圖,只須要採用
這樣比較小的卷積核獲得檢測值。
在YOLO中,每一個單元預測多個邊界框,可是其都是相對這個單元自己(正方塊),可是真實目標的形狀是多變的,Yolo須要在訓練過程當中自適應目標的形狀。而SSD借鑑了Faster R-CNN中anchor的理念,每一個單元設置尺度或者長寬比不一樣的default boxes,預測的邊界框(bounding boxes)是以這些先驗框爲基準的,在必定程度上減小訓練難度。
通常狀況下,每一個單元會設置多個default boxes,其尺度和長寬比存在差別,以下圖所示,能夠看到每一個單元使用了4個不一樣的default boxes,圖片中貓和狗分別採用最適合它們形狀的先驗框來進行訓練,後面會詳細講解訓練過程當中的先驗框匹配原則。
SSD的檢測值也與YOLO不太同樣,對於每一個單元cell的每一個先驗框default box,其都輸出一套獨立的檢測值,對於一個bouding box,主要分爲兩個部分:
習慣上,咱們稱上面這個過程爲邊界框的編碼(encode),預測時,你須要反向這個過程,即進行解碼(decode),從預測值l中獲得邊界框的真實值b:
然而,在SSD的caffe源碼實現中還有trick,那就是設置variance超參數來調整檢測值,經過bool參數variance_encoded_in_target來控制兩種模式。當其爲true時,表示variance(方差)被包含在預測值中,就是上面那種狀況,若是是false(大部分採用這種方式,訓練更容易),就須要手動設置超參數variance,用來對l的4個值進行放縮,此時邊界框須要這樣解碼:
綜上所述,對於一個大小的特徵圖,共有m x n 個單元,每一個單元設置的先驗框數目記爲k,那麼每一個單元共須要
個預測值,全部的單元共須要
個預測值,因爲SSD採用卷積作檢測,因此就須要
個卷積核來完成這個特徵圖的檢測過程。(卷積核參數共享)。
SSD採用VGG16做爲基礎模型,而後在VGG16的基礎上新增了卷幾層來得到更多的特徵圖以用於檢測。SSD網絡結構如圖所示:
很明顯能夠看出SSD利用了多尺度的特徵圖作檢測,模型的輸入圖片大小是(還能夠是
),其與前者網絡結構沒有差異,只是最後新增一個卷積層。
採用VGG16作基礎模型,首先VGG16是在ILSVRC CLS-LOC數據集預訓練。而後借鑑了DeepLab-LargeFOV,分別將VGG16的全鏈接層fc6和fc7轉換成 卷積層 conv6和
卷積層conv7,同時將池化層pool5由原來的stride=2的
變成stride=1的
(猜測是不想reduce特徵圖大小),爲了配合這種變化,採用了一種Atrous Algorithm,其實就是conv6採用擴展卷積或帶孔卷積(Dilation Conv),其在不增長參數與模型複雜度的條件下指數級擴大卷積的視野,其使用擴張率(dilation rate)參數,來表示擴張的大小,以下圖6所示,(a)是普通的
卷積,其視野就是
,(b)是擴張率爲1,此時視野變成
,(c)擴張率爲3時,視野擴大爲
,可是視野的特徵更稀疏了。Conv6採用
大小但dilation rate=6的擴展卷積。
而後移除dropout層和fc8層,並新增一系列卷積層,在檢測數據集上作finetuing。
其中VGG16中的Conv4_3層將做爲用於檢測的第一個特徵圖。conv4_3層特徵圖大小是 ,可是該層比較靠前,其norm(範數)較大,因此在其後面增長了一個L2 Normalization層(參見ParseNet),以保證和後面的檢測層差別不是很大,這個和Batch Normalization層不太同樣,其僅僅是對每一個像素點在channle維度作歸一化,而Batch Normalization層是在[batch_size, width, height]三個維度上作歸一化。歸一化後通常設置一個可訓練的放縮變量gamma,使用TF能夠這樣簡單實現:
1 # l2norm (not bacth norm, spatial normalization) 2 def l2norm(x, scale, trainable=True, scope="L2Normalization"): 3 n_channels = x.get_shape().as_list()[-1] 4 l2_norm = tf.nn.l2_normalize(x, [3], epsilon=1e-12) 5 with tf.variable_scope(scope): 6 gamma = tf.get_variable("gamma", shape=[n_channels, ], dtype=tf.float32, 7 initializer=tf.constant_initializer(scale), 8 trainable=trainable) 9 return l2_norm * gamma
從後面新增的卷積層中提取Conv7,Conv8_2,Conv9_2,Conv10_2,Conv11_2做爲檢測所用的特徵圖,加上Conv4_3層,共提取了6個特徵圖,其大小分別是 ,可是不一樣特徵圖單元cell設置的先驗框數目不一樣(同一個特徵圖上每一個單元設置的先驗框是相同的,這裏的數目指的是一個單元的先驗框數目)。先驗框的設置,包括尺度(或者說大小)和長寬比兩個方面。對於先驗框的尺度,其遵照一個線性遞增規則:隨着特徵圖大小下降,先驗框尺度線性增長
每個feature map中的每個小格子(cell)都包含多個default box,同時每一個box對應loc(位置座標)和conf(每一個種類的得分)。
default box長寬比例默認有四個和六個:
四個default box是長寬比(aspect ratios)爲(1:1)、(2:1)、(1:2)、(1:1);六個則是添加了(1:3)、(3:1)
爲何會有兩個(1:1)呢。這時候就要講下論文中Choosing scales and aspect ratios for default boxes這段內容了。做者認爲不一樣的feature map應該有不一樣的比例(一個大框一個小框,長寬比相同,大框是指不一樣feature map 相對於原圖的尺寸比例不一樣),這是什麼意思呢,表明的是default box中這個1在原圖中的尺寸是多大的,計算公式以下所示:
Sk即表明在300*300輸入中的比例,表示先驗框大小相對於圖片的比例
m爲當前的feature map是第幾層; m=5,由於一共有6個feature map,可是第一層(Conv4_3層)是單獨設置的
k表明的是一共有多少層的feature map
Smin和Smax表明的是第一層和最後一層所佔的比例,比例的最小值和最大值,在ssd300中爲0.2-0.9。
計算:
第一個feature map 是 conv4_3:默認設置比例爲0.2/2=0.1, 此時k=1
第二個feature map 是 conv7: k=2,s = 0.2 +(0.7/4) x (2-1) =0.375 ,最後300x0.375 = 112.5,這個就是在這個feature map中比例爲1的這個default box 的尺寸相對於原圖300x300 的大小。
爲何default box的size有兩個1嗎?
做者在這有引入了一個
,也就是每一個特徵圖都設置了兩個長寬比爲1大小不一樣的正方形default box。有的小夥伴可能會有疑問,這有了Sk+1則須要多出來一部分的Sk啊,是的沒錯,最後一個特徵圖須要參考
來計算
,所以每一個特徵圖(的每一個cell)都有6個default box
(aspect ratios),可是在實現時, Conv4_3,Conv10_2,Conv11_2僅僅使用4個先驗框(default box),不使用長寬比爲3,1/3的先驗框(default box)。做者的代碼中就添加了兩層,第一層取0.1,最後一層取1。
注:對於第一個特徵圖,先驗框(default box)的尺度比例通常
,則尺度爲300x0.1=30。
對於後面的特徵圖,先驗框尺度比例按照上面公式線性增長,先將尺度比例放大100倍,而後再計算獲得Sk,而後再將Sk除以100,再乘以圖片大小,就能夠獲得各個特徵圖的先驗框的size
那麼S怎麼用呢?按以下方式計算先驗框的寬高(這裏的Sk是上面求得的各個特徵圖的先驗框的實際size,再也不是尺度比例):
ar表明的是以前提到的default box(aspect ratios)比例,即
對於default box中心點的值取值爲:
其中i,j表明在feature map中的水平和垂直的第幾格
fk表明的是feature map的size
每一個單元的先驗框中心點分佈在各單元的中心
獲得特徵圖後,須要對特徵圖進行卷積獲得檢測結果,下圖給出了一個5x5大小的特徵圖檢測過程:
Priorbox是獲得先驗框,生成規則前面已經講了。
檢測值包含兩個部分:類別置信度和邊界框位置,各採用一次3x3卷積來進行完成。
是該特徵圖所採用的先驗框數目,那麼類別置信度須要的卷積核數量爲
,而邊界框位置須要的卷積核數量爲
。因爲每一個先驗框都會預測一個邊界框,因此SSD300一共能夠預測
Conv4_3 獲得的feature map大小爲38*38:38*38*4 = 5776
Conv7 獲得的feature map大小爲19*19:19*19*6 = 2166
Conv8_2 獲得的feature map大小爲10*10:10*10*6 = 600
Conv9_2 獲得的feature map大小爲5 * 5 :5 * 5 * 6 = 150
Conv10_2獲得的feature map大小爲3 * 3 :3 * 3 * 4 = 36
Conv11_2獲得的feature map大小爲1 * 1 :1 * 1 * 4 = 4
最後結果爲:8732
個邊界框,這是一個至關龐大的數字,因此說SSD本質上是密集採樣。
在訓練過程當中,首先要肯定訓練圖片中的ground truth(真實目標)與哪一個先驗框來進行匹配,與之匹配的先驗框所對應的邊界框將負責預測它。
Yolo中,ground truth的中心落在哪一個單元格,該單元格中與其IOU最大的邊界框負責預測它。
SSD中,先驗框與ground truth的匹配原則又兩點:
一、每一個ground truth找到與其IOU最大的先驗框,互相匹配。該先驗框稱爲正樣本(先驗框對應的預測box)
如有個先驗框沒有與ground truth匹配,就只能與背景匹配,就是負樣本。(一個圖片中ground truth少,但先驗框多,這樣匹配,不少先驗框會是負樣本,正負樣本不均衡)。
二、對剩餘未匹配先驗框,若某個ground truth的IOU大於某個閾值(通常是0.5),那麼該先驗框也與這個ground truth進行匹配。
這樣ground truth可能與多個先驗框匹配
FP:負樣本 TP:正樣本
儘管一個ground truth能夠與多個先驗框匹配,可是ground truth相對於先驗框仍是太少了,因此負樣本會不少。爲保證正負樣本儘可能均衡,SSD採用了hard negative mining,先將每個物體位置上對應 predictions(default boxes)是 negative 的 boxes 進行排序,按照 default boxes 的 confidence 的大小。 選擇最高的幾個,保證最後 negatives、positives 的比例接近3:1
損失函數定義爲位置偏差(locatization loss, loc)與置信度偏差(confidence loss, conf)的加權和:
其中
是先驗框的正樣本數量。
這裏
爲一個指示參數,當
時表示第
個先驗框與第
個ground truth匹配,而且ground truth的類別爲
。
爲類別置信度預測值。
爲先驗框的所對應邊界框的位置預測值
是ground truth的位置參數
對於位置偏差,其採用Smooth L1 loss,定義以下:
因爲
的存在,因此位置偏差僅針對正樣本進行計算。值得注意的是,要先對ground truth的
進行編碼獲得
,由於預測值
也是編碼值,若設置variance_encoded_in_target=True,編碼時要加上variance:
對於置信度偏差,其採用softmax loss:
權重係數 經過交叉驗證設置爲1。
採用數據擴增(Data Augmentation)能夠提高SSD的性能,主要採用的技術有水平翻轉(horizontal flip),隨機裁剪加顏色扭曲(random crop & color distortion),隨機採集塊域(Randomly sample a patch)(獲取小目標訓練樣本),以下圖所示:
肯定預測框類別(置信度最大者)與置信度值,而且過濾掉屬於背景的預測框,過濾掉置信度閾值較低的預測框;
對留下的預測框進行編碼,獲得真實的位置參數(解碼後還須要clip,防止預測框位置超出圖片);
解碼以後,根據置信度進行降序排列,保留top-k個預測框;
進行NMS算法,過濾掉那些重疊度比較大的預測框,最後剩餘的預測框就是檢測結果了。
首先總體看一下SSD在VOC2007,VOC2012及COCO數據集上的性能,如表1所示。相比之下,SSD512的性能會更好一些。加*的表示使用了image expansion data augmentation(經過zoom out來創造小的訓練樣本)技巧來提高SSD在小目標上的檢測效果,因此性能會有所提高。
SSD與其它檢測算法的對比結果(在VOC2007數據集)如表2所示,基本能夠看到,SSD與Faster R-CNN有一樣的準確度,而且與Yolo具備一樣較快地檢測速度。
文章還對SSD的各個trick作了更爲細緻的分析,表3爲不一樣的trick組合對SSD的性能影響,從表中能夠得出以下結論:
一樣的,採用多尺度的特徵圖用於檢測也是相當重要的,這能夠從表4中看出:
一、L2 normalization
二、hard nevigating mining