1. 程式人生 > >目標檢測SSD論文解讀

目標檢測SSD論文解讀

回到頂部

一. 演算法概述

本文提出的SSD演算法是一種直接預測目標類別和bounding box的多目標檢測演算法。與faster rcnn相比,該演算法沒有生成 proposal 的過程,這就極大提高了檢測速度。針對不同大小的目標檢測,傳統的做法是先將影象轉換成不同大小(影象金字塔),然後分別檢測,最後將結果綜合起來(NMS)。而SSD演算法則利用不同卷積層的 feature map 進行綜合也能達到同樣的效果。演算法的主網路結構是VGG16,將最後兩個全連線層改成卷積層,並隨後增加了4個卷積層來構造網路結構。對其中5種不同的卷積層的輸出(feature map)分別用兩個不同的 3×3 的卷積核進行卷積,一個輸出分類用的confidence

,每個default box 生成21個類別confidence;一個輸出迴歸用的 localization,每個 default box 生成4個座標值(x, y, w, h)。此外,這5個feature map還經過 PriorBox 層生成 prior box(生成的是座標)。上述5個feature map中每一層的default box的數量是給定的(8732個)。最後將前面三個計算結果分別合併然後傳給loss層。

回到頂部

二. Default box

文章的核心之一是作者同時採用lower和upper的feature map做檢測。如圖Fig 1 所示,這裡假定有8×8和4×4兩種不同的feature map。第一個概念是feature map cell

,feature map cell 是指feature map中每一個小格子,如圖中分別有64和16個cell。另外有一個概念:default box,是指在feature map的每個小格(cell)上都有一系列固定大小的box,如下圖有4個(下圖中的虛線框,仔細看格子的中間有比格子還小的一個box)。假設每個feature map cell有k個default box,那麼對於每個default box都需要預測c個類別score和4個offset,那麼如果一個feature map的大小是m×n,也就是有m*n個feature map cell,那麼這個feature map就一共有(c+4)*k * m*n 
個輸出。這些輸出個數的含義是:採用3×3的卷積核對該層的feature map卷積時卷積核的個數,包含兩部分(實際code是分別用不同數量的3*3卷積核對該層feature map進行卷積):數量c*k*m*n是confidence輸出,表示每個default box的confidence,也就是類別的概率;數量4*k*m*n是localization輸出,表示每個default box迴歸後的座標)。訓練中還有一個東西:prior box,是指實際中選擇的default box(每一個feature map cell 不是k個default box都取)。也就是說default box是一種概念,prior box則是實際的選取。訓練中一張完整的圖片送進網路獲得各個feature map,對於正樣本訓練來說,需要先將prior box與ground truth box做匹配,匹配成功說明這個prior box所包含的是個目標,但離完整目標的ground truth box還有段距離,訓練的目的是保證default box的分類confidence的同時將prior box儘可能迴歸到ground truth box。 舉個列子:假設一個訓練樣本中有2個ground truth box,所有的feature map中獲取的prior box一共有8732個。那個可能分別有10、20個prior box能分別與這2個ground truth box匹配上。訓練的損失包含定位損失和迴歸損失兩部分。

作者的實驗表明default box的shape數量越多,效果越好。

這裡用到的 default box 和Faster RCNN中的 anchor 很像,在Faster RCNN中 anchor 只用在最後一個卷積層,但是在本文中,default box 是應用在多個不同層的feature map上。

那麼default box的scale(大小)和aspect ratio(橫縱比)要怎麼定呢?假設我們用m個feature maps做預測,那麼對於每個featuer map而言其default box的scale是按以下公式計算的: 

 ∨” role=”presentation”>

Sk=Smin+Smax−Sminm−1(k−1),k∈[1,m]” role=”presentation”>Sk=Smin+SmaxSminm1(k1),k[1,m]Sk=Smin+Smax−Sminm−1(k−1),k∈[1,m]

這裡smin是0.2,表示最底層的scale是0.2;smax是0.9,表示最高層的scale是0.9。

至於aspect ratio,用ar” role=”presentation”>arar表示為下式:注意這裡一共有5種aspect ratio 

ar={1,2,3,1/2,1/3}” role=”presentation”>ar={1,2,3,1/2,1/3}ar={1,2,3,1/2,1/3}

因此每個default box的寬的計算公式為: 

wka=skar” role=”presentation”>wak=skarwka=skar

高的計算公式為:(很容易理解寬和高的乘積是scale的平方) 

hka=sk/ar” role=”presentation”>hak=sk/arhka=sk/ar

另外當aspect ratio為1時,作者還增加一種scale的default box: 

sk′=sksk+1” role=”presentation”>sk=sksk+1sk′=sksk+1

因此,對於每個feature map cell而言,一共有6種default box。 

可以看出這種default box在不同的feature層有不同的scale,在同一個feature層又有不同的aspect ratio,因此基本上可以覆蓋輸入影象中的各種形狀和大小的object!

(訓練自己的樣本的時候可以在FindMatch()之後檢查是否能覆蓋了所有的 ground truth box)

 原始碼中的 ssd_pascal.py 設計了上面幾個引數值,caffe 原始碼 prior_box_layer.cpp 中Forward_cpu()實現。

最後會得到(38*38*4 + 19*19*6 + 10*10*6 + 5*5*6 + 3*3*4 + 1*1*4)= 8732個prior box。

                                                               Fig.2 SSD 框架

回到頂部

三. 正負樣本

prior box和 grount truth box 按照IOU(JaccardOverlap)進行匹配,匹配成功則這個prior box就是positive example(正樣本),如果匹配不上,就是negative example(負樣本),顯然這樣產生的負樣本的數量要遠遠多於正樣本。這裡將前向loss進行排序,選擇最高的num_sel個prior box序號集合 D” role=”presentation”>DD。同時可以通過規範num_sel的數量(是正樣本數量的三倍)來控制使得最後正、負樣本的比例在 1:3 左右。

 

                                                Fig.3 positive and negtive sample VS ground_truth box

1.正樣本獲得

我們已經在圖上畫出了prior box,同時也有了ground truth,那麼下一步就是將prior box匹配到ground truth上,這是在 src/caffe/utlis/bbox_util.cpp 的 FindMatches 以及子函式MatchBBox函式裡完成的。值得注意的是先是從groudtruth box出發給每個groudtruth box找到了最匹配的prior box放入候選正樣本集,然後再從prior box出發為prior box集中尋找與groundtruth box滿足IOU>0.5” role=”presentation”>IOU>0.5IOU>0.5的一個IOU最大的prior box(如果有的話)放入候選正樣本集,這樣顯然就增大了候選正樣本集的數量。

2.負樣本獲得

在生成一系列的 prior boxes 之後,會產生很多個符合 ground truth box 的 positive boxes(候選正樣本集),但同時,不符合 ground truth boxes 也很多,而且這個 negative boxes(候選負樣本集),遠多於 positive boxes。這會造成 negative boxes、positive boxes 之間的不均衡。訓練時難以收斂。

因此,本文采取,先將每一個物體位置上對應 predictions(prior boxes)loss 進行排序。 對於候選正樣本集:選擇最高的幾個prior box與正樣本集匹配(box索引同時存在於這兩個集合裡則匹配成功),匹配不成功則刪除這個正樣本(因為這個正樣本不在難例裡已經很接近ground truth box了,不需要再訓練了);對於候選負樣本集:選擇最高的幾個prior box與候選負樣本集匹配,匹配成功則作為負樣本。這就是一個難例挖掘的過程,舉個例子,假設在這8732個prior box裡,經過FindMatches後得到候選正樣本P” role=”presentation”>PP個候選負樣本作為負樣本。SSD演算法中通過這種方式來保證 positives、negatives 的比例。實際程式碼中有三種負樣本挖掘方式:

如果選擇HARD_EXAMPLE方式(源於論文Training Region-based Object Detectors with Online Hard Example Mining),則預設M=64” role=”presentation”>M=64M=64的時候,就是論文中的正負樣本比例1:3了。

enum MultiBoxLossParameter_MiningType {
  MultiBoxLossParameter_MiningType_NONE = 0,
  MultiBoxLossParameter_MiningType_MAX_NEGATIVE = 1,
  MultiBoxLossParameter_MiningType_HARD_EXAMPLE = 2
};

3.Data augmentation

本文同時對訓練資料做了 data augmentation,資料增廣。

每一張訓練影象,隨機的進行如下幾種選擇:

  • 使用原始的影象
  • 隨機取樣多個 patch(CropImage),與物體之間最小的 jaccard overlap 為:0.1,0.3,0.5,0.7 與 0.9

取樣的 patch 是原始影象大小比例是 [0.31.0],aspect ratio 在 0.5 或 2。

當 groundtruth box 的 中心(center)在取樣的 patch 中且在取樣的 patch中 groundtruth box面積大於0時,我們保留CropImage。

在這些取樣步驟之後,每一個取樣的 patch 被 resize 到固定的大小,並且以 0.5 的概率隨機的 水平翻轉(horizontally flipped,翻轉不翻轉看prototxt,預設不翻轉)

這樣一個樣本被諸多batch_sampler取樣器取樣後會生成多個候選樣本,然後從中隨機選一個樣本送人網路訓練。

回到頂部

四. 網路結構

SSD的結構在VGG16網路的基礎上進行修改,訓練時同樣為conv1_1,conv1_2,conv2_1,conv2_2,conv3_1,conv3_2,conv3_3,conv4_1,conv4_2,conv4_3,conv5_1,conv5_2,conv5_3(512),fc6經過3*3*1024的卷積(原來VGG16中的fc6是全連線層,這裡變成卷積層,下面的fc7層同理),fc7經過1*1*1024的卷積,conv6_1,conv6_2(對應上圖的conv8_2),conv7_1,conv7_2,conv,8_1,conv8_2,conv9_1,conv9_2,loss。然後一方面:針對conv4_3(4),fc7(6),conv6_2(6),conv7_2(6),conv8_2(4),conv9_2(4)(括號裡數字是每一層選取的default box種類)中的每一個再分別採用兩個3*3大小的卷積核進行卷積,這兩個卷積核是並列的(括號裡的數字代表prior box的數量,可以參考Caffe程式碼,所以上圖中SSD結構的倒數第二列的數字8732表示的是所有prior box的數量,是這麼來的38*38*4+19*19*6+10*10*6+5*5*6+3*3*4+1*1*4=8732),這兩個3*3的卷積核一個是用來做localization的(迴歸用,如果prior box是6個,那麼就有6*4=24個這樣的卷積核,卷積後map的大小和卷積前一樣,因為pad=1,下同),另一個是用來做confidence的(分類用,如果prior box是6個,VOC的object類別有20個,那麼就有6*(20+1)=126個這樣的卷積核)。如下圖是conv6_2的localizaiton的3*3卷積核操作,卷積核個數是24(6*4=24,由於pad=1,所以卷積結果的map大小不變,下同):這裡的permute層就是交換的作用,比如你卷積後的維度是32×24×19×19,那麼經過交換層後就變成32×19×19×24,順序變了而已。而flatten層的作用就是將32×19×19×24變成32*8664,32是batchsize的大小。另一方面結合conv4_3(4),fc7(6),conv6_2(6),conv7_2(6),conv8_2(4),conv9_2(4)中的每一個和資料層(ground truth boxes)經過priorBox層生成prior box。

經過上述兩個操作後,對每一層feature的處理就結束了。對前面所列的5個卷積層輸出都執行上述的操作後,就將得到的結果合併:採用Concat,類似googleNet的Inception操作,是通道合併而不是數值相加。 

                                                           Fig.5 SSD 流程

損失函式方面:和Faster RCNN的基本一樣,由分類和迴歸兩部分組成,可以參考Faster RCNN,這裡不細講。總之,迴歸部分的loss是希望預測的box和prior box的差距儘可能跟ground truth和prior box的差距接近,這樣預測的box就能儘量和ground truth一樣。

上面得到的8732個目標框經過Jaccard Overlap篩選剩下幾個了;其中不滿足的框標記為負數,其餘留下的標為正數框。緊隨其後:

 

訓練過程中的 prior boxes 和 ground truth boxes 的匹配,基本思路是:讓每一個 prior box 迴歸並且到 ground truth box,這個過程的調控我們需要損失層的幫助,他會計算真實值和預測值之間的誤差,從而指導學習的走向。

SSD 訓練的目標函式(training objective)源自於 MultiBox 的目標函式,但是本文將其拓展,使其可以處理多個目標類別。具體過程是我們會讓每一個 prior box 經過Jaccard係數計算和真實框的相似度,閾值只有大於 0.5 的才可以列為候選名單;假設選擇出來的是N個匹配度高於百分之五十的框吧,我們令 表示第 i 個預設框,j 表示第 j 個真實框,p表示第p個類。那麼xijp” role=”presentation”>xpijxijp。總的目標損失函式(objective loss function)就由 localization loss(loc) 與 confidence loss(conf) 的加權求和:

  • N 是與 ground truth box 相匹配的 prior boxes 個數
  • localization loss(loc) 是 Fast R-CNN 中 Smooth L1 Loss,用在 predict box(l) 與 ground truth box(g) 引數(即中心座標位置,width、height)中,迴歸 bounding boxes 的中心位置,
    以及 width、height
  • confidence loss(conf) 是 Softmax Loss,輸入為每一類的置信度 c
  • 權重項 α,可在protxt中設定 loc_weight,預設設定為 1
回到頂部

五.使用注意

1. 使用batch_sampler做data argument時要注意是否crop的樣本只包含目標很小一部分。

2.檢查對於你的樣本來說迴歸和分類問題哪個更難,以此調整multibox_loss_param中loc_weight進行訓練。

3.正負樣本比例,HARD_EXAMPLE方式預設只取64個最高predictions loss來從中尋找負樣本,檢查你的樣本集中正負樣本比例是否合適。