※この記事はAE2100のUbuntu + OpenVINOコンテナ(ubuntu_openvino_2020R3.tar)を対象としています。
要約
この記事では、画像分類のディープラーニング・モデルに対してModel Optimizerを適用する方法を説明します。
また、Model Optimizerによる変換後のモデルをAE2100のUbuntu + OpenVINOコンテナへデプロイし、推論を実行します。
はじめに
OKIのAIエッジコンピュータ「AE2100」には、Intel製のディープラーニング推論用ハードウェア・アクセラレータであるMovidius Myriad X VPUが搭載されています。
またAE2100のUbuntu + OpenVINOコンテナubuntu_openvino_2020R3.tar
には、ディープラーニングの推論環境としてOpenVINOがインストールされています。
この記事ではOpenVINOのModel Optimizerを利用してディープラーニング・モデルの形式を変換し、変換後のモデルによる推論をAE2100上で実行する方法について説明します。
Model Optimizerとは
AE2100上でOpenVINOを利用した推論を実行するにあたり、モデルをIntermediate Representation (IR)という形式に変換します。
この変換を行うツールがModel Optimizerです。
Model Optimizer Developer Guide - OpenVINO™ Toolkit
例えば各種フレームワーク(TensorFlow、PyTorch、Caffe2、Chainer、MXNetなど)を使用してご自身で訓練を行ったモデルや、webから入手した訓練済みモデルを用いて推論を行うために、各種形式のモデルをIRへ変換します。
また、Model Optimizerによる変換を行う際、IRのデータ型を指定できます。
例えばMyriad X VPUは演算精度としてFP16に対応していますが、FP32には非対応です。
したがって、変換前のモデルのデータ型がFP32の場合、AE2100でMyriad X VPUを使用した推論を行うためには、IRのデータ型としてFP16を指定する必要があります。
この場合、重みやバイアスはFP32からFP16へ量子化されます。
推論実行までの手順
開発環境上でのModel Optimizerの実行からAE2100上での推論実行までの大まかな手順は、下記の通りです。
- モデルを用意する(自身でモデルを訓練する、webで公開されているモデルを取得するなど)
- Model Optimizerのパラメータを確認する
- Model Optimizerを実行してモデルをIRへ変換する
- 推論用アプリケーションを用意する
- アプリケーションとIRをAE2100のコンテナへデプロイする
- アプリケーションの実行により推論を実行する
また下図では、上記手順におけるAE2100、OpenVINO、モデルの関係を表しています。
IRを用いた推論には、OpenVINOに含まれるライブラリ群であるInference Engineを利用します。
また、Inference Engineを介してVPUなどのIntel製デバイスを利用した推論を行います。
以降は上記の手順に沿ってModel Optimizerを使用方法を説明します。
画像分類モデルへのModel Optimizer使用方法
事前準備
Ubuntu開発環境上にOpenVINOおよびModel Optimizerのインストールを行ってください。
なおAVX命令に非対応のプロセッサー上でModel Optimizerを使用したTensorFlowモデルの変換を行うと、エラー「core dumped (Illegal instruction)」 が発生します。
開発環境として、Intel製プロセッサーを用いる場合にはCore i もしくはXeon系のプロセッサーを搭載したPC等をご用意ください。
詳細は「AE2100 シリーズ SDK 取扱説明書 ―DeepLearning 編―」(版数: 1.2) p. 10をご参照ください。
モデルの用意
開発環境上でモデルを用意します。
ディープラーニング・モデルのファイル形式は、各種フレームワークで出力可能な形式が様々にあります。
このうちOpen Neural Network Exchange (ONNX)は、様々なフレームワーク間の互換性をサポートするモデル形式です。
今回はONNX Model Zooから訓練済み画像分類モデル(resnet50-v1-7.onnx
)を取得し、AE2100上で画像分類を行います。
ホームディレクトリ直下にモデルとアプリケーションの保存用ディレクトリを作成し、移動します。
また、wget
コマンドを用いてwebからモデルファイルをダウンロードし、tar
コマンドで解凍します。
# cd
# mkdir mo_classification
# cd mo_classification
# wget https://media.githubusercontent.com/media/onnx/models/master/vision/classification/resnet/model/resnet50-v1-7.onnx
上記コマンドを実行すると、モデルファイルresnet50-v1-7.onnx
が得られます。
以降ではこのresnet50-v1-7.onnx
に対してModel Optimizerを適用します。
Model Optimizerのパラメータ確認
Model Optimizerを実行する際、モデルの入出力ノードの名前や、入力の形状、入力の平均値、入力のスケール値などのパラメータを引数として指定します。
モデルの訓練をご自身で行った場合にはこれらのパラメータがわかりますが、webからモデルを入手した場合にはパラメータを調べる必要があります。
ここでは取得したモデルの入手元のドキュメントを参照し、パラメータを調べます。
models/vision/classification/resnet at master · onnx/models · GitHub
上記のドキュメントには、モデルへの入力は3チャネルRGB画像のミニバッチであり、形状は(N x 3 x H x W)であるという記載があります。
また、Nはバッチサイズ、HとWは少なくとも224です。
したがって、Model Optimizerのパラメータとしての入力の形状[1,3,224,224]が得られます。
また、上記のドキュメントには、モデルへ画像を入力する前に行う前処理についても説明があります。
具体的には、画素値の範囲を[0, 1]として画像を読み込んだ上で、RGBについて平均値[0.485, 0.456, 0.406]、標準偏差[0.229, 0.224, 0.225]の標準化を行うという記載があります。
IRへ変換後のモデルで推論を行う際にも、モデルへ前述の通りの標準化を行うべきです。
しかしながら、後述するサンプルアプリケーションでは標準化が実装されていません。
そこでModel Optimizerのパラメータとして、平均値および標準偏差(スケール値)を与えることで、IRに標準化を取り入れます。
後述するサンプルアプリケーションでは、画素値の範囲を[0, 255]として画像を読み込みます。
画素値の範囲は前述の通り[0, 1]へ変換されているため、前述の平均値に255を乗じることで、Model Optimizerのパラメータとしての平均値[123.675, 116.28, 103.53]が得られます。
同様に前述の標準偏差に255を乗じることで、Model Optimizerのパラメータとしての標準偏差[58.395, 57.12, 57.375]が得られます。
なお今回のモデルresnet50-v1-7.onnx
に対しては入出力ノードの名前をModel Optimizerの引数として指定する必要はありませんが、入出力ノードの名前を調べるにはモデルビューアを使用する等の方法があります。
以上でModel Optimizerのパラメータを得ることができました。
Model Optimizerの実行
開発環境にてModel Optimizerを実行し、モデルファイルresnet50-v1-7.onnx
をIRへ変換します。
Model OptimizerはPythonにより実行します。Pythonの仮想環境を起動します。
# cd
# cd ./mo_classification
# source /opt/intel/openvino/deployment_tools/model_optimizer/venv/bin/activate
下記のコマンドで/opt/intel/openvino/deployment_tools/model_optimizer/mo.py
を実行し、モデルファイルresnet50-v1-7.onnx
をIRへ変換します。
# python3 /opt/intel/openvino/deployment_tools/model_optimizer/mo.py \
--framework onnx \
--input_model resnet50-v1-7.onnx \
--data_type FP16 \
--input_shape [1,3,224,224] \
--mean_values [123.675,116.28,103.53] \
--scale_values [58.395,57.12,57.375] \
--reverse_input_channels
下記の表にパラメータ引数の説明を示します。
引数 | 説明 |
---|---|
--framework {tf,caffe,mxnet,kaldi,onnx} |
訓練済みモデルのフレームワーク名 |
--input_model INPUT_MODEL |
変換対象のモデルファイル |
--data_type {FP16,FP32,half,float} |
IRのデータ型 |
--input INPUT |
入力ノード名またはそのリスト |
--input_shape INPUT_SHAPE |
入力データの形状 |
--mean_values MEAN_VALUES |
入力画像のチャネルごとの平均値 |
--scale SCALE |
入力画像の全チャネル共通のスケール値 |
--scale_values SCALE_VALUES |
入力画像のチャネルごとのスケール値 |
--output OUTPUT |
出力オペレーション名 |
--reverse_input_channels |
入力チャネルの並びをRGBからBGRへ(またはその逆へ)入れ替える |
Converting a Model Using General Conversion Parameters - OpenVINO™ Toolkit
IRへの変換対象となるモデルの構造にあわせてこれらの引数を変更します。
今回の変換では下記のように引数を指定します。
-
--framework onnx
: ONNX形式のモデルを変換するため、フレームワーク名としてonnx
を指定 -
--input_model resnet50-v1-7.onnx
: モデルファイルresnet50-v1-7.onnx
を指定 -
--data_type FP16
: Myriad X VPUで推論を行うため、データ型としてFP16を指定 -
--input_shape [1,3,224,224]
: 入力の形状[1,3,224,224]
を指定 -
--mean_values [123.675,116.28,103.53]
: 入力画像のチャネルごとの平均値[123.675,116.28,103.53]
を指定 -
--scale_values [58.395,57.12,57.375]
: 入力画像のチャネルごとの標準偏差[58.395,57.12,57.375]
を指定 -
--reverse_input_channels
: 次節でビルドするサンプルアプリケーションでの画像読込に合わせて、入力チャネルの並びをRGBからBGRへ入替
Model Optimizerの実行が成功すると、IRとして.xml
形式のファイルと.bin
形式のファイルが得られます。
今回の変換ではresnet50-v1-7.onnx
の変換後のIRとして下記のファイルが得られます。
resnet50-v1-7.xml
resnet50-v1-7.bin
サンプルアプリケーションのビルド
IRを利用した推論を行うアプリケーションを開発環境上に用意します。
今回はOpenVINOに付属しているInference Engine SamplesのC++アプリケーションを一括ビルドし、画像分類用のサンプルアプリケーション(classification_sample_async
)を使います。
Image Classification C++ Sample Async - OpenVINO™ Toolkit
下記のコマンドでサンプルの保存フォルダへ移動し、ビルドを行います。
# cd /opt/intel/openvino/inference_engine/samples/cpp
# ./build_samples.sh
ビルドが成功すると~/inference_engine_cpp_samples_build/intel64/Release
下にアプリケーションが保存されます。
AE2100へのデプロイ
IRに変換したモデルと推論用アプリケーションを、開発環境からAE2100へデプロイします。
開発環境でビルドした画像分類用のサンプルアプリケーションclassification_sample_async
を保存用ディレクトリへコピーします。
またclassification_sample_async
の実行に必要な共用ライブラリlibformat_reader.so
を保存用ディレクトリへコピーします。
# cd
# cd mo_classification
# cp ~/inference_engine_cpp_samples_build/intel64/Release/classification_sample_async .
# cp ~/inference_engine_cpp_samples_build/intel64/Release/lib/libformat_reader.so .
また、画像分類の対象とする画像データを用意します。
ここではOpenVINOから提供されている猫の画像とバナナの画像を、下記のコマンドにより保存用ディレクトリへダウンロードします。
# wget https://storage.openvinotoolkit.org/data/test_data/images/cat.jpg
# wget https://storage.openvinotoolkit.org/data/test_data/images/banana.jpg
なお、アプリケーションclassification_sample_async
は、ラベルのテキストファイル(.labels
)をIRと同じファイル名で配置しておくことで、分類結果のラベル名を表示します。
例えばIRがresnet50-v1-7.xml
の場合、ラベルのテキストファイルはresnet50-v1-7.labels
とします。
アプリケーションにて分類結果のラベル名を表示するには、下記コマンドでラベルファイルを取得し、ファイルの名前を変更しておきましょう。
# wget https://raw.githubusercontent.com/onnx/models/master/vision/classification/synset.txt
# mv synset.txt resnet50-v1-7.labels
ls
コマンドにより、AE2100へデプロイするファイルが~/mo_classification
に保存されていることを確認します。
# cd
# ls mo_classification
少なくとも下記のファイルが~/mo_classification
に保存されていることを確認してください。
banana.jpg
cat.jpg
classification_sample_async
libformat_reader.so
resnet50-v1-7.xml
resnet50-v1-7.bin
resnet50-v1-7.labels
ファイルが保存されていることを確認したら~/mo_classification
をtar
コマンドで圧縮し、開発環境からAE2100へ送信するファイルの準備は完了となります。
# cd
# tar czf mo_classification.tar.gz mo_classification
作成した圧縮ファイルmo_classification.tar.gz
をAE2100へ送信してください。
また、圧縮ファイルをUbuntu + OpenVINOコンテナのホームディレクトリへコピーしてください。
AE2100上での推論実行
以降はコンテナのシェルに入った後の操作になります。
下記コマンドにより、コンテナ内のホームディレクトリにてmo_classification.tar.gz
を解凍し、ディレクトリmo_classification
へ移動します。
# cd
# tar xzf mo_classification.tar.gz
# cd mo_classification
OpenVINOの環境変数を設定します。
またmo_classification
に保存した共用ライブラリlibformat_reader.so
を使用するためにパスを設定します。
# source /opt/intel/openvino/bin/setupvars.sh
# export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/mo_classification
以上でアプリケーションclassification_sample_async
の実行準備が済みました。
それではclassification_sample_async
を実行し、画像分類の推論をさせてみましょう。
classification_sample_async
を実行する際は、引数-i
に推論対象の画像ファイルパス、-m
にIRのファイルパス(.xml
)、-d
に推論デバイス名を指定します。
猫の画像cat.jpg
を分類するには、下記のコマンドを実行してください。
# ./classification_sample_async -i cat.jpg -m resnet50-v1-7.xml -d HDDL
classification_sample_async
が正しく動作すると、cat.jpg
の分類結果(クラスID、スコア、クラスのラベル)が下記のように上位10位まで表示されます。
(今回使用したモデルはSoftmax関数が適用されていないスコアを出力するため、probabilityの列は確率ではなくスコアが表示されています)
Top 10 results:
Image cat.jpg
classid probability label
------- ----------- -----
281 11.1406250 n02123045 tabby, tabby cat
285 10.4062500 n02124075 Egyptian cat
435 10.0781250 n02808440 bathtub, bathing tub, bath, tub
876 10.0312500 n04493381 tub, vat
896 9.9609375 n04553703 washbasin, handbasin, washbowl, lavabo, wash-hand basin
282 9.7109375 n02123159 tiger cat
904 9.3906250 n04589890 window screen
794 8.9921875 n04209239 shower curtain
728 8.3515625 n03958227 plastic bag
478 8.1484375 n02971356 carton
続いてバナナの画像banana.jpg
に対しても分類を行ってみましょう。
# ./classification_sample_async -i banana.jpg -m resnet50-v1-7.xml -d HDDL
Top 10 results:
Image banana.jpg
classid probability label
------- ----------- -----
954 13.2343750 n07753592 banana
114 7.7851562 n01945685 slug
940 6.1835938 n07716906 spaghetti squash
390 6.1406250 n02526121 eel
502 5.9296875 n03047690 clog, geta, patten, sabot
110 5.8789062 n01924916 flatworm, platyhelminth
950 5.4960938 n07747607 orange
942 5.4882812 n07717556 butternut squash
600 5.3945312 n03532672 hook, claw
956 5.3867188 n07760859 custard apple
分類結果を見ると、Model Optimizerで変換したIRを用いて妥当な推論結果が得られたといえます。
以上でModel Optimizerを利用して画像分類モデルをIRへ変換し、AE2100上で推論を実行することができました。
おわりに
今回はOpenVINOのModel Optimizerを利用して画像分類モデルをIRへ変換し、AE2100上で推論を実行しました。
ご自身で訓練した画像分類モデルやwebから取得した訓練済み画像分類モデルをAE2100へデプロイする際には、本記事をご参照ください。
次回は物体検出モデルに対してModel Optimizerを適用する方法について説明する予定です。