こんにちは、機械学習 エンジニアの駿です。
先日庭の花壇にヒマワリの種をまいたのですが、早速芽が出てきました。
夏に黄色い花が咲くのが今から楽しみです。
今回はAWS の外観検査サービスである Amazon Lookout for Vision が、 AWS IoT Greengrass を使ってエッジでの推論が可能になったため、試してみました。
今までは Lookout for Vision はクラウド 側での推論(判定)しかできず、画像をネットワーク越しに送るため、オーバーヘッドが発生していました。
そのため、例えば工場の生産ラインで外観検査をしていたとすると、製品の撮影・検査をした後で、異常なモノを仕分けをしたりしますが、それに時間がかかってしまう、といった状況が発生することになってしまいます。
しかし、 Lookout for Vision のモデルを Greengrass でパッケージ化しエッジデバイス に配置して検査を行うことで、画像を送信するオーバーヘッドがなくなり、リアルタイムで処理ができるようになります。
Lookout for Vision は画像が正常か異常を判定する、異常検知のサービスです。
教師画像は最低30枚と少ない枚数で始められますが、非常に高い精度で異常を判定することができます。
詳細については以下の記事があるので、そちらをご覧ください。
acro-engineer.hatenablog.com
AWS IoT Greengrass
Greengrass は Raspberry Pi などのエッジデバイス 上にIoTアプリケーションを構築、デプロイ、管理するためのクラウド サービスです。
Lambda関数、Dockerコンテナなどをコンポーネント としてパッケージ化し、エッジデバイス にデプロイ、実行することができます。
そんな Greengrass が2021年末に Lookout for Vision モデルのコンポーネント に対応し、
GPU を備えたエッジデバイス にデプロイすることで、クラウド に画像を送ることなく、オンプレミスかつリアルタイムの外観検査ができるようになりました。
構成
今回はエッジデバイス にJetsonNanoを使用し、 Greengrass サービスを通じて、 Lookout for Vision モデルコンポーネント と、
それを利用するための EdgeAgent コンポーネント をデプロイします。
今回の構成図(公式ドキュメント より)
手順
大まかな流れは下記のようになります。
JetsonNano 上で Greengrass のサービスを起動する
Lookout for Vision モデルを Greengrass 用にコンポーネント 化する
モデルコンポーネント とAWS が提供している EdgeAgent を JetsonNano にデプロイする
Python スクリプト からデプロイされたモデルを起動し、検査を実行する
早速、詳細の説明に入ります。
1. JetsonNano 上で Greengrass のサービスを起動する
公式ドキュメントでは動作環境としてJetson Xavierを推奨 していますが、すぐに用意できなかったので、今回は JetsonNano を使ってみました。
ただし、性能を考慮した場合、実際の運用などでは Jetson Xavier などを利用するほうが安全だと思われます。
(1) JetsonNano に JetPack をインストール
エッジデバイス 上で Lookout for Vision のモデルを使用するためには、GPU とCUDA、TensorRT などのライブラリが必要です。
JetPack を使うと、これらのライブラリをひとつひとつインストールする必要がなく、
既に整った環境を作ることができます。
JetPack4.5.1 のSDカードイメージをダウンロードし、公式ドキュメント
に従ってセットアップを行います。
なお、Greengrass でデプロイする Lookout for Vision モデルが対応しているのが、バージョン4.4と4.5系のみのため、間違えて最新バージョンを入れないように注意が必要です。
(2) Greengrass サービスおよび Lookout for Vision モデルの起動に必要なライブラリのインストール
Greengrass サービスの起動に Java が必要になります。
今回はAWS が提供する Corretto をインストールしました。
また、Lookout for Vision のモデルの起動に Python3.8 もしくは 3.9 が必要です。
今回は 3.8 をインストールしました。
(3) クライアントアプリに必要なライブラリのインストール
公式ドキュメント に従って、
grpc をインストールし、サービス定義ファイルからクライアントインターフェイス を生成します。
また、画像読み込みのための Pillow もインストールします。
(4) Greengrass サービスのダウンロードおよび起動
Greengrass のコンソールから 「1つのCoreデバイス をセットアップ」を選択します。
「1つのCoreデバイス をセットアップ」
コアデバイス 名など必要な情報を入力すると、インストーラ のダウンロードコマンドおよび実行コマンドが生成されるので、エッジデバイス 上でコマンドを実行します。
インストールが終わると、自動で Greengrass サービスの実行が始まります。
また、インストール中に Greengrass ユーザ ggc_user が作成されています。
そのままでは Greengrass でデプロイされたコンポーネント が GPU にアクセスできない ため、 ggc_user を video グループに追加します。
sudo usermod -a -G video ggc_user
Greengrass コンソールから追加したエッジデバイス が確認でき、ステータスが「正常」となっていたら Greengrass の準備は完了です。
JetsonNanoがCoreデバイス として設定できた
(5) DLR のインストール
Lookout for Vision が libdlr.so を必要とするのですが、 pip でインストールできるDLRには .so ファイルが含まれていない ようです。
ggc_user として whl からインストールすることで、 モデルコンポーネント が読み込めるようになります。
下記コマンドを ggc_user として実行してください。
curl -O https://neo-ai-dlr-release.s3-us-west-2.amazonaws.com/v1.10.0/jetpack4.5/dlr-1.10.0-py3-none-any.whl
python3.8 -m pip install dlr-1.10.0-py3-none-any.whl
2. Lookout for Vision モデルを Greengrass 用にコンポーネント 化する
既に学習済みのモデルがあるものとします。
プロジェクトのページに遷移し左のメニューで「モデルのパッケージ」を選択します。
「モデルパッケージングジョブを作成」ボタンを押し、「モデルの選択」など必要な項目を埋めていきます。
「モデルパッケージングジョブを作成」
ターゲットハードウェア設定
2022/05/07現在、プリセットの設定は Jetson Xavier 用しかないため、JetsonNano を使用する際は「ターゲットプラットフォーム」を選択して、設定を行います。
コンパイラ オプションは使用するデバイス 、インストールしたライブラリのバージョンによって異なります。
GPU コード、TensorRT バージョン、CUDA バージョンをそれぞれ指定します。
上記値は JetsonNano+JetPack4.5.1の場合の値です。
ターゲットハードウェアの設定
最後に「モデルパッケージングジョブを作成」ボタンを押して、パッケージングを開始します。
コンソール上で、「成功」ステータスになったら完了です。
Greengrass コンソールのコンポーネント ページからも作成したモデルコンポーネント を確認することができます。
3. モデルコンポーネント とAWS が提供している EdgeAgent を JetsonNano にデプロイする
Greengrass コンソールのデプロイページからデプロイを作成します。
今回はデプロイターゲットにコアデバイス を選択し、上で登録した JetsonNano にのみデプロイします。
「コンポーネント の選択」画面で、パッケージした Lookout for Vision モデルコンポーネント を選択します。
このコンポーネント は AWS が提供する aws .iot.lookoutvision.EdgeAgent に依存しているため、
そちらも自動でデプロイされます。
「コンポーネント の選択」
そのほかの設定を変更する必要は必要ありません。
「デプロイ」を選択して、 JetsonNano にデプロイします。
デプロイのステータスが「完了」になったら成功です。
4. Python スクリプト からデプロイされたモデルを起動し、検査を実行する
エッジデバイス 上で ggc_user としてログインします。
Python のインタプリタ を起動し、モデルの起動と検査を試してみます。
(1) モデルの起動
import grpc
from edge_agent_pb2_grpc import EdgeAgentStub
import edge_agent_pb2 as pb2
channel = grpc.insecure_channel("unix:///tmp/aws.iot.lookoutvision.EdgeAgent.sock" )
stub = EdgeAgentStub(channel)
model_component_name = "lfv_component_aarm"
model_description_response = stub.DescribeModel(pb2.DescribeModelRequest(model_component=model_component_name))
model_description_response.model_description.status == pb2.STOPPED
stub.StartModel(pb2.StartModelRequest(model_component=model_component_name))
model_description_response = stub.DescribeModel(ob2.DescribeModelRequest(model_component=model_component_name))
model_description_response.model_description.status == pb2.RUNNING
(2) 検査実行
モデルが起動したら画像に対して検査を実行できます。
エッジデバイス に画像を用意して、Pillow で読み込んだものをモデルに送ります。
from PIL import Image
image = Image.open(image_path)
image = image.convert("RGB" )
detect_anomalies_response = stub.DetectAnomalies(
pb2.DetectAnomaliesRequest(
model_component=model_component_name,
bitmap=pb2.Bitmap(
width=image.size[0 ],
height=image.size[1 ],
byte_data=bytes (image.tobytes())
)
)
)
is_anomalous = detect_anomalies_response.detect_anomaly_result.is_anomalous
confidence = detect_anomalies_response.detect_anomaly_result.confidence
print (f"Image is anomalous - {is_anomalous}" )
print (f"confidence - {confidence:.2}" )
(3) モデルの停止
stub.StopModel(StopModelRequest(model_component=model_component_name))
model_description_response = stub.DescribeModel(ob2.DescribeModelRequest(model_component=model_component_name))
model_description_response.model_description.status == pb2.STOPPED
channel.close()
結果
精度
前述の投稿で使用している Metal Nut 画像から正常を5枚、異常を5枚使って検査を実行したところ、すべて正しく判定することができました。
クラウド 側で判定した場合と比較して、エッジデバイス 上で判定しても同等の精度が出ることがわかりました。
実行時間
下記の関数を作り、画像1枚を推論するのにかかる時間を計測してみました。
def timeit ():
start_time = time.time()
stub.DetectAnomalies(...)
print (f"took {time.time() - start_time} seconds" )
上記関数を10回実行した結果は下記のようになり、平均で0.25秒/枚で検査ができることになります。
#
所要時間(ms)
1
399.8
2
374.2
3
212.9
4
216.0
5
217.8
6
212.5
7
215.5
8
212.8
9
218 .3
10
216.5
平均
249.6
awscli でクラウド 側の Lookout for Vision モデルを使用した場合はネットワークの往復も含めて約3秒でした。
awscli の場合は画像変換の時間も含まれるため単純な比較はできませんが、エッジで実行することで10倍以上早くなっています。
Jetson Xavier などより計算力のあるデバイス を用いることで、さらにリアルタイム性のある外観検査ができるようになりますね。
(オレゴン リージョンの Lookout for Vision を使用しているため、東京リージョンのものを用いるよりもさらに伝送時間がかかっていると思われます。)
料金
Greengrass を使ってエッジデバイス にデプロイした Lookout for Vision モデルを使用する場合、エッジ推論ユニットに基づいて月額料金がかかります。
1デバイス 上で120検査/分までの検査は1エッジ推論ユニットとして扱われ、1エッジ推論ユニットは月100USD かかります。
個人で実施するにはちょっとお高めになっているので、工場など大規模で検査を行う必要があるユースケース を想定しているのがわかります。
まとめ
今回はGreengrassを使ってLookout for Vision のモデルをJetson Nanoにデプロイし、外観検査を行いました。
普段エッジデバイス を使うことがあまりないこともあり、最初の環境構築でバージョン不整合などでつまづいてしまいました。
実際に動かしてみて、エッジでの検査は画像をネットワーク越しに送信する必要がない分、10倍も早く実行できることがわかりました。
それでいてクラウド と同じモデルを使っているため、精度は同等です。
また、今回は Python のインタプリタ を使って検査を実行しましたが、クライアントアプリを作成して Greengrass コンポーネント としてデプロイすることもできます。
今度は実際にカメラを繋いで、どれくらいのFPS が出せるのか、なども試してみたいです。
Acroquest Technologyでは、キャリア採用を行っています。
ディープラーニング 等を使った自然言語 /画像/音声/動画解析の研究開発
Elasticsearch等を使ったデータ収集/分析/可視化
マイクロサービス、DevOps、最新のOSS を利用する開発プロジェクト
書籍・雑誌等の執筆や、社内外での技術の発信・共有によるエンジニアとしての成長
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
www.wantedly.com