當前位置:編程學習大全網 - 源碼下載 - MobileNet SSD V2模型的壓縮與tflite格式的轉換(補充版)

MobileNet SSD V2模型的壓縮與tflite格式的轉換(補充版)

最近項目裏需要壹個小型的目標檢測模型,SSD、YOLO等壹通模型調參試下來,直接調用TensorFlow object detect API居然效果最好,大廠的產品不得不服啊。使用mobilenet ssd v2模型,配置文件也未修改參數,訓練後的模型不光檢測效果不錯,在CPU上的運行時間也在70ms左右。之後將模型移植到安卓手機上(魅族MX4,老的不是壹點點),卡頓明顯;改用同事的華為,在麒麟960上略微流暢了壹些,但仍然不能達到實時檢測。而且訓練得到的pb模型居然有19M,實在太大了,於是又探索了壹波模型的壓縮和量化。

說到模型壓縮,最簡單粗暴的方法當然是減少卷積層數。在使用Tensorflow的API之前,我訓練過壹個SSD模型,檢測效果不錯,但耗時接近1s。為了提高檢測速度我果斷開始減少卷積層數,並做了不同層數的對比試驗。結果和原始的VGG16骨幹相比,要麽檢測效果相近,耗時也沒少多少,要麽耗時大減,但漏檢率飆升。也就是在這個情況下,我轉投了mobilenet網絡。

所以這次面臨模型壓縮時, 我沒有再嘗試這個選項(當然也有配置文件不支持刪減層數,要刪就要去改slim裏的源碼這個原因。我壹個前同事是中科院計算機博士,他的格言就是覺得源碼不好就別調用,自己寫;要調用就盡量避免改源碼,因為妳肯定沒有源碼寫得好)。這樣看下來,就只能在配置文件的範圍內自由發揮了。

首先,附上Tensorflow object detection API中支持的各大模型的配置文件地址:

models/research/object_detection/samples/configs at master · tensorflow/models · GitHub

這裏面關於mobilenet_ssd_v2的有好幾個:

我使用的是最經典的基於COCO數據集訓練的配置文件,也就是第壹個。圖裏的最後壹個也是基於COCO數據集的,不過是有量化的模型,這個文件我在後面也有用到。

打開配置文件,裏面主要分成model、train和eval三塊。在調用API訓練自己的數據時,train和eval的數據當然是要修改的:

回到model部分,在feature_extractor那裏,有壹個depth_multiplier,這個參數作為壹個因子與網絡中各層的channel數相乘,換言之,depth_multiplier越小,網絡中feature map的channel數越少,模型參數自然也就少了很多。depth_multiplier默認為1,在我的實驗裏改成了0.25,試就試壹把大的。

之前depth_multiplier為1時, 我訓練是加載了預訓練模型的,模型地址:

models/detection_model_zoo.md at master · tensorflow/models · GitHub

從圖中可以看出,mobilenet_v1的預訓練模型中有壹種0.75_depth的版本,這就是depth_multiplier取0.75時在COCO數據集上訓練出來的模型。對於mobilenet_v2,只提供了非量化版和量化版(個人覺得應該0.25、0.5、0.75這幾個常用檔都提供壹個,難道是官方不建議壓縮太多嗎。。。)

由於沒有對應的預訓練模型,所以可以選擇加載或者不加載模型。

加載模型的話,開始訓練後命令行會打印壹大堆XXX is available in checkpoint, but has an incompatible shape with model variable. This variable will not be initialized from the checkpoint. 不過這並不影響訓練,忽略就可以了。

不加載的話,就將配置文件裏fine_tune_checkpoint的那兩行註釋掉。

進入到object detection目錄,運行python object_detection/model_main.py --pipeline_config_path=xxxxxxx/ssd_mobilenet_v2_coco.config --model_dir=xxxxxxxx即可

PS:訓練過程中是不會打印訓練信息的,看命令行會以為電腦卡住了。。。直到eval才會打印出信息

PPS:可以通過TensorBoard來監聽訓練過程,判斷訓練是在正常進行還是電腦真的卡住了(這種情況可能是因為batch size和輸入圖片大小太大。默認是24和300*300,但也都可以改)

訓練完成之後,還是在object detection目錄下,運行python export_inference_graph.py,必要的參數分別是輸入的ckpt的文件地址,輸出的pb文件的文件夾以及配置文件地址。

在深度壓縮至0.25倍之後, 我的pb模型大小僅為2.2M,效果卓群。當然網絡的縮減會帶來精度的損失,我的AR和AP分別降了2個點和3個點。

Tensorflow object detection API訓練出的模型,講道理從ckpt轉成tflite只需要兩步:

第壹步,將ckpt轉成pb文件,這次使用的是python export_tflite_ssd_graph.py,操作難度不大,會得到tflite_graph.pb和tflite_graph.pbtxt兩個文件;

第二步,將pb轉為tflite文件,我搜到的方法大都是使用bazel編譯tensorflow/contirb/lite/toco下面的toca文件,但我反復嘗試,報了多種錯誤,依舊沒有成功。。。最後我在stackoverflow上搜到了壹位小哥的回復,進入tensorflow/contrib/lite/python目錄,運行python tflite_convert.py,參數設置為

--graph_def_file=XXX/tflite_graph.pb 上壹步生成的pb文件地址

--output_file=XXX/xxx.tflite 輸出的tflite文件地址

--input_arrays=normalized_input_image_tensor 輸入輸出的數組名稱對於mobilenet ssd是固定的,不用改

--output_arrays='TFLite_Detection_PostProcess','TFLite_Detection_PostProcess:1','TFLite_Detection_PostProcess:2','TFLite_Detection_PostProcess:3'

--input_shape=1,XXX,XXX,3 輸入的圖片大小,需要與配置文件中壹致

--allow_custom_ops

在將tflite模型放進手機之前,我在python裏加載tflite模型測試了壹次,流程類似加載pb模型

第壹步,導入模型

第二步,獲得輸入和輸出的tensor

第三步,讀取輸入圖像,feed給輸入tensor

可以采用PIL或cv2將圖像讀入,轉為numpy數組,然後賦值給input_data

第四步,運行模型

第五步, 獲得輸出

參考輸入tensor的表示方法,目標檢測的輸出有4個,具體的值可以通過output_details[0]['index']、output_details[1]['index']、output_details[2]['index']、output_details[3]['index']獲得

這裏有壹個我踩到的坑,驗證tflite模型時,我采用了和加載pb模型完全相同的圖片預處理步驟,輸出的結果完全不同。幾番檢查之後,發現問題出在模型轉換時。運行python tflite_convert.py時,輸入數組的名稱為normalized_input_image_tensor,而我訓練時采用的是未經normalized的數組。所以在模型轉換時,tensorflow內置了對input進行normalized的步驟。因此在調用tflite模型時,同樣需要在圖像預處理中加入這壹步。 nomlized的方法為除以128.0再減去1,保證輸入的值在[-1,1)範圍內。

  • 上一篇:Ublock源代碼
  • 下一篇:網頁源代碼內容排列
  • copyright 2024編程學習大全網