LoginSignup
2
2

More than 1 year has passed since last update.

Azure Custom Visionで学習した画像分類モデルを「AE2100」で推論してみよう

Posted at

要約

  • 本記事では、マイクロソフト社のクラウドサービスであるAzureのCustom Visionを使用して、画像分類モデルを作成します。
  • その画像分類モデルをAIエッジコンピューター「AE2100」へデプロイして、推論を実行するまでを説明します。

はじめに

Custom Visionとは、GUI操作だけで簡単にAI学習モデルの作成ができるマイクロソフト社のSaaS型のクラウドサービスで、製造業の検品作業や倉庫の類似部品の識別(管理)などで利用されています。
Custom Visionで学習モデルを作成すると、専用のURLが割り当てられます。Azure上で推論させる場合は、このURLに対し推論させたい画像データをREST APIで送信すると、推論結果を取得することができます。
しかし、Azureは、従量課金制のため、Azure上で推論(API呼び出し)される度にコストがかかりまいます。また、クラウドでのAIの処理は、クラウドに画像データを送信する必要があるため、リアルタイムな推論ができないデメリットもあります。

本記事では、Custom Visionで作成した学習モデルをAE2100へデプロイし、推論実行する方法を解説します。これにより、無料かつリアルタイムで推論することができます。

環境

構成イメージは以下のようになります。
image.png

用意するものは、以下の3つです。
①カメラによる撮影または、kaggle等のオープンデータをダウンロードして、学習させる画像を用意してください。
本記事では、製造業における検品作業を想定して、ゴルフボールの画像を使用したいと思います。

②Custom Visionで学習モデルを作成するために、Azureのアカウントを用意してください。

AE2100のマニュアル(SDK取扱説明書 DeepLearning編)に従って、AE2100の環境と開発環境ご用意してください。
なお、AE2100および開発環境は以下のものを前提としています。
【開発環境】
OS:Ubuntu20.04 LTS   OpenVINO:2021.4.1 LTS

【AE2100】
本体ファーム:V3.6.0(HDDL Daemon:OpenVINO2021.4.1 LTS)
標準コンテナ:OpenVINO有(Ubuntu20.04版)2021年10月版

プロジェクトの作成(Custom Vision)

さっそく、Custom Visionのwebページに移動し、[サインイン]の後、[NEW PROJECT]を選択して、新しいプロジェクトを作成していきます。
image.png
Custom Vision サービスを使用するには、Azure で Custom Vision Training リソースと Prediction リソースを作成する必要がありますので、Create new project>Resourceの[Create new]をクリックして、リソースを作成します。
image.png

この時、「Name」は、Azure上で一意な名前にしなければならない点と、「pricing Tier」の選択によって、使用できる機能と料金が変化する点を注意してください。今回は、あくまでお試しなので、無料で利用できる「F0」を選択しています。

リソースの作成が完了したら、プロジェクトの詳細を設定します。ここではAIの種類を選択します。
今回、ゴルフボールの正しい並び(OK)と誤った並び(NG)の判定をおこなうために、「Project Type」は”Classification”を選択します。
また、AE2100へデプロイ可能なAIモデルを出力するためには、「Domains」は”General(compact)”もしくは”General(compact)[S1]”を選択する必要があります。今回は、精度の高い”General(compact)[S1]”を選択します。
残りの選択項目は、デフォルトのままで構いません。

プロジェクトの詳細を設定後[Create project]をクリックすると、以下のような画面に遷移します。
image.png

学習モデルの作成(Custom Vision)

続いて、公式ドキュメントの通りに、データセット(学習させたい画像)をアップロードしていきます。
公式ドキュメントでは、タグごとに最低30枚の画像を学習することが推奨になりますが、ここではOKとNGの画像をそれぞれ10枚ずつ学習します。
なお、正しい並び(OK)は、左から黄、白、橙、白の順で列毎に同じ色のボールが並んでおり、それ以外の並びの画像は誤った並び(NG)としております。
image.png

正しい並び(OK)と誤った並び(NG)の画像(「1_1_OK_images_TRAIN」、「1_2_NG_images_TRAIN」フォルダの画像)に対してタグ付けし、[Train]をクリックして学習を開始します。
image.png
3分程度で学習が完了します。その後、テスト画像(「2_1_OK_images_TEST_to_TRAIN」、「2_2_NG_images_TEST_to_TRAIN」フォルダの画像)のアップロードを行い、[Quick Test]でモデルの評価を実施します。
「OK」を正しく「OK」と予測した画像が9/10枚、
「NG」を正しく「NG」と予測した画像が2/10枚でした。。
image.png

「NG」の正解率が低いので、「Quick Test」で使用したテスト画像に正しいタグを付けて再度学習します。
image.png

2回目は、「OK」を正しく「OK」と予測した画像が10/10枚、「NG」を正しく「NG」と予測した画像が7/10枚でしたので、NGのテスト画像(「3_2_NG_images_TEST_to_TRAIN」フォルダの画像)10枚のみを再度学習させました。
そうすると、「OK」、「NG」の両方のテスト画像を10/10枚正しく予測させることができました!
image.png

学習モデルの精度を上げるには、いろいろな方法があるようですので、自作の学習モデルを作成する際は、試行錯誤してみてください。

学習モデルのエクスポート(Custom Vision)

それでは、先ほど作成した学習モデルをエクスポートしていきます。
「performance」>「Export」>「OpenVino」>「Export」の順にクリックし、AE2100で動作させるのに最適なOpenVINO形式で学習モデルをエクスポートします。
image.png

ダウンロードして開いたzipファイルが、以下のようになっていれば問題ありません。
image.png

AE2100へのデプロイ

エクスポートした学習モデルをAE2100へデプロイします。
学習モデルのzipファイル、テスト画像、サンプルコード(predict.py)をzipに圧縮して、SCPでAE2100へ転送します。
image.png

なお、サンプルコード(predict.py)は、OpenVINO形式の学習モデルを読み込み、入力画像に対してラベル毎の推論結果(確率)を表示するプログラムになっています。

サンプルコード(predict.py)の確認は、ここをクリック
import argparse
import pathlib
import numpy as np
import PIL.Image
from openvino.inference_engine import IECore


class Model:
    def __init__(self, xml_filepath, bin_filepath):
        ie = IECore()
        net = ie.read_network(str(xml_filepath), str(bin_filepath))
        assert len(net.input_info) == 1

        self.exec_net = ie.load_network(network=net, device_name='CPU')
        self.input_name = list(net.input_info.keys())[0]
        self.input_shape = net.input_info[self.input_name].input_data.shape[2:]
        self.output_names = list(net.outputs.keys())

    def predict(self, image_filepath):
        # The model requires RGB[0-1] NCHW input.
        image = PIL.Image.open(image_filepath).resize(self.input_shape)
        input_array = np.array(image)[np.newaxis, :, :, :]
        input_array = input_array.transpose((0, 3, 1, 2))  # => (N, C, H, W)
        input_array = input_array / 255  # => Pixel values should be in range [0, 1]

        return self.exec_net.infer(inputs={self.input_name: input_array})


def print_outputs(outputs):
    outputs = list(outputs.values())[0]
    for index, score in enumerate(outputs[0]):
        print(f"Label: {index}, score: {score:.5f}")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('xml_filepath', type=pathlib.Path)
    parser.add_argument('bin_filepath', type=pathlib.Path)
    parser.add_argument('image_filepath', type=pathlib.Path)

    args = parser.parse_args()



    model = Model(args.xml_filepath, args.bin_filepath)
    outputs = model.predict(args.image_filepath)
    print_outputs(outputs)


if __name__ == '__main__':
    main()

OpenVINOを利用したプログラムの実装方法につきましては、別の記事で詳しく記載されておりますので、ご参照ください。

続いて、teratermでAE2100へログインし、標準コンテナ上に「CV_Classification」ディレクトリを作成します。

root@ae2100:~# docker start ubuntu-openvino
root@ae2100:~# docker exec -it ubuntu-openvino /bin/bash
root@3a69a45317dd:/opt/intel/openvino_2021.4.689# cd
root@3a69a45317dd:~# mkdir CV_Classification
root@3a69a45317dd:~# exit
exit

ホストからコンテナへzipファイルをコピーします。

root@ae2100:~# docker cp Send_TO_AE2100.zip ubuntu-openvino:/root/CV_Classification

そして、コンテナ内でunzipを実行(解凍)します。
(unzipコマンドがない場合は、インターネットに接続した状態でインストールしてください。)

root@ae2100:~# docker start ubuntu-openvino
root@ae2100:~# docker exec -it ubuntu-openvino /bin/bash
root@3a69a45317dd:/opt/intel/openvino_2021.4.689# cd /root/CV_Classification/
root@3a69a45317dd:~/CV_Classification# apt install unzip
root@3a69a45317dd:~/CV_Classification# unzip Send_TO_AE2100.zip
root@3a69a45317dd:~/CV_Classification# cd Send_TO_AE2100
root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# unzip ExportFile_OpenVino.zip

#結果の出力
最後に推論を実行していきましょう。

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin OK_image.jpg
Label: 0, score: 0.16326
Label: 1, score: 0.83674

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin NG_image1.jpg
Label: 0, score: 0.94221
Label: 1, score: 0.05779

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin NG_image2.jpg
Label: 0, score: 0.97225
Label: 1, score: 0.02775

Label: 0が誤った並び(NG)、Label: 1が正しい並び(OK)である各確率をscoreで表示しています。
よって、「OK_image.jpg」は、16%の確率でNG、83%の確率でOKと推論しています。
「NG_image1.jpg」については94%でNG、6%でOK、「NG_image2.jpg」については97%でNG、3%でOKということで、正しく推論できていることがわかります。

続いて、viコマンドで「predict.py」の14行目「self.exec_net = ie.load_network(network=net, device_name='CPU')」を「self.exec_net = ie.load_network(network=net, device_name='HDDL')」に変更して、VPUを指定して実行できるか確認してみましょう。

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# vi predict.py
サンプルコード(predict.py)の確認は、ここをクリック
import argparse
import pathlib
import numpy as np
import PIL.Image
from openvino.inference_engine import IECore


class Model:
    def __init__(self, xml_filepath, bin_filepath):
        ie = IECore()
        net = ie.read_network(str(xml_filepath), str(bin_filepath))
        assert len(net.input_info) == 1

        self.exec_net = ie.load_network(network=net, device_name='HDDL')
        self.input_name = list(net.input_info.keys())[0]
        self.input_shape = net.input_info[self.input_name].input_data.shape[2:]
        self.output_names = list(net.outputs.keys())

    def predict(self, image_filepath):
        # The model requires RGB[0-1] NCHW input.
        image = PIL.Image.open(image_filepath).resize(self.input_shape)
        input_array = np.array(image)[np.newaxis, :, :, :]
        input_array = input_array.transpose((0, 3, 1, 2))  # => (N, C, H, W)
        input_array = input_array / 255  # => Pixel values should be in range [0, 1]

        return self.exec_net.infer(inputs={self.input_name: input_array})


def print_outputs(outputs):
    outputs = list(outputs.values())[0]
    for index, score in enumerate(outputs[0]):
        print(f"Label: {index}, score: {score:.5f}")


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('xml_filepath', type=pathlib.Path)
    parser.add_argument('bin_filepath', type=pathlib.Path)
    parser.add_argument('image_filepath', type=pathlib.Path)

    args = parser.parse_args()



    model = Model(args.xml_filepath, args.bin_filepath)
    outputs = model.predict(args.image_filepath)
    print_outputs(outputs)


if __name__ == '__main__':
    main()
root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin OK_image.jpg
Label: 0, score: 0.25000
Label: 1, score: 0.75000

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin NG_image1.jpg
Label: 0, score: 0.93506
Label: 1, score: 0.06494

root@3a69a45317dd:~/CV_Classification/Send_TO_AE2100# python3 predict.py model.xml model.bin NG_image2.jpg
Label: 0, score: 0.95703
Label: 1, score: 0.04312

こちらも問題ないみたいですね!
ターミナル上で出力が少し遅かったですが、GPUやHDDLで実行する際は、モデルのロード時間がかかりますので、その影響かと思います。
また、HDDLのパフォーマンスを最大限に活かすためには、非同期処理のプログラムを作成する必要があります。
別途、参考の記事がありますので、挑戦してみてください。

#参考
念のため、OpenVINOのベンチマークを行ってみます。
(※AE2100上でベンチマークを行うには、OpenVINOのフルパッケージをインストールする必要がありますので、リソースにご注意ください。)

CPUのベンチマーク結果

root@3a69a45317dd:/opt/intel/openvino_2021.4.689/deployment_tools/tools/benchmar
k_tool# python3 benchmark_app.py -d CPU -i /root/CV_Classification/Send_TO_AE210
0/OK_image.jpg -m  /root/CV_Classification/Send_TO_AE2100/model.xml
~中略~
Count:      572 iterations
Duration:   60481.09 ms
Latency:    414.16 ms
Throughput: 9.46 FPS

GPUのベンチマーク結果

root@3a69a45317dd:/opt/intel/openvino_2021.4.689/deployment_tools/tools/benchmar
k_tool# python3 benchmark_app.py -d GPU -i /root/CV_Classification/Send_TO_AE210
0/OK_image.jpg -m  /root/CV_Classification/Send_TO_AE2100/model.xml
~中略~
Count:      1236 iterations
Duration:   60328.87 ms
Latency:    195.01 ms
Throughput: 20.49 FPS

VPUのベンチマーク結果

root@3a69a45317dd:/opt/intel/openvino_2021.4.689/deployment_tools/tools/benchmar
k_tool# python3 benchmark_app.py -d HDDL -i /root/CV_Classification/Send_TO_AE2100/OK_image.jpg -m  /root/CV_Classification/Send_TO_AE2100/model.xml
~中略~
Count:      2432 iterations
Duration:   60212.76 ms
Latency:    197.85 ms
Throughput: 40.39 FPS

ベンチマークの結果を表にすると、以下のようになります。
image.png
CPUに対してVPUのスループットが4倍以上の数値であることをご確認いただけるかと思います。

まとめ

Custom VisionとAE2100を使用することで、簡単にAIの学習モデルを作成し、実運用の環境でリアルタイムな推論ができます。
Custom Visionは、GPUサーバーなどのAIの学習環境を構築が不要で、無料枠も充実しているため、気軽に利用を開始することができます。
皆様の現場でどの程度使えそうか(精度)は、やってみないと分からないところもありますので、ぜひ色々な使い方で試してみてください。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2