參考博文:https://blog.csdn.net/a8039974/article/details/77592395 和 https://www.jianshu.com/p/5b3ca7201fae
SSD github : https://github.com/weiliu89/caffe/tree/ssd
SSD paper : https://arxiv.org/abs/1512.02325
SSD eccv2016 slide pdf : http://download.csdn.NET/download/zy1034092330/9940054
SSD pose estimation paper : http://download.csdn.net/download/zy1034092330/9940059
圖1
縮進SSD,全稱Single Shot MultiBox Detector,是Wei Liu在ECCV 2016上提出的一種目標檢測算法,截至目前是主要的檢測框架之一,相比Faster RCNN有明顯的速度優勢,相比YOLO又有明顯的mAP優勢(不過已經被CVPR 2017的YOLO9000超越)。SSD具有如下主要特點:
- 從YOLO中繼承了將detection轉化為regression的思路,同時一次即可完成網絡訓練
- 基於Faster RCNN中的anchor,提出了相似的prior box;
- 加入基於特征金字塔(Pyramidal Feature Hierarchy)的檢測方式,相當於半個FPN思路。
- SSD使用VGG16作為基礎網絡,上圖的黃色部分為在VGG16基礎網絡上填加的特征提取層。SSD與yolo不同之處是除了在最終特征圖上做目標檢測之外(conv7),還增加了5個特特征圖,對這6個特征圖進行預測。也就是說上圖的(conv4_3, conv_7)是VGG16的原有結構,(conv8_2, conv9_2, conv_10_2, pool_11)是SSD網絡增加的網絡增加的網絡,最后進入預測環節的是(conv4_3, conv_7) +(conv8_2, conv9_2, conv_10_2, pool_11)。
- 對於一張圖片,SSD網絡使用(conv8_2, conv9_2, conv_10_2, pool_11)+(conv4_3, conv_7)的特征圖進行檢測,可以增加小目標被檢測的概率。
- 在網絡的最后需要對所有的feature map 進行分類和box坐標的預測。這里一共有8732個框如下。
- 對於特征圖,特征圖的每個點上面會有預測k個box坐標和k個分類值。對於一張m x n的特征圖,同一層特征圖上每個點的box數量設為為k個(同一層的box數量一樣,不在同一層的特征圖上每個點的box數量不一樣,例如38x38每個點是4個box,19x19每個點是6個box),一共有c個物體類別。則這里一張特征圖的網絡的輸出是:
m * n * k * (c+4)。
本文接下來都以SSD 300為例進行分析。
1 SSD網絡結構
圖2 SSD網絡結構(和代碼貌似有點差別)
縮進上圖2是原論文中的SSD 300網絡結構圖。可以看到YOLO在卷積層后接全連接層,即檢測時只利用了最高層feature maps(包括Faster RCNN也是如此);而SSD采用了特征金字塔結構進行檢測,即檢測時利用了conv4-3,conv-7(FC7),conv6-2,conv7-2,conv8_2,conv9_2這些大小不同的feature maps,在多個feature maps上同時進行softmax分類和位置回歸,如圖3。
圖3 單層feature map預測和特征金字塔預測對比
2 Prior Box
縮進在SSD中引入了Prior Box,實際上與anchor非常類似,就是一些目標的預選框,后續通過softmax分類+bounding box regression獲得真實目標的位置。SSD按照如下規則生成prior box:
- 以feature map上每個點的中點為中心(offset=0.5),生成一些列同心的prior box(然后中心點的坐標會乘以step,相當於從feature map位置映射回原圖位置)
- 正方形prior box最小邊長為
,最大邊長為:
- 每在prototxt設置一個aspect ratio,會生成2個長方形,長寬為:
和
圖4 prior box
- 而每個feature map對應prior box的min_size和max_size由以下公式決定,公式中m是使用feature map的數量(SSD 300中m=6):
第一層feature map對應的min_size=S1,max_size=S2;第二層min_size=S2,max_size=S3;其他類推。在原文中,Smin=0.2,Smax=0.9,但是在SSD 300中prior box設置並不能和paper中上述公式對應:
min_size | max_size | |
---|---|---|
conv4_3 |
30
|
60
|
fc7 |
60
|
111
|
conv6_2 |
111
|
162
|
conv7_2 |
162
|
213
|
conv8_2 |
213
|
264
|
conv9_2 |
264
|
315
|
不過依然可以看出,SSD使用低層feature map檢測小目標,使用高層feature map檢測大目標,這也應該是SSD的突出貢獻了。其中SSD 300在conv4_3生成prior box的conv4_3_norm_priorbox層prototxt定義如下:
- layer {
- name: "conv4_3_norm_mbox_priorbox"
- type: "PriorBox"
- bottom: "conv4_3_norm"
- bottom: "data"
- top: "conv4_3_norm_mbox_priorbox"
- prior_box_param {
- min_size: 30.0
- max_size: 60.0
- aspect_ratio: 2
- flip: true
- clip: false
- variance: 0.1
- variance: 0.1
- variance: 0.2
- variance: 0.2
- step: 8
- offset: 0.5
- }
- }
知道了priorbox如何產生,接下來分析prior box如何使用。這里以conv4_3為例進行分析。
圖5
從圖5可以看到,在conv4_3 feature map網絡pipeline分為了3條線路:
- 經過一次batch norm+一次卷積后,生成了[1, num_class*num_priorbox, layer_height, layer_width]大小的feature用於softmax分類目標和非目標(其中num_class是目標類別,SSD 300中num_class = 21)
- 經過一次batch norm+一次卷積后,生成了[1, 4*num_priorbox, layer_height, layer_width]大小的feature用於bounding box regression(即每個點一組[dxmin,dymin,dxmax,dymax],參考Faster RCNN 2.5節)
- 生成了[1, 2, 4*num_priorbox]大小的prior box blob,其中2個channel分別存儲prior box的4個點坐標和對應的4個variance
縮進后續通過softmax分類+bounding box regression即可從priox box中預測到目標,熟悉Faster RCNN的讀者應該對上述過程應該並不陌生。其實pribox box的與Faster RCNN中的anchor非常類似,都是目標的預設框,沒有本質的差異。區別是每個位置的prior box一般是4~6個,少於Faster RCNN默認的9個anchor;同時prior box是設置在不同尺度的feature maps上的,而且大小不同。
縮進還有一個細節就是上面prototxt中的4個variance,這實際上是一種bounding regression中的權重。在圖4線路(2)中,網絡輸出[dxmin,dymin,dxmax,dymax],即對應下面代碼中bbox;然后利用如下方法進行針對prior box的位置回歸:
- decode_bbox->set_xmin(
- prior_bbox.xmin() + prior_variance[0] * bbox.xmin() * prior_width);
- decode_bbox->set_ymin(
- prior_bbox.ymin() + prior_variance[1] * bbox.ymin() * prior_height);
- decode_bbox->set_xmax(
- prior_bbox.xmax() + prior_variance[2] * bbox.xmax() * prior_width);
- decode_bbox->set_ymax(
- prior_bbox.ymax() + prior_variance[3] * bbox.ymax() * prior_height);
上述代碼可以在SSD box_utils.cpp的void DecodeBBox()函數見到。
3 Permute,Flatten And Concat Layers
圖6
縮進上一節以conv4_3 feature map分析了如何檢測到目標的真實位置,但是SSD 300是使用包括conv4_3在內的共計6個feature maps一同檢測出最終目標的。在網絡運行的時候顯然不能像圖6一樣:一個feature map單獨計算一次softmax socre+box regression(雖然原理如此,但是不能如此實現)。那么多個feature maps如何協同工作?這時候就要用到Permute,Flatten和Concat這3種層了。其中conv4_3_norm_conf_perm的prototxt定義如下:
- layer {
- name: "conv4_3_norm_mbox_conf_perm"
- type: "Permute"
- bottom: "conv4_3_norm_mbox_conf"
- top: "conv4_3_norm_mbox_conf_perm"
- permute_param {
- order: 0
- order: 2
- order: 3
- order: 1
- }
- }
Permute是SSD中自帶的層,上面conv4_3_norm_mbox_conf_perm的的定義。Permute相當於交換caffe blob中的數據維度。在正常情況下caffe blob的順序為:
bottom blob = [batch_num, channel, height, width]
經過conv4_3_norm_mbox_conf_perm后的caffe blob為:
top blob = [batch_num, height, width, channel]
而Flattlen和Concat層都是caffe自帶層,請參照caffe official documentation理解。
圖7 SSD中部分層caffe blob shape變化
縮進那么接下來以conv4_3和fc7為例分析SSD是如何將不同size的feature map組合在一起進行prediction。圖7展示了conv4_3和fc7合並在一起的過程中caffe blob shape變化(其他層類似,考慮到圖片大小沒有畫出來,請腦補)。
- 對於conv4_3 feature map,conv4_3_norm_priorbox(priorbox層)設置了每個點共有4個prior box。由於SSD 300共有21個分類,所以conv4_3_norm_mbox_conf的channel值為num_priorbox * num_class = 4 * 21 = 84;而每個prior box都要回歸出4個位置變換量,所以conv4_3_norm_mbox_loc的caffe blob channel值為4 * 4 = 16。
- fc7每個點有6個prior box,其他feature map同理。
- 經過一系列圖7展示的caffe blob shape變化后,最后拼接成mbox_conf和mbox_loc。而mbox_conf后接reshape,再進行softmax(為何在softmax前進行reshape,Faster RCNN有提及)。
- 最后這些值輸出detection_out_layer,獲得檢測結果
4 SSD網絡結構優劣分析
縮進SSD算法的優點應該很明顯:運行速度可以和YOLO媲美,檢測精度可以和Faster RCNN媲美。除此之外,還有一些雞毛蒜皮的優點,不解釋了。這里談談缺點:
- 需要人工設置prior box的min_size,max_size和aspect_ratio值。網絡中prior box的基礎大小和形狀不能直接通過學習獲得,而是需要手工設置。而網絡中每一層feature使用的prior box大小和形狀恰好都不一樣,導致調試過程非常依賴經驗。
- 雖然采用了pyramdial feature hierarchy的思路,但是對小目標的recall依然一般,並沒有達到碾壓Faster RCNN的級別。作者認為,這是由於SSD使用conv4_3低級feature去檢測小目標,而低級特征卷積層數少,存在特征提取不充分的問題。
5 SSD訓練過程
縮進對於SSD,雖然paper中指出采用了所謂的“multibox loss”,但是依然可以清晰看到SSD loss分為了confidence loss和location loss兩部分,其中N是match到GT(Ground Truth)的prior box數量;而α參數用於調整confidence loss和location loss之間的比例,默認α=1。SSD中的confidence loss是典型的softmax loss:
其中代表第i個prior box匹配到了第j個class為p類別的GT box;而location loss是典型的smooth L1 loss:
Matching strategy:
縮進在訓練時,groundtruth boxes 與 default boxes(就是prior boxes) 按照如下方式進行配對:
- 首先,尋找與每一個ground truth box有最大的jaccard overlap的default box,這樣就能保證每一個groundtruth box與唯一的一個default box對應起來(所謂的jaccard overlap就是IoU,如圖8)。
- SSD之后又將剩余還沒有配對的default box與任意一個groundtruth box嘗試配對,只要兩者之間的jaccard overlap大於閾值,就認為match(SSD 300 閾值為0.5)。
- 顯然配對到GT的default box就是positive,沒有配對到GT的default box就是negative。
圖8 jaccard overlap
- 所以SSD在訓練時會依據confidience score排序default box,挑選其中confidience高的box進行訓練,控制positive:negative=1:3
Data augmentation:
縮進數據增廣,即每一張訓練圖像,隨機的進行如下幾種選擇:
- 使用原始的圖像
- 采樣一個 patch,與物體之間最小的 jaccard overlap 為:0.1,0.3,0.5,0.7 或 0.9
- 隨機的采樣一個 patch
其實Matching strategy,Hard negative mining,Data augmentation,都是為了加快網絡收斂而設計的。尤其是Data augmentation,翻來覆去的randomly crop,保證每一個prior box都獲得充分訓練而已。不過當數據達到一定量的時候,不建議再進行Data augmentation,畢竟“真”的數據比“假”數據還是要好很多。