主流的算法主要分為兩個類型:
(1)tow-stage
R-CNN系列算法,其主要思路是先通過啟發式方法(selective search)或者CNN網絡(RPN)產生一些列稀疏的候選框,然后對這些候選框進行分類和回歸。two-stage方法的優勢是准確度高。
(2)one-stage
如YOLO和SSD,主要思路是均勻的在圖片的不同位置進行密集抽樣,抽樣時可以采用不同尺度和長寬比,然后利用CNN提取特征后直接進行分類和回歸,整個過程只需要一部,所以其優勢是速度快。
均勻的密集采樣的一個重要缺點是訓練比較困難,這主要是因為正樣本與負樣本極其不平衡,導致模型准確度稍低,不同算法的性能如圖:
SSD英文名是(Single Shot MultiBox Detector),single shot指的是SSD算法屬於one-stage方法,MultiBox說明SSD是多框預測。
上圖可以看出SSD在准確度和速度(除了SSD512)上都比YOLO要好很多。
下圖是不同算法的基本框架圖,對於Faster R-CNN,其先通過CNN得到候選框,然后再進行分類和回歸,而Yolo與SSD可以一步到位完成檢測。相比於YOLO,SSD采用CNN來直接進行檢測,而不是像YOLO那樣在全連接層之后再做檢測。
其實采用卷積直接做檢測只是SSD相比於YOLO的其中一個不同點,另外還有兩個重要的改變,一是SSD提取不同尺度的特征圖來做檢測,大尺度特征圖(較靠前的特征圖)用來檢測小物體,小尺度特征圖(較靠后的特征圖,感受野大)用來檢測大物體;二是SSD采用了不同尺度和長寬比的先驗框(Prior boxes, Default boxes,在Faster R-CNN中叫做錨,Anchors)。Yolo算法的缺點是難以檢測小目標,而且定位不准,但是這幾點重要的改進使得SSD在一定程度上克服這些缺點。
設計理念
SSD和YOLO都是采用一個CNN網絡來進行檢測,但是卻采用了多尺度的特征圖,其基本架構如下圖,下面將SSD核心設計理念總結為以下三點:
(1)采用多尺度特征圖用於檢測
所謂多尺度采用大小不同的特征圖,CNN網絡一般前面的特征圖比較大,后面會逐漸采用stride=2的卷積或者pool來降低特征圖大小,下圖所示,一個比較大的特征圖和一個比較小的特征圖,他們都用來做檢測。這樣做的好處是比較大的特征圖用來檢測相對較小的目標,而小的特征圖負責檢測大目標,8x8的特征圖可以划分更多的單元,但是其每個單元的default box尺度比較小。
(2)采用卷積進行檢測
與Yolo最后采用全連接層不同,SSD直接采用卷積對不同的特征圖來進行提取檢測結果。對於形狀為的特征圖,只需要采用
這樣比較小的卷積核得到檢測值。
(3)設置先驗框default boxes
在YOLO中,每個單元預測多個邊界框,但是其都是相對這個單元本身(正方塊),但是真實目標的形狀是多變的,Yolo需要在訓練過程中自適應目標的形狀。而SSD借鑒了Faster R-CNN中anchor的理念,每個單元設置尺度或者長寬比不同的default boxes,預測的邊界框(bounding boxes)是以這些先驗框為基准的,在一定程度上減少訓練難度。
一般情況下,每個單元會設置多個default boxes,其尺度和長寬比存在差異,如下圖所示,可以看到每個單元使用了4個不同的default boxes,圖片中貓和狗分別采用最適合它們形狀的先驗框來進行訓練,后面會詳細講解訓練過程中的先驗框匹配原則。
SSD的檢測值也與YOLO不太一樣,對於每個單元cell的每個先驗框default box,其都輸出一套獨立的檢測值,對於一個bouding box,主要分為兩個部分:
- 第一個部分是各個類別的置信度或者評分
- 值得注意的是SSD將背景也當做了一個特殊的類別,如果檢測目標共有c個類別,SSD其實需要預測c+1個置信度值,其中第一個置信度是不含目標或者屬於背景的評分。后面當我們說c個類別置信度時,請記住里面包含背景那個特殊的類別,即真實的檢測類別只有c-1個。
- 在預測過程中,置信度最高的那個類別就是邊界框所屬的類別。特別的,當第一個置信度最高時,表示邊界框中並不包含目標。
- 第二個部分就是邊界框的location,包含4個值
,分別表示邊界框的中心坐標以及寬高。但是真實預測其實只是預測邊界框相對於先驗框的轉換值(offset)。
- 先驗框(anchor)位置用
表示,其對應預測的邊界框用
表示,那么邊界框的預測值l其實是b相對於d的轉換值:
-
-
- 先驗框(anchor)位置用
習慣上,我們稱上面這個過程為邊界框的編碼(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本質上是密集采樣。
訓練過程
(1)先驗框匹配
在訓練過程中,首先要確定訓練圖片中的ground truth(真實目標)與哪個先驗框來進行匹配,與之匹配的先驗框所對應的邊界框將負責預測它。
Yolo中,ground truth的中心落在哪個單元格,該單元格中與其IOU最大的邊界框負責預測它。
SSD中,先驗框與ground truth的匹配原則又兩點:
1、每個ground truth找到與其IOU最大的先驗框,互相匹配。該先驗框稱為正樣本(先驗框對應的預測box)
若有個先驗框沒有與ground truth匹配,就只能與背景匹配,就是負樣本。(一個圖片中ground truth少,但先驗框多,這樣匹配,很多先驗框會是負樣本,正負樣本不均衡)。
2、對剩余未匹配先驗框,若某個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
(2)損失函數
損失函數定義為位置誤差(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。
(3)數據擴增
采用數據擴增(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的性能影響,從表中可以得出如下結論:
- 數據擴增技術很重要,對於mAP的提升很大;
- 使用不同長寬比的先驗框可以得到更好的結果;
同樣的,采用多尺度的特征圖用於檢測也是至關重要的,這可以從表4中看出:
補充
1、L2 normalization
2、hard nevigating mining