最近領(lǐng)導(dǎo)考慮到生產(chǎn)成本的問題强法,想要在CPU上運行神經(jīng)網(wǎng)絡(luò),于是研究了一陣Intel推出的OpenVINO工具包。下面主要是介紹在Ubuntu16.04上使用OpenVINO配置TensorFlow模型。
OpenVINO深度學(xué)習(xí)部署工具套件
OpenVINO的深度學(xué)習(xí)部署工具套件主要包括兩部分吵瞻,一個是模型優(yōu)化器葛菇,另外一個是推理引擎。模型優(yōu)化器是由Python編寫的橡羞,推理引擎是一套C++函數(shù)庫以及C++的類熟呛。
工作原理是對訓(xùn)練產(chǎn)生的網(wǎng)絡(luò)模型進(jìn)行優(yōu)化,優(yōu)化結(jié)果轉(zhuǎn)換成中間表示文件尉姨,得到IR文件(xml文件和bin文件)。xml文件中包含優(yōu)化以后的網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)吗冤,bin文件優(yōu)化之后的模型參數(shù)和模型變量又厉。
對于TensorFlow框架,對應(yīng)的模型為pb文件椎瘟。
環(huán)境準(zhǔn)備工作
安裝
首先覆致,官網(wǎng)上有詳細(xì)的安裝步驟:Install the Intel? Distribution of OpenVINO? toolkit for Linux*
但是,配置環(huán)境總是一件麻煩的事肺蔚,鬼知道會缺失什么依賴包煌妈,到頭來沒裝好不說,還可能影響已有的環(huán)境┑( ̄Д  ̄)┍宣羊。在即將入坑之際璧诵,我發(fā)現(xiàn)了現(xiàn)成的docker image,于是果斷選擇跳過官方指導(dǎo)仇冯。之宿。。
sudo docker run -it cortexica/openvino /bin/bash
(使用sudo docker search openvino命令可找到很多相關(guān)的images苛坚,cortexica/openvino這個image的描述里提到了Ubuntu16.04比被,所以我選擇了這一個)
配置模型優(yōu)化器
運行容器,進(jìn)入模型優(yōu)化器 prerequisites文件夾(不同images中的路徑可能有差異泼舱,但從deployment_tools這層目錄開始應(yīng)該都一樣)
cd? /opt/intel/computer_vision_sdk/deployment_tools/model_optimizer/install_prerequisites
運行腳本
sudo?./install_prerequisites.sh
運行demo驗證安裝成功
這一步我跳過了等缀,具體操作可以參考Use the Demo Scripts to Verify Your Installation
轉(zhuǎn)換TensorFlow模型
先來關(guān)注一下可以轉(zhuǎn)的層:Supported TensorFlow Layers
PS:點名RandomUniform是Not supported。娇昙。尺迂。什么仇什么怨,不支持別寫在表里好不好
其實轉(zhuǎn)的過程很簡單涯贞,就兩小步:
1辜纲、進(jìn)入model_optimizer文件夾
cd??/opt/intel/computer_vision_sdk/deployment_tools/model_optimizer
2缩麸、使用mo_tf.py腳本將pb文件轉(zhuǎn)為IR文件
python mo_tf.py --input_model <INPUT_MODEL>.pb --output_dir <OUTPUT PATH>
幻想是豐富的,現(xiàn)實是殘酷的,如果真這么簡單就能成功列吼,那還記錄個啥哦(*/ω╲*)?
對于大部分模型來說,直接運行mo_tf.py得到的應(yīng)該都是各種各樣的ERROR较沪,下面正文正式開始
使用轉(zhuǎn)化參數(shù)
mo_tf.py文件除了--input_model和--output_dir這個兩個參數(shù)以外逻翁,還有一大波:
下面介紹幾個比較重要的
Mean and Scale Values
一般來說在訓(xùn)練時我們都會使用歸一化的輸入薄嫡,比如從0~255歸一化到0~1。還有在使用Image Net等公開數(shù)據(jù)集的時候颗胡,會進(jìn)行一個去均值的操作毫深。這些都屬于簡單的數(shù)據(jù)預(yù)處理,乍一看好像和網(wǎng)絡(luò)沒啥關(guān)系毒姨,但其實影響很大哑蔫,重點在于預(yù)處理部分的代碼有沒有被寫進(jìn)TensorFlow的拓?fù)浣Y(jié)構(gòu)里。
如果預(yù)處理部分被寫進(jìn)拓?fù)浣Y(jié)構(gòu)里了弧呐,這種主要就是在訓(xùn)練網(wǎng)絡(luò)時直接讀取的原始數(shù)據(jù)闸迷,然后用tf里的函數(shù)進(jìn)行預(yù)處理的情況。這種情況下得到的模型俘枫,在pb文件里會有預(yù)處理相關(guān)的node腥沽,這些node也會直接轉(zhuǎn)化到xml文件中(前提是OpenVINO支持。鸠蚪。今阳。我在預(yù)處理結(jié)中使用的tf.map_fn對多圖進(jìn)行處理就一直報錯)。
另一種情況是拓?fù)浣Y(jié)構(gòu)里沒有預(yù)處理部分茅信,舉例就是用numpy對原始數(shù)據(jù)進(jìn)行了處理盾舌,然后作為tf網(wǎng)絡(luò)的輸入,輸入到網(wǎng)絡(luò)中汹押。由于拓?fù)浣Y(jié)構(gòu)中沒有預(yù)處理部分矿筝,雖然pb轉(zhuǎn)IR的時候也可以成功,但之后推理的結(jié)果肯定是錯的棚贾。這個時候就需要用到相關(guān)參數(shù)--scale窖维、 --scale_values,、--mean_values妙痹。當(dāng)mean value和scale value被同時指定時铸史,數(shù)據(jù)先減去mean value,再除以scale value怯伊。
python mo_tf.py --input_model <model_name>.pb --scale_values [59,59,59]?--mean_values [177,177,177]
至于怎么看拓?fù)浣Y(jié)構(gòu)里有沒有預(yù)處理部分琳轿,restore pb文件打印出所有node是一種辦法,再直觀一點耿芹,使用Netron崭篡,把pb文件導(dǎo)進(jìn)去可以直接可視化網(wǎng)絡(luò)~
這一個參數(shù)其實并不影響模型轉(zhuǎn)化的成功與否,只不過沒注意的話吧秕,轉(zhuǎn)化笑嘻嘻琉闪,推理mmp。
接下來的參數(shù)會直接影響轉(zhuǎn)化的成敗砸彬。
Input Shapes
在TensorFlow中颠毙, 輸入的placeholderr的shape可以被設(shè)成None或者-1斯入。這種設(shè)置在對輸入任意尺寸圖片和調(diào)整batch size時非常方便。但遺憾的是OpenVINO不接受這么隨意的輸入蛀蜜。刻两。。
如果在pb文件中滴某,輸入沒有明確的尺寸的話磅摹,需要加入--input_shape參數(shù)指定shape,比如[1霎奢,128偏瓤,128,3]椰憋。對于batch size不定的情況,再調(diào)用mo_tf.py后面加上-b赔退。這兩個參數(shù)不能同時使用橙依。
python mo_tf.py --input_model <model_name>.pb --input_shape [1,128,128, 3]
python mo_tf.py --input_model <model_name>.pb -b 1
Is_Training
神經(jīng)網(wǎng)絡(luò)的輸入除了輸入數(shù)據(jù),一般還會有一個區(qū)分train和valid(test)狀態(tài)的is_training硕旗,用來控制batch norm和dropout的狀態(tài)窗骑。這里也有兩種情況:
1、train和valid是兩份代碼漆枚,這種情況下创译,is_training在各自的代碼里是True和False的定值,并不會再程序運行中切換墙基,此時的pb文件應(yīng)該固定的是valid代碼中狗的graph软族,再pb轉(zhuǎn)IR的過程中也無需多加參數(shù);
2残制、在train的過程中同時進(jìn)行valid立砸,此時is_training是一個placeholder,會在train時傳入True初茶,再valid時傳入False颗祝,在pb文件中也會存在這個node,此時就需要使用參數(shù)--freeze_placeholder_with_value恼布,將is_training(node的名字以自己網(wǎng)絡(luò)中的為準(zhǔn))的值定為False螺戳。
python mo_tf.py --input_model <model_name>.pb --freeze_placeholder_with_value “is_training->False"
Tensorflow模型特有的參數(shù)
--tensorflow_use_custom_operations_config
這個參數(shù)我沒有用到,主要是使用TensorFlow Object Detection API中的模型時會用到折汞,需要傳入相應(yīng)的json配置文件倔幼。網(wǎng)上很多在轉(zhuǎn)SSD、Faster RCNN字支、YOLO等模型發(fā)生錯誤時凤藏,使用這個參數(shù)導(dǎo)入配置文件后都成功了奸忽。
--disable_nhwc_to_nchw
這個參數(shù)主要是轉(zhuǎn)換輸入維度的,NHWC和NCHW揖庄,默認(rèn)會從NHWC轉(zhuǎn)為NCHW栗菜。
實驗結(jié)果
我自己轉(zhuǎn)換了一個4分類模型,轉(zhuǎn)好后的IR文件存在/opt/intel/computer_vision_sdk/deployment_tools/model_optimizer/model路徑下
進(jìn)入推理引擎文件夾
cd /opt/intel/computer_vision_sdk/deployment_tools/inference_engine/samples/build/intel64/Release
進(jìn)行推理
./classification_sample -d CPU -i <TEST_IMAGE_PATH> -m <XML_PATH>
在i7-8700KCPU3.70GHz硬件條件下蹄梢,分類50張圖片疙筹,
直接使用CPU前傳pb文件耗時903.15 ms,使用OpenVINO引推理引擎耗時176.72 ms
總結(jié):加速效果還是明顯的禁炒,但使用自己的模型轉(zhuǎn)IR文件還是很復(fù)雜的而咆,自定義層的轉(zhuǎn)化還需要多多研究~
參考
Intel OpenVINO配置和使用 - James的博客 - CSDN博客
Using the Model Optimizer to Convert TensorFlow* Models | Intel? Software