1. 程式人生 > >SSD演算法詳解

SSD演算法詳解

SSD目標檢測

SSD目標檢測

白裳丶

白裳丶

為啥你們只收藏不點贊?

161 人讚了該文章

SSD,全稱Single Shot MultiBox Detector,是Wei Liu在ECCV 2016上提出的一種目標檢測演算法,截至目前是主要的檢測框架之一,相比Faster RCNN有明顯的速度優勢,相比YOLO又有明顯的mAP優勢(不過已經被CVPR 2017的YOLO9000超越)。

圖1 速度對比

SSD具有如下主要特點:

  • 從YOLO中繼承了將detection轉化為regression的思路,一次完成目標定位與分類
  • 基於Faster RCNN中的Anchor,提出了相似的Prior box;
  • 加入基於特徵金字塔(Pyramidal Feature Hierarchy)的檢測方式,即在不同感受野的feature map上預測目標

本文接下來都以SSD 300為例進行分析。

1 SSD300網路結構

圖2 SSD300/YOLO網路結構對比

上圖2是原論文中的SSD300與YOLO網路結構圖。位什麼要把SSD與YOLO對比呢?因為截止到目前目標檢測分為了2種主流框架:

  • Two stages:以Faster RCNN為代表,即RPN網路先生成proposals目標定位,再對proposals進行classification+bounding box regression完成目標分類。
  • Single shot:以YOLO/SSD為代表,一次性完成classification+bounding box regression。

那麼來看同為Single shot方式的SSD/YOLO區別:

  • YOLO在卷積層後接全連線層,即檢測時只利用了最高層Feature maps(包括Faster RCNN也是如此)
  • SSD採用金字塔結構,即利用了conv4-3/conv-7/conv6-2/conv7-2/conv8_2/conv9_2這些大小不同的feature maps,在多個feature maps上同時進行softmax分類和位置迴歸
  • SSD還加入了Prior box

對比如圖3。

圖3 單層feature map預測和特徵金字塔預測對比

2 Prior Box

在SSD300中引入了Prior Box,實際上與Faster RCNN Anchor非常類似,就是一些目標的預選框,後續通過classification+bounding box regression獲得真實目標的位置。

SSD按照如下規則生成prior box:

  • 以feature map上每個點的中點為中心,生成一些列同心的prior box
  • 正方形prior box最小邊長為和最大邊長為:

  • 每在prototxt設定一個aspect ratio,會生成2個長方形,長寬為:

圖4 prior box

  • 而每個feature map對應prior box的min_size和max_size由以下公式決定:

s_k = s_{min} + \frac{s_{max}-s_{min}}{m-1}(k-1), \ \ k\in[1, m]

公式中的 m 是指進行預測時使用feature map的數量,如SSD300使用conv4-3等6個feature maps進行預測,所以 m=6 。同時原文設定s_{min}=0.2 ,s_{max}=0.9 。

那麼:

  • 對於conv4-3: k=1 , min\_size=s_1 *300 , max\_size=s_2*300
  • 對於conv-7:k=2 , min\_size=s_2 *300 , max\_size=s_3*300
  • ....

顯然可以用上述公式推匯出每個feature maps使用的Prior Box size。但是在SSD300中prior box設定並不能完全和上述公式對應:

不過依然可以看出:SSD使用感受野小的feature map檢測小目標,使用感受野大的feature map檢測更大目標

更具體一點,來看SSD300在conv4_3層的Prior Box設定conv4_3生成prior box的conv4_3_norm_priorbox層prototxt定義如下,可以清晰的看到 min\_size 和 max\_size 以及 aspect\_ratio 等值。

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網路分為了3條線路:

  1. 經過一次batch norm+一次卷積後,生成了[1, num_class*num_priorbox, layer_height, layer_width]大小的feature用於softmax分類目標和非目標(其中num_class是目標類別,SSD300中num_class = 21,即20個類別+1個背景)
  2. 經過一次batch norm+一次卷積後,生成了[1, 4*num_priorbox, layer_height, layer_width]大小的feature用於bounding box regression(即每個點一組[dxmin,dymin,dxmax,dymax],參考Faster R-CNN 2.5節)
  3. 生成了[1, 2, 4*num_priorbox*layer_height*layer_width]大小的prior box blob,其中2個channel分別儲存prior box的4個點座標(x1, y1, x2, y2)和對應的4個引數variance

後續通過softmax分類判定Prior box是否包含目標,然後再通過bounding box regression即可可獲取目標的精確位置,熟悉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 SSD的資料流

對於新學習SSD的人,肯定有一個很大的困惑,就是這麼多feature maps和Prior Box,如何組合在一起進行forwards/backwards。本節專門介紹SSD的資料流動方式,也許有點難。但是隻有了解SSD的資料流動方式才能真的理解。

圖6

上一節以conv4_3 feature map分析瞭如何檢測到目標的真實位置,但是SSD 300是使用包括conv4_3在內的共計6個feature maps一同檢測出最終目標的。在網路執行的時候顯然不能像圖6一樣:一個feature map單獨計算一次multiclass 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]

圖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,獲得檢測結果

可以看到,SSD一次判斷priorbox到底是背景 or 是20種目標類別之一,相當於將Faster R-CNN的RPN與後續proposal再分類進行了整合。

圖8 SSD300

4 SSD網路結構優劣分析

SSD演算法的優點應該很明顯:執行速度可以和YOLO媲美,檢測精度可以和Faster RCNN媲美。除此之外,還有一些雞毛蒜皮的優點,不解釋了。這裡談談缺點:

  1. 需要人工設定prior box的min_size,max_size和aspect_ratio值。網路中prior box的基礎大小和形狀不能直接通過學習獲得,而是需要手工設定。而網路中每一層feature使用的prior box大小和形狀恰好都不一樣,導致除錯過程非常依賴經驗。
  2. 雖然採用了pyramdial feature hierarchy的思路,但是對小目標的recall依然一般,並沒有達到碾壓Faster RCNN的級別。作者認為,這是由於SSD使用conv4_3低階feature去檢測小目標,而低階特徵卷積層數少,存在特徵提取不充分的問題。

5 SSD訓練過程

對於SSD,雖然paper中指出採用了所謂的“multibox loss”,但是依然可以清晰看到SSD loss分為了confidence loss和location loss(bouding box regression 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,如圖9)。
  • SSD之後又將剩餘還沒有配對的default box與任意一個groundtruth box嘗試配對,只要兩者之間的jaccard overlap大於閾值,就認為match(SSD 300 閾值為0.5)。
  • 顯然配對到GT的default box就是positive,沒有配對到GT的default box就是negative。

圖9 jaccard overlap

Hard negative mining:

值得注意的是,一般情況下negative default boxes數量>>positive default boxes數量,直接訓練會導致網路過於重視負樣本,從而loss不穩定。所以需要採取:

  • 所以SSD在訓練時會依據confidience score排序default box,挑選其中confidence高的box進行訓練,控制 positive:negative=1:3

Data augmentation:

資料增廣。即對每一張image進行如下之一變換獲取一個patch進行訓練:

  • 直接使用原始的影象(即不進行變換)
  • 取樣一個patch,保證與GT之間最小的IoU為:0.1,0.3,0.5,0.7 或 0.9
  • 完全隨機的取樣一個patch

圖10 Random crop

同時在原文中還提到:

  • 取樣的patch佔原始影象大小比例在 [0.1,1] 之間
  • 取樣的patch的長寬比在 [0.5,2] 之間
  • 當 Ground truth box中心恰好在取樣的patch中時,保留整個GT box
  • 最後每個patch被resize到固定大小,並且以0.5的概率隨機的水平翻轉

最終以這些處理好的patches進行訓練。

其實Matching strategy,Hard negative mining,Data augmentation,都是為了加快網路收斂而設計的。尤其是Data augmentation,翻來覆去的randomly crop,保證每一個prior box都獲得充分訓練而已。後續有Focal loss解決這個問題。

最後多說一句,如果是新手,瞭解經典的Faster RCNN/YOLO/SSD三種演算法肯定就是入門檢測啦。