【深度學習】Mobilenet-SSD實現步驟

轉自:http://blog.csdn.net/Jesse_Mx/article/details/78680055

牆裂推薦,自己就不寫了,轉載一下~

mobilenet 也算是提出有一段時間了,網上也不乏各種實現版本,其中,谷歌已經開源了Tensorflow的全部代碼;

單純的Mobilenet分類不是關注重點,如何將其應用到目標檢測網絡纔是關鍵,目前基本看好的思路就是Mobilenet+SSD,github上已經有至少如下項目涉及到這方面:

https://github.com/chuanqi305/MobileNet-SSD

https://github.com/zeusees/SSD_License_Plate_Detection

https://github.com/canteen-man/MobileNet-SSD-Focal-loss

https://github.com/cooliscool/LISA-on-SSD-mobilenet

https://github.com/FreeApe/VGG-or-MobileNet-SSD

Mobilenet的速度是很快的,如果配上Depthwise layer,在TitanX應該能達到150fps,如果能將檢測精度提升到70%以上,將會是一個很好的檢測網絡。

實現方案一

項目地址:MobileNet-SSD

chuanqi大神在Caffe平臺上初步實現了Mobilenet-SSD

模型分析

通過分析Mobilenet的模型結構MobileNet-SSD的模型結構, 可以看出,conv13是骨幹網絡的最後一層,作者仿照VGG-SSD的結構,在Mobilenet的conv13後面添加了8個卷積層,然後總共抽取6層用作檢測,貌似沒有使用分辨率爲38*38的層,可能是位置太靠前了吧。

模型運行

這個項目既然叫MobileNet-SSD,那首先要求能正常運行基礎版本的SSD,這方面的博客教程這是不少

克隆項目:

$ git clone https://github.com/chuanqi305/MobileNet-SSD.git

然後可以在自己的目錄(我是用的是/home目錄)下得到MobileNet-SSD文件夾,其中重要文件簡介如下:

  • template 存放4個網絡定義的公用模板,可以由gen.py腳本修改並生成
  • MobileNetSSD_deploy.prototxt 運行網絡定義文件
  • solver_train.prototxt 網絡訓練超參數定義文件
  • solver_test.prototxt 網絡測試超參數定義文件
  • train.sh 網絡訓練腳本
  • test.sh 網絡測試腳本
  • gen_model.sh 生成自定義網絡腳本(調用template文件夾內容)
  • gen.py 生成公用模板腳本(暫不用)
  • demo.py 實際檢測腳本(圖片存於images文件夾)
  • merge_bn.py 合併bn層腳本,用於生成最終的caffemodel

接下來下載已經訓練好的caffemodel放入項目文件夾:Google Drive | 百度雲 
最後打開demo.py腳本,根據個人情況修改以下路徑:


caffe_root = '/home/yaochuanqi/ssd/caffe/'

net_file= 'MobileNetSSD_deploy.prototxt'  

caffe_model='MobileNetSSD_deploy.caffemodel'  

test_dir = "images"

 

然後運行demo.py腳本,就能看到檢測結果了,效果尚可,隨便貼兩張圖:

這裏寫圖片描述

這裏寫圖片描述

模型訓練

我們也可以用自己的數據集來訓練這個MobileNet-SSD模型,訓練步驟簡要記錄如下:

1.建立數據集軟連接 
我們需要提前建立好適用於SSD訓練的數據集(VOC格式),比如博主所用的是KITTI數據集,製作方法可在往期博文中找到,最終需要生成訓練驗證集和測試集的lmdb文件,然後建立軟連接,類似於一個快捷方式,可以簡化命令和節省空間。


$ cd ~/MobileNet-SSD

$ ln ‐s /home/its/data/KITTIdevkit/KITTI/lmdb/KITTI_trainval_lmdb trainval_lmdb

$ ln ‐s /home/its/data/KITTIdevkit/KITTI/lmdb/KITTI_test_lmdb test_lmdb

執行完命令,就能在項目文件夾下看到trainval_lmdb和test_lmdb軟連接。

2.創建labelmap.prototxt文件 
該文件用於定義訓練樣本的類別,置於項目文件夾下,其內容如下:


item {

  name: "none_of_the_above"

  label: 0

  display_name: "background"

  }

  item {

  name: "Car"

  label: 1

  display_name: "Car"

  }

  item {

  name: "Pedestrian"

  label: 2

  display_name: "Pedestrian"

  }

  item {

  name: "Cyclist"

  label: 3

  display_name: "Cyclist"

  }
  1.  

3.運行gen_model.sh腳本 
由於VOC數據集是21類(加上背景),而這裏只有4類,因此,我們需要重新生成訓練、測試和運行網絡文件,這裏就要用到gen_model.sh腳本,它會調用template文件夾中的模板,按照我們指定的參數,生成所需的文。這個腳本的用法如下:


usage: ./gen_model.sh CLASSNUM

        for voc the classnum is 21

只有一個類別數量的參數,因此我們執行命令如下:

./gen_model.sh 4

執行之後,得到examples文件夾,裏面的3個prototxt就是從模板生成的正式網絡定義,根據作者設置,其中的deploy文件是已經合併過bn層的,需要後面配套使用。

4.修改訓練和測試超參數 
根據實際情況,修改solver_train.prototxt和solver_test.prototxt。 
其中test_iter=測試集圖片數量/batchsize;初始學習率不宜太高,否則基礎權重破壞比較嚴重;優化算法是RMSProp,可能對收斂有好處,不要改成SGD,也是爲了保護權重。

5.下載預訓練模型 
下載地址:Google Drive | 百度雲,放在項目文件夾下,這裏的預訓練模型是作者從Tensorflow那邊轉化過來的,然後經過了VOC數據集的初步調試。

6.開始訓練 
修改並運行train.sh腳本,中途可以不斷調節參數。訓練結束後,運行test.sh腳本,測試網絡的精度值。

7.合併bn層 
爲了提高模型運行速度,作者在這裏將bn層合併到了卷積層中,相當於bn的計算時間就被節省了,對檢測速度可能有小幅度的幫助,打開merge_bn.py文件,然後注意修改其中的文件路徑:

caffe_root = '/home/yaochuanqi/ssd/caffe/'
train_proto = 'MobileNetSSD_train.prototxt'
train_model = 'MobileNetSSD_train.caffemodel'  # should be your snapshot caffemodel, e.g. mobilnetnet_iter_72000.caffemodel
deploy_proto = 'MobileNetSSD_deploy.prototxt' 
save_model = 'MobileNetSSD_deploy.caffemodel'

然後運行該腳本,就可以得到最終的檢測模型,那這個模型由於合併了bn層,參數格式已經變化,就不能再用於訓練了。如果想繼續訓練,應該用合併前的。對於得到的最終模型,可用demo.py腳本查看實際檢測效果,也可以部署在其他地方。

存在的問題

本人使用擴充的KITTI數據集訓練Mobilenet-SSD,折騰了一週,精度才只有52%左右,而且訓練速度比VGG的慢一些。我感覺不應該這麼低,至少也應該有65%吧,暫時沒有找到問題的根源在哪裏,如果有同學也拿這個訓練且效果很好,請告知,不勝感激!


更新:考慮到Mobilenet特徵提取能力有限,最近試驗將分辨率提升至416*416(速度降低很少),然後使用僅含4類目標(通過腳本提取)的COCO預訓練模型,初始學習率爲0.001,根據損失值和精度調整後續學習率,迭代50000次後,目前精度提升到62.8%。

Mobilenet使用Depthwise Layer

理論上Mobilenet的運行速度應該是VGGNet的數倍,但實際運行下來並非如此,前一章中,即使是合併bn層後的MobileNet-SSD也只比VGG-SSD快那麼一點點,主要的原因是Caffe中暫時沒有實現depthwise convolution,目前都是用的group。這裏group相當於一個for循環,需要依次計算,如果能使用深度卷積,那就可以一次性計算完,節省不少時間。

經過大量實驗,終於找到能讓mobilenet加速的方法,項目地址:DepthwiseConvolution, 十分感謝該項目作者。

用上了depthwise convolution layer,對於mobilenet的提速十分明顯,可以說是立竿見影。下面簡單介紹使用方法.

添加新的深度卷積層

首先克隆項目:

$ git clone https://github.com/yonghenglh6/DepthwiseConvolution.git

注意到項目中的caffe文件夾,將其中的depthwise_conv_layer.hpp,depthwise_conv_layer.cpp和depthwise_conv_layer.cu這三個文件放到SSD(即caffe)的相應位置中,這裏的操作是從基礎卷積類中派生了深度卷積這個類,此處並不需要對caffe.proto文件進行修改。稍後,需要重新編譯Caffe,這樣才能識別新增的depthwise convolution layer。

修改deploy文件

接下來我們需要修改MobileNetSSD_deploy.prototxt,將其中所有名爲convXX/dw(XX代指數字)的type從”Convolution”替換成”DepthwiseConvolution”,總共需要替換13處,從conv1/dw到conv13/dw,然後把“engine: CAFFE”都註釋掉,這個新的網絡文件可以另存爲MobileNetSSD_deploy_depth.prototxt。在運行網絡的時候,caffemodel模型不用動,只需要指定新的prototxt文件和含有depthwise convolution layer的Caffe即可。

效果驗證

爲了驗證效果,我們使用demo.py腳本來測試網絡的平均運行時間,運行模式設置爲gpu,在demo.py文件中添加和time相關的代碼:

import time
def detect(imgfile):
    #
    #
    net.blobs['data'].data[...] = img
    start=time.time() # time begin
    out = net.forward()  
    use_time=time.time()-start # proc time  
    print("time="+str(use_time)+"s") 
    #
    #

筆記本電腦顯卡是GTX 850m,對於默認的7張檢測圖片,VGG-SSD,Mobilenet-SSD(group)和Mobilenet-SSD(depth)的平均檢測時間爲:

Model Inference time
VGG-SSD 107ms
MobileNet-SSD(group) 62ms
MobileNet-SSD(depth) 17ms

如果我們使用Caffe自帶的time工具,結果也是差不多的:


 
  1. $ cd ~/caffe

  2. $ ./build/tools/caffe time -gpu 0 -model examples/mobilenet/XXXX.prototxt

  3.  
  4. I1219 20:09:24.062338 10324 caffe.cpp:412] Average Forward pass: 109.97 ms. # VGG-SSD

  5. I1219 20:09:47.771399 10343 caffe.cpp:412] Average Forward pass: 57.4238 ms. # Mobilenet-SSD(group)

  6. I1219 20:10:25.145504 10385 caffe.cpp:412] Average Forward pass: 16.39 ms. # Mobilenet-SSD(depth)

可以看到,depthwise convolution layer是有效的,運行時間快了五六倍之多。然後,博主在Jetson TX1上也如法炮製,得到的檢測時間如下:

I1219 22:08:15.236963  2210 caffe.cpp:412] Average Forward pass: 57.3939 ms.

意味着TX1上Mobilenet-SSD能達到17幀左右,這離真正的real-time又近了一步

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章