深度學習 SSD的理解和細節分析

賈瀾鵬發表於2019-05-06

之前在簡書的文章,搬遷過來 ^-^
先放大神的論文和原始碼鎮樓:

SSD Github: https://github.com/weiliu89/caffe 請選擇分支 SSD
SSD paper: arxiv.org/abs/1512.02…

對於SSD來說,最有新意的就是它的多尺度特徵,而整個程式碼中調整頻度最高的應該是它的Prior_box,我們就從這些方面來分享一下我自己的理解。

##多尺度 先說一下多尺度特徵。在之前的Faster-RCNN中,特徵向量都是從最後一層的Feature Maps上得到的,對於這種單一的特徵層而言,感受野是十分有限的,沒有完全利用好前面幾級的特徵網路。在SSD中,作者從CONV4_3開始,利用多級Feature Maps的組合作為分類和迴歸的依據,達到了論文中提到的多尺度的效果。 借用論文中的一張圖來說明,作者是拿YOLO和SSD做的對比:

1.jpg

可以看出SSD 的特徵是從不同的卷積層提取出來(上圖紅線),進行組合再進行迴歸和分類,而YOLO只有一層,在YOLO之後的版本中也借鑑了 SSD的這種多尺度的思想來提高mAp。也就是說,SSD就是Faster-RCNN和YOLO中做了一次的分類和檢測過程放在不同的影像大小上做了多次。
##Prior_box 知道了SSD的特徵是從不同尺度上提取的,那麼論文中所說的8732 BOXES又是怎麼來的呢?用下面這張表來告訴你。

name Out_size Prior_box_num Total_num
conv4-3 38x38 4 5776
fc7 19x19 6 2166
conv5-2 10x10 6 600
conv7-2 5x5 6 150
conv8-2 3x3 6 36
conv9-2 1x1 4 4
8732

和 Faster-RCNN一樣,SSD也是特徵圖上的每一個點對應一組預選框。然後每一層中每一個點對應的prior box的個數,是由PriorBox這一層的配置檔案決定的。拿conv4-3對應的priorbox來說,caffe的模型配置檔案如下:

深度學習 SSD的理解和細節分析

那麼SSD是怎麼生成對應的四個priorbox的呢? 框的生成過程大概分為下面三種方式:

  1. 先以 min_size為寬高生成一個框。

  2. 如果存在max_size則用sqrt(min_size_ * max_size_),生成一個框。

  3. 然後根據 aspect_ratio,再去生成。如上面的配置檔案,aspect_ratio=2,那麼會自動的再新增一個aspect_ratiod = 1/2,然後根據下面的計算方法:

    深度學習 SSD的理解和細節分析

    分別生成兩個框,一個對應 ar = 2 一個對應 ar= 1/2。

直觀點說,就是min_size和max_size會分別生成一個正方形的框,aspect_ratio引數會生成2個長方形的框。所以輸出框的個數 :
prior_box_num = count(min_size)*1+count(max_size)*1+count(aspect_ratio)*2。

PS: min_size是必須要有的引數,否則不會進入對應的框的生成過程。論文跟實際程式碼是有一些出入的,Git上也有人在討論這個,基本都選擇無視論文。。。

這裡還有一個比較關鍵的引數,就是step,在conv4-3中設定為8,這個又是怎麼來的呢?還是用一個表來看一下:

name Out_size Cal_scale Real_scale
conv4-3 38x38 7.8 8
fc7 19x19 15.78 16
conv5-2 10x10 30 32
conv7-2 5x5 60 64
conv8-2 3x3 100 100
conv9-2 1x1 300 300

Cal_scale = 300/out_size 實際就是 原圖與特徵圖 大小的比值,比如conv4-3 width = 38 ,輸入的大小為300,那麼scale=7.8,所以這裡設定的step=8。程式碼中實現如下:

深度學習 SSD的理解和細節分析

這一部分的計算過程可以在 prior_box_layer.cpp的Forward_cpu中看到。

##特徵的表出形式 如果你看了SSD的網路結構會發現,每一個 convXXXX_mbox_loc 或者 convXXXX_mbox_conf後面都會跟一個permute+flatten layer,如下圖:

深度學習 SSD的理解和細節分析

這是在幹什麼呢? 使用CAFFE的同學都知道 ,CAFFE的資料結構是 NCHW的形式(N:樣本個數, C:通道數,H:高,W:寬),而SSD的 XX_conf 和 XX_loc層的輸出,是用通道來儲存特徵向量的,所以這裡需要將通道數調整到最後,也就是 permute所做的事情,通過該層後,資料的順序被換成了 NHWC,再通過 flatten拉成一列。

深度學習 SSD的理解和細節分析

這裡還有還是要說一下 XX_LOC 和 XX_CONF 層的輸出通道的規則,XX_LOC層是用來回歸框的,所以需要4個座標資訊,而XX_CONF是用來做分類的,所以需要class_num個資訊,同時每個點會有多個prior_box ,我們令 K = count(prior_box),那麼相應的XX_LOC的輸出的通道個數應為4*K,而XX_CONF的輸出通道個數應為 class_num*K,作為驗證,我們還是看一下針對於VOC的模型的引數設定,

深度學習 SSD的理解和細節分析

深度學習 SSD的理解和細節分析

還是看conv4_3,這一層對應了4個prior_box ,VOC的分類個數是21(20個分類+1個背景),所以對應的conv4_3_norm_mbox_loc 的num output = 16 = 4*4 ,而 conf的 num_output = 84 = 21*4。所以,如果針對的是自己的訓練集,一定要記著修改 XX_CONF的輸出通道數。

其實簡單點理解,就是SSD的最後幾層的輸出資訊都是儲存在Channel這一維度的,而一個LOC+CONF+PRIOR的模組可以認為等效於一個 Faster-rcnn的最後的迴歸+分類過程,通過將這些子模組的特徵拼接起來,得到一組特徵向量,達到提取多尺度特徵的目的(多個F-RCNN同時工作於同一圖片的不同尺度上)。

#####再看一下為什麼一個特徵點要對應幾個prior_box。 原圖中的某一個片區域,在經過幾層的提取後,會抽象成特徵圖上的一個點,那麼多對於多個prior_box而言,他們對應的都是同一組資訊,那麼多個prior_box的意義是什麼呢?看下圖:

深度學習 SSD的理解和細節分析

該圖只是示意作用,我假設某一層的特徵輸出中的一個點,在原圖中的感受野剛好是上圖左上角的區域,可以看出卡片遮擋了筆的部分特徵(橙色和藍色的框是我標註上去的,2根藍線是示意作用,可以忽略),如果沒有多個prioro_box的時候,這種場景就無法正確分類,要麼認為是卡片,要麼認為是筆。這時候多個Prior_box的價值就來了,因為多個框都會輸出自己的座標迴歸和分類,它們會去關注自己對應的特徵,然後不同的框給出不同的分類得分,個人覺得有點類似於一個Attention的結構。

##最後還是要提一下SSD的資料增強 SSD的資料增強有很多,隨機的剪裁,放縮,亮度,飽和度的調整,等等。引數也基本是見名知意的,所以最好自己跟著程式碼看一下比較有效。如果自己需要做資料增強不妨學習一下他的用法。 這裡推薦一個 GIT: https://github.com/eric612/MobileNet-SSD-windows

這個GIT的SSD版本是可以在 WINDOWS上跑的,這樣就能用宇宙最強IDE——VS一步一步的跟著看圖片的變化了。

相關文章