【翻譯】Movidius神經運算棒_在Intel® Movidius™ NCS上部署客製化Caffe模型來進行影像分類

(Original post from Intel Movidius NCS blog: “Deploying Your Customized Caffe Models on Intel® Movidius™ Neural Compute Stick”:https://movidius.github.io/blog/deploying-custom-caffe-models/ )

作者/攝影 曾吉弘
文章分類 教學(翻譯)
時間 3小時
難度 ★★★★★
材料表
  • Raspberry Pi 3單板電腦
  • Intel Movidius神經計算棒

為什麼需要客製化模型?

Neural Compute Application Zoo (NCAppZoo) 會下載數個預先訓練好的神經網路,例如GoogLeNet、AlexNet、SqueezeNet與MobileNets⋯⋯等等。這些網路多數是根據ImageNet的資料集進行訓練,其中包含了上千個影像類別(class,也稱為category)。這些範例網路與程式,使開發者很容易評估所採用的平台,並以此建立簡易專題。不過,如果您打算對邊緣產品進行概念驗證,例如智慧型數位相機、能以手勢控制的無人機,或工業用的智慧攝影機的話,就應該需要客製化的神經網路才行。

如果今天要做的是一台放在住家門口的智慧監控攝影機,應該就不需要用到ImageNetLet上那上千個已經定義好的類別,比如「zebra」、「armadillo」或 「lionfish」。反之,您應該只需要大約15至20個類別,例如「person」、「dog」、「mailman」、「person wearing hoody」這樣就好。把資料集的類別從上千個降至20個的話,同時也大大降低所需要提取的特徵。這與您網路的複雜度直接相關,影響到其大小、訓練時間及推論時間⋯⋯等等。換言之,神經網路最佳化有以下好處:

  1. 資料集變小了,訓練網路的時間自然縮短。
    • 節省硬體的運行與訓練成本。
    • 縮短開發時間。
  2. 節省所需記憶體,進而降低硬體成本。
  3. 由於網路複雜度降低,藉此提高推論結果的向前傳遞(forward pass)速度,這樣就能讓邊緣裝置以更快速度處理攝影機影像。

本文將依序介紹如何使用客製化的資料集訓練一個預先定義好的神經網路,使用Intel® Movidius™ Neural Compute SDK (NCSDK)來剖析、修改網路,以改善執行時間,最後則是將客製化模型部署至Intel® Movidius™ 神經運算棒(NCS)上。

讓我們邊做邊學!

您會製作:

可以辨識狗與貓兩種類別的客製化GoogLeNet 深度神經網路。

您會學到:

  • 使用NCSDK中的mvNCProfile工具軟體來剖析神經網路

您會需要:


讓我們開始吧!

為了簡化,我將本文分成四大段:

  1. 訓練(Train) -選用神經網路、準備資料集及訓練。
  2. 剖析(Profile) -分析所採用神經網路的頻寬、複雜度與執行時間。
  3. 微調(Fine tune)-修改神經網路拓樸來改善執行時間
  4. 部署(Deploy)-將客製化完成的神經網路部署至可運行NCS的邊緣裝置上。

註:如果您的訓練機器與安裝NCSDK的系統並非同一台的話,請在您的訓練硬體上執行Step 1至3,並在安裝好NCSDK的系統上執行Step 2與4。

首先,請由NCAppZoo下載原始碼與說明文件,如以下指令:

mkdir -p ~/workspace
cd ~/workspace
git clone https://github.com/movidius/ncappzoo

mkdir -p ~/workspace
cd ~/workspace
git clone https://github.com/movidius/ncappzoo


1. 訓練

選用神經網路

除非您打算從頭打造一套深度神經網路,不然選用何種神經網路對於您裝置的執行效能是最關鍵的事情。以這個鮭魚種類分類器來說,您只要選擇足以處理少數幾種類別的網路拓樸即可(這樣要檢查的特徵就少多了),但系統的速度還是要夠快才能成功分類不停游來游去的魚兒。另一方面,如果是倉儲物流的存貨掃描機器人的話,這時可能需要犧牲一點速度來提高分類超大量庫存商品的正確性。

一旦選好網路之後,您就得不斷微調它直到在正確性、執行時間與功耗方面達到平衡為止。GoogLeNet是針對ImageNet 2014比賽所設計的,具備超過1000個類別,顯然用它來分類貓狗是小題大作了,但為了讓本範例盡量簡單,我們還是採用它,但會清楚說明神經網路在客製化之後對於正確性與執行時間的影響。

準備資料集

  • 從Kaggle下載zip and train1.zip,放到 ~/workspace/ncappzoo/apps/dogsvscats/data路徑下。
  • 準備資料集所需的步驟都包在Makefile中了,包括:
    • 影像預處理、調整大小、裁切與直方圖均化(histogram equalization)等等
    • 影像洗牌(shuffling)
    • 將所有影像分成訓練用與驗證用兩組
    • 對這些影像建立一個lmdb資料庫
    • 計算影像均值 – 這是資料正規化的常用深度學習技術
# The helper scripts use $CAFFE_PATH to navigate into your caffe installation directory.
export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats
make

註:請把畫面上的均值(mean)記下來,後續推論時會用到。

一切順利的話,會看到以下目錄架構:

tree ~/workspace/ncappzoo/apps/dogsvscats/data

data
├── dogsvscats-mean.binaryproto
├── dogsvscats_train_lmdb
│   ├── data.mdb
│   └── lock.mdb
├── dogsvscats_val_lmdb
│   ├── data.mdb
│   └── lock.mdb
├── test1
│   ├── cat.92.jpg
│   ├── cat.245.jpg
│   └── ...
├── test1.zip
├── train
│   ├── cat.2388.jpg
│   ├── cat.465.jpg
│   └── ...
└── train.zip

訓練

如果硬體效能夠強的話,要從頭開始訓練我們的「」資料集(25000張影像)應該不會太久,但在此要運用遷移學習(transfer learning)技術來節省開發的力氣。由於GoogLeNet是根據ImageNet資料集(包含了各種貓與狗的影像)所訓練,我們當然可以好好運用預先訓練好的GoogLeNet模型中的各個權重值。

Caffe讓我們只要在訓練指令後加入–weights 旗標就能輕鬆應用遷移學習。另外還要根據我們所採用的遷移學習類型來修改 training & solver prototxt (模型定義) 這兩個檔案。本範例選用最簡單的fixed feature extractor。

本文的dogsvscats專題github也一併提供了修改好的prototxt檔。想深入了解我改了哪些地方的話,請實際執行Caffe的範例網路檔與本專題所用網路來比較看看。

export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats
diff -u $CAFFE_PATH/models/bvlc_googlenet bvlc_googlenet/org

請用以下指令開始訓練。根據您採用的硬體,所需時間可能從喝杯飲料到睡個午覺都有可能。

# The helper scripts use $CAFFE_PATH to navigate into your Caffe installation directory.
export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats

# Download pre-trained GoogLeNet model
$CAFFE_PATH/scripts/download_model_binary.py $CAFFE_PATH/models/bvlc_googlenet

# Start training session
$CAFFE_PATH/build/tools/caffe train --solver bvlc_googlenet/org/solver.prototxt --weights $CAFFE_PATH/models/bvlc_googlenet/bvlc_googlenet.caffemodel 2>&1 | tee bvlc_googlenet/org/train.log

一切順利的話,會在dogsvscats/bvlc_googlenet/org資料夾中看到一大堆.caffemodel 與 .solverstate 檔。

註:我的模型在測試過程中收斂得不太理想,所以後來就不再從頭訓練,結果也好多了。如果您也遇到相同問題的話,只要拿掉 –weights 再重新跑一次訓練就好。如果想知道為什麼我的模型不會收斂的話,請到 Intel Movidius 開發者論壇 留言。

2. Profile

bvlc_googlenet_iter_xxxx.caffemodel包含了方才訓練好模型的各個權重。現在要看看它在Intel Movidius神經運算棒的執行效果如何。NCSDK ships with a 神經網路 profiler tool called mvNCProfile, ,它專門用來分析神經網路,並可對執行在某硬體平台上的神經網路提供逐層說明。

請在已安裝NCSDK的系統上執行以下指令,並確保NCS已經正確接上系統:

cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/org
mvNCProfile -s 12 deploy.prototxt -w bvlc_googlenet_iter_40000.caffemodel

ls -l graph
-rw-rw-r-- 1 ashwin ashwin 11972912 Dec 24 17:24 graph

 

您應該會看到各層關於頻寬、複雜度與執行時間的相關資訊。或者可透過output.gv.svg與output_report.html將這些資訊以圖形介面來呈現。

 

3. 微調

請注意Inception 4a, 4b, 4c  4d是最複雜的層,並且它們用了相當長的時間來向前傳遞。理論上來說,把這些層刪掉可以讓效能提升20~30ms,但這會影響到正確性嗎?重新用custom/deploy.prototxt 來訓練看看就知道了。

以下是我對bvlc_googlenet/org/train_val.prototxt 所作修改之圖形畫呈現。

CAFFE_PATH/python/draw_net.py 這個python程式是用於繪製網路。Netscope是另一個不錯的線上Caffe網路繪製工具。

cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/org
python $CAFFE_PATH/python/draw_net.py train_val.prototxt train_val_plot.png

cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/custom
python $CAFFE_PATH/python/draw_net.py train_val.prototxt train_val_plot.png

 

 

# The helper scripts use $CAFFE_PATH to navigate into your caffe installation directory.
export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats

# Start training session
$CAFFE_PATH/build/tools/caffe train --solver bvlc_googlenet/custom/solver.prototxt 2>&1 | tee bvlc_googlenet/custom/train.log

註:請注意,在此沒有看到 –weights旗標,代表我沒有用到遷移學習。那為什麼您會期待我這麼做呢?預先訓練好的網路,其權重會與該網路架構直接相關。由於本範例刪除了inception層,因此遷移學習的效果不會太好。

這次的訓練過程顯然會比喝杯飲料的時間久一點,耐心等一下吧。訓練好 之後,請再次執行mvNCProfile來分析客製化之後的神經網路。

cd ~/workspace/ncappzoo/apps/dogsvscats/model
mvNCProfile -s 12 dogsvscats-custom-deploy.prototxt -w dogsvscats-custom.caffemodel

ls -l graph
-rw-rw-r-- 1 ashwin ashwin 8819152 Dec 24 17:26 graph

 

看起來我們的模型與原本的GoogLeNet相比,速度快了21.26 ms,網路也小了3 MB。不過網路正確性又如何呢?現在我們要把客製化前後的訓練學習曲線畫出來。

# The helper scripts use $CAFFE_PATH to navigate into your Caffe installation directory.
export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/org

# Plot learning curve
python $CAFFE_PATH/tools/extra/plot_training_log.py 2 bvlc_googlenet_train.png train.log

接著在另一個終端機中把客製化網路的學習曲線畫出來:

# The helper scripts use $CAFFE_PATH to navigate into your Caffe installation directory.
export CAFFE_PATH=/PATH/TO/CAFFE/INSTALL_DIR
cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/custom

# Plot learning curve
python $CAFFE_PATH/tools/extra/plot_training_log.py 2 bvlc_googlenet_train.png train.log

註:graph的標籤不太好懂,因為我們期待“Test Loss”會在執行多次之後下降,不過它反而上升。這個graph實際上繪製的是loss3/top-1, 這就是您網路的正確性。更多細節請參考位於train_val.prototxt中的loss3/top-1定義。

在執行訓練過程時,我發現兩個網路在正確性差異非常小。我認為原因是來自類別數量很少導致特徵也變少的關係。類別數量增加的話應該就能看到更明顯的差異。

 

4. 部署

對於這個神經網路的效能滿意了嗎?可以準備將網路部署到像是Raspberry Pi或是MinnowBoard這樣的邊緣裝置上了。在此採用image-classifier來載入graph並對指定影像進行推論。原本的程式碼要修改一下才能運用正確的均值與比例因數(scaling factor),接著將程式碼搭配正確的graph檔之後才能測試影像。

--- a/apps/image-classifier/image-classifier.py
+++ b/apps/image-classifier/image-classifier.py
@@ -16,10 +16,10 @@ import sys

# User modifiable input parameters
NCAPPZOO_PATH           = '../..'
-GRAPH_PATH              = NCAPPZOO_PATH + '/caffe/GoogLeNet/graph'
-IMAGE_PATH              = NCAPPZOO_PATH + '/data/images/cat.jpg'
-CATEGORIES_PATH         = NCAPPZOO_PATH + '/data/ilsvrc12/synset_words.txt'
-IMAGE_MEAN              = numpy.float16( [104.00698793, 116.66876762, 122.67891434] )
+GRAPH_PATH              = NCAPPZOO_PATH + '/apps/dogsvscats/bvlc_googlenet/custom/graph'
+IMAGE_PATH              = NCAPPZOO_PATH + '/apps/dogsvscats/data/test1/173.jpg'
+CATEGORIES_PATH         = NCAPPZOO_PATH + '/apps/dogsvscats/data/categories.txt'
+IMAGE_MEAN              = numpy.float16( [106.202, 115.912, 124.449] )
IMAGE_STDDEV            = ( 1 )
IMAGE_DIM               = ( 224, 224 )

@@ -77,7 +77,7 @@ order = output.argsort()[::-1][:6]

# Get execution time
inference_time = graph.GetGraphOption( mvnc.GraphOption.TIME_TAKEN )

-for i in range( 0, 4 ):
+for i in range( 0, 2 ):
print( "Prediction for "
+ ": " + categories[order[i]]
+ " with %3.1f%% confidence"

 

修改完成之後執行image-classifier:

cd ~/workspace/ncappzoo/apps/image-classifier
python3 image-classifier.py

應該會看到以下類似訊息:

——- predictions ——–
Prediction for : Dog with 98.4% confidence in 90.46 ms
Prediction for : Cat with 1.7% confidence in 90.46 ms

 

rapid-image-classifier是一個用於測試影像分類效果的實用工具軟體,它會讀取某個資料夾(包含子資料夾)中的所有影像,並顯示推論結果。請把剛剛對image-classifier做的再做一次,最後執行程式。

cd ~/workspace/ncappzoo/apps/rapid-image-classifier
python3 rapid-image-classifier.py

應該會在terminal看到以下訊息:

Pre-processing images…
Prediction for 6325.jpg: Cat with 100.0% confidence in 90.00 ms
Prediction for 7204.jpg: Cat with 100.0% confidence in 73.67 ms
Prediction for 3384.jpg: Dog with 100.0% confidence in 73.72 ms
Prediction for 5487.jpg: Dog with 100.0% confidence in 73.27 ms
Prediction for 1185.jpg: Cat with 100.0% confidence in 73.60 ms
Prediction for 3845.jpg: Dog with 68.5% confidence in 73.29 ms

    讚!您已經成功將以Caffe為基礎的客製化深度神經網路部署在邊緣裝置上了。

註:有注意到第一個與第二個推論嗎?兩者之間的差異超過20ms。這是由於要先開啟裝置與載入graph才能首次呼叫loadTensor,因此耗時較長。

上述image-classifier與rapid-image-classifier這兩個範例使用了來自mvNCProfile的預設graph檔,但您可以改用自定義的graph檔。

cd ~/workspace/ncappzoo/apps/dogsvscats/bvlc_googlenet/org
mvNCCompile -s 12 deploy.prototxt -w bvlc_googlenet_iter_40000.caffemodel -o dogsvscats-org.graph

還可以試試

  • 運用資料增強(data augmentation)技術來提高您所用模型的正確度。.
  • GoogLeNet (本範例的客製版也算) 對於分類貓狗來說真的是小題大作;換成像是VGG 16、Resnet-18或 LeNet這類型的簡易網路試試看吧
    • 在NCSDK的release note可以找到一系列已驗證的可用網路

延伸閱讀

 

相關文章

 

2 thoughts on “【翻譯】Movidius神經運算棒_在Intel® Movidius™ NCS上部署客製化Caffe模型來進行影像分類

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *