AWS IoT Greengrass V2 / SageMaker によるエッジAI推論の紹介
AWS IoT Greengrass V2 / SageMaker の紹介を目的とした勉強会、「AWS IoT Greengrass V2/SageMaker によるエッジAI推論の紹介」を開催しました。
プレゼンテーションの内容を共有し、 AWS を使用したエッジ推論についての理解の機会を提供できればと思います。 この投稿のサンプルは、 GitHub リポジトリから取得できます。
前提条件
参加者は以下が期待されます:
- AWS でのエッジ AI 推論に興味がある
- 機械学習と AWS の基本知識
この投稿の目標:
- AWS 上でのエッジ AI 推論の概要把握
- IoT Greengrass V2, SageMaker, SageMaker Neo, SageMaker Edge Manager を使用したデモ
エッジコンピューティング概要
Edge computing is a distributed computing paradigm that brings computation and data storage closer to the sources of data. This is expected to improve response times and save bandwidth.
エッジコンピューティングには次のような多くの利点があります。
- 低レイテンシー(特に自動運転などのリアルタイムアプリケーションにとって重要)
- セキュリティリスク低減
- 通信コスト低減
ただし、エッジコンピューティングにはいくつかの欠点もあります。
- 垂直スケーリングが難しい(クラウド環境では簡単)
- キャパシティプランニングが必要
- インフラ管理
エッジコンピューティングは AI だけでなく、 CDN にも利用されています。
エッジ AI の現在の課題の1つは、コンピューティング能力です。 現代の機械学習と深層学習のアルゴリズムは多くのハイパーパラメーターを持ち、相当なコンピューティングリソースを必要とします。 エッジ AI 向けに ML/DL モデルを最適化するためのさまざまな取り組みが行われています。1
IoT Greengrass V2
概要
AWS IoT Greengrass is an open source Internet of Things (IoT) edge runtime and cloud service that helps you build, deploy and manage IoT applications on your devices.
IoT Greengrass V2 の特徴:
- Windows 2, Linux (Ubuntu, Raspberry Pi OS など) での実行が可能
- x86, ARM の両方のアーキテクチャに対応
- Lambda 関数サポート
- エッジ AI 推論のための Deep Learning Runtime (DLR) サポート
概念
IoT Greengrass V2 の概念には以下が含まれます。
- Greengrass Core デバイス
- エッジで Greengrass Core を実行します。
- AWS IoT Things として登録されます。
- AWS と通信します。
- Greengrass クライアントデバイス
- MQTT を使用して Greengrass Core デバイスと通信します。
- AWS IoT Things として登録されます。
- Greengrass Core デバイスがメッセージブローカーとして使用される場合、他のクライアントデバイスと通信します。
- Greengrass コンポーネント
- Greengrass Core デバイス上で実行されるソフトウェアです。
- ユーザーによって実装および登録されます。
- デプロイメント
- AWS から Greengrass Core デバイスへの指令です。
SageMaker
SageMaker 概要
SageMaker は AWS での機械学習用マネージドサービスです。 ユーザーは17の組み込みアルゴリズムを使用して、少ないコードで機械学習を実行できます 3。 TensorFlow や PyTorch などの主要なディープラーニングフレームワークをサポートしています 4。
SageMaker は以下の種類の推論エンドポイントを提供しています。
- SageMaker Hosting Services (EC2 に類似)
- SageMaker Serverless Endpoints (Preview) (Lambda に類似)
- 非同期推論 (SQS, EC2, Auto Scaling に類似)
- バッチ変換 (AWS Batch に類似)
SageMaker Neo 概要
Neo is a capability of Amazon SageMaker that enables machine learning models to train once and run anywhere in the cloud and at the edge.
With a single click, SageMaker Neo optimizes the trained model and compiles it into an executable. The compiler uses a machine learning model to apply the performance optimizations that extract the best available performance for your model on the cloud instance or edge device.
SageMaker Edge Manager 概要
Amazon SageMaker Edge Manager provides model management for edge devices so you can optimize, secure, monitor, and maintain machine learning models on fleets of edge devices such as smart cameras, robots, personal computers, and mobile devices.
この投稿の例では、モニタリング機能は使用しません。
エッジ AI 推論の例
概要
この例では、 EC2 インスタンスをエッジデバイスとみなします。
以下でエッジ推論を確認できます。
- セットアップ
- AWS リソース準備
- 訓練スクリプト実装
- 推論スクリプト実装
- SageMaker
- SageMaker 訓練
- SageMaker Neo でモデルのコンパイル
- SageMaker Edge Manager でモデルのパッケージング
- Greengrass
- Greengrass Core セットアップ
- エッジ推論用 Greengrass コンポーネント登録
- Greengrass コンポーネントのデプロイ
- テスト
AWS リソース準備
以下の AWS リソースを事前に準備してください。 各リソースの詳細については、サンプルの GitHub リポジトリで提供している CloudFormation テンプレートを確認してください。
リソース | 名前 | 説明 |
---|---|---|
IAM ユーザー | greengrass-core-setup-user | Greengrass Core セットアップに使用 |
IAM ロール | sagemaker-execution-role | SageMaker 実行ロール |
IAM ロール | GreengrassV2TokenExchangeRole | Greengrass Core ロール |
S3 | sagemaker-ml-model-artifacts-{account_id}-{region} | ML モデル用のバケット |
以下のコマンドを実行して、これらのリソースを作成できます。
% aws cloudformation deploy --template-file ./cfn.yaml --stack-name greengrass-sample --capabilities CAPABILITY_NAMED_IAM
Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - greengrass-sample
訓練スクリプト実装
この例では、 PyTorch の事前学習済み VGG16 モデルを使用しているため、次のコマンドでインストールしてください。
% pip install torch torchvision
以下の内容で training.py
を作成してください。
このファイルは SageMaker で実行されます。
import argparse
import os
from datetime import datetime
import torch
from torchvision import models
def fit(model: torch.nn.modules.Module) -> None:
# Write some training codes...
pass
def save(model: torch.nn.modules.Module, path: str) -> None:
suffix = datetime.now().strftime('%Y-%m-%d_%H-%M-%S')
path = os.path.join(path, f'model-{suffix}.pt')
# If you use `model.state_dict()`, SageMaker compilation will fail.
torch.save(model, path)
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
# hyperparameters sent by the client are passed as command-line arguments to the script.
# input data and model directories
parser.add_argument('--model_dir', type=str)
parser.add_argument('--sm_model_dir', type=str, default=os.environ.get('SM_MODEL_DIR'))
parser.add_argument('--train', type=str, default=os.environ.get('SM_CHANNEL_TRAIN'))
parser.add_argument('--test', type=str, default=os.environ.get('SM_CHANNEL_TEST'))
args, _ = parser.parse_known_args()
return args
if __name__ == '__main__':
args = parse_args()
vgg16 = models.vgg16(pretrained=True)
fit(vgg16)
save(vgg16, args.sm_model_dir)
SageMaker 用の訓練スクリプトを実装する際は、ローカル環境でのアプローチと同じように進めることができます。 ただし、以下の点に留意する必要があります。 詳細については、公式ドキュメントをご参照ください。
- 実行時引数
- 環境変数
- 訓練データセット
FILE
モードを使用している場合、訓練データセットは S3 から SageMaker インスタンスに自動的にコピーされます。PIPE
モードを使用している場合、ストリーミングされた訓練データの読み取りのためのコードを実装する必要があります。詳細については、公式ドキュメントをご参照ください。
- モデル保存ディレクトリ
SM_MODEL_DIR
環境変数は、訓練済みモデルを保存するために使用できます。このディレクトリに保存されたモデルは、自動的に S3 にアップロードされます。
上記の例では訓練コードは含まれていません。
推論スクリプト実装
SageMaker Neo でコンパイルされたモデルは、 Deep Learning Runtime (DLR) を使用してロードできます。 次のコマンドで DLR をインストールしてください。
% pip install dlr
以下の内容で inference.py
を作成してください。
このファイルは Greengrass Core で実行されます。
import argparse
import glob
import json
import os
import time
import numpy as np
from dlr import DLRModel
def load_model() -> DLRModel:
return DLRModel('/greengrass/v2/work/vgg16-component')
def load_labels() -> dict:
path = os.path.dirname(os.path.abspath(__file__))
# See https://storage.googleapis.com/download.tensorflow.org/data/imagenet_class_index.json
path = os.path.join(path, 'imagenet_class_index.json')
with open(path, 'r') as f:
labels = json.load(f)
return labels
def iter_files(path: str) -> str:
path = path[:-1] if path.endswith('/') else path
files = glob.glob(f'{path}/*.npy')
for file in files:
yield file
def predict(model: DLRModel, image: np.ndarray) -> np.ndarray:
return model.run(image)[0]
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument('--test_dir', type=str)
parser.add_argument('--interval', type=int, default=300)
args, _ = parser.parse_known_args()
return args
def start(model: DLRModel, path: str, labels: dict) -> None:
for file in iter_files(path):
image = np.load(file)
y = predict(model, image)
index = int(np.argmax(y))
label = labels.get(str(index), '')
print(f'Prediction result of {file}: {label}')
if __name__ == '__main__':
args = parse_args()
print(f'args: {args}')
model = load_model()
labels = load_labels()
if args.interval == 0:
start(model, args.test_dir, labels)
else:
while True:
start(model, args.test_dir, labels)
print(f'Sleep in {args.interval} seconds...')
time.sleep(args.interval)
PyTorch は入力データとして torch.Tensor
を想定していますが、 SageMaker Neo でコンパイルされたモデルは numpy.ndarray
を想定していることに注意が必要です。
PyTorch の事前学習済みモデルの入力フォーマットに関する情報については、公式ドキュメントをご参照ください。
この例では、 Greengrass Core に配置された /greengrass/v2/work/vgg16-inference-component/images/*.npy
に対して --interval
引数で指定された間隔で推論が実行されます。
AWS 提供のコンポーネント aws.greengrass.DLRImageClassification
や aws.greengrass.DLRObjectDetection
もご参照ください。
推論用 Greengrass コンポーネントを登録するには、推論スクリプトと関連するファイルを含む ZIP ファイルを S3 バケットにアップロードしてください。
% cd vgg16-inference-component
% zip vgg16-inference-component-1.0.0.zip inference.py imagenet_class_index.json
% aws s3 cp vgg16-inference-component-1.0.0.zip s3://{YOUR_BUCKET}/artifacts/
SageMaker 訓練
SageMaker Python SDK を以下のコマンドでインストールしてください。
% pip install sagemaker
ローカル環境で SageMaker の訓練ジョブをキューに入れるには、以下の内容で training_job.py
を作成してください。
もちろん、 SageMaker のマネジメントコンソールを使用することもできます。
from sagemaker.pytorch import PyTorch
AWS_ACCOUNT_ID = '123456789012'
S3_BUCKET = f's3://sagemaker-ml-model-artifacts-{AWS_ACCOUNT_ID}-ap-northeast-1’
if __name__ == '__main__':
pytorch_estimator = PyTorch(
entry_point='training.py',
source_dir='./',
role='sagemaker-execution-role',
instance_count=1,
instance_type='ml.m5.large',
framework_version='1.10.0',
py_version='py38',
output_path=f'{S3_BUCKET}/models/trained',
hyperparameters={}
)
pytorch_estimator.fit()
スクリプトを実行後、実行ログに請求情報が表示されます。 例えば、以下のログでは255秒が請求されます。
% python training_job.py
…
2022-02-16 15:41:56 Uploading - Uploading generated training model
2022-02-16 15:42:56 Completed - Training job completed
ProfilerReport-1645025749: NoIssuesFound
Training seconds: 255
Billable seconds: 255
モデルは S3 バケットに保存されます (output/model.tar.gz
)。
この後、 SageMaker Neo を使用してコンパイルおよび最適化します。
SageMaker Neo でモデルのコンパイル
SageMaker のコンパイルジョブを作成してください。 この例では、ジョブが完了するのに約4分かかりました。
以下に従って入力設定を指定してください。
フィールド | 値 |
---|---|
アーティファクト | model.tar.gz のS3 URI |
入力設定 | モデルの入力形状 |
フレームワーク | PyTorch |
フレームワークのバージョン | 1.8 |
入力形状については、公式ドキュメントに次のように記載されています。
All pre-trained models expect input images normalized in the same way, i.e. mini-batches of 3-channel RGB images of shape (3 x H x W), where H and W are expected to be at least 224.
出力設定は任意の値を指定してください。
Target device
として rasp4b
を選択すると、モデルは64ビットアーキテクチャ向けにコンパイルされます。したがって、 Raspberry Pi 32 ビット OS などの32ビット OS にモデルをロードすることはできません。この場合、64ビット OS を使用する必要があります。 AWS 公式ドキュメントには情報が見当たりませんでしたが、 AWS フォーラムでコメントがありました。
ページの下部に以下のように記載されています。
The library libdlr.so compiled by Sagemaker Neo with target rasp4b returns “ELF-64 bit LSB pie executable, ARM aarch64, version 1 (GNU/Linux), dynamically linked,
以下の項目はデフォルトのままで OK です。
SageMaker Edge Manager でモデルのパッケージング
SageMaker Edge パッケージングジョブを作成してください。
SageMaker Neo コンパイルジョブ名を入力してください。
デプロイのプリセットとして Greengrass V2 コンポーネントを選択した場合、コンパイルされたモデルは以下のようになります。
- SageMaker Edge によって Greengrass V2 コンポーネントとして登録されます。
- Greengrass Core 上の
/greengrass/v2/work/vgg16-component/
に保存されます。
Greengrass Core セットアップ
エッジデバイス上に Greengrass Core をセットアップしてください。 この投稿では、 Ubuntu 20.04.03 を実行している EC2 インスタンスを使用しています。 Greengrass Core のインストール手順についての詳細は、公式ドキュメントをご参照ください。
MQTT over TLS は、8883 ポートを使用します。 ポートが開いていない場合は、手動セットアップが必要です。
以下のコマンドで JDK をインストールしてください。
% sudo apt install default-jdk
% java -version
Greengrass Core 用のユーザーとグループを追加してください。
% sudo useradd --system --create-home ggc_user
% sudo groupadd --system ggc_group
AWS クレデンシャルを設定してください。
% # Set the credential of greengrass-core-setup-user already provisioned by CloudFormation
% export AWS_ACCESS_KEY_ID=
% export AWS_SECRET_ACCESS_KEY=
以下のコマンドで Greengrass Core をインストールしてください。
% curl -s https://d2s8p88vqu9w66.cloudfront.net/releases/greengrass-nucleus-latest.zip > greengrass-nucleus-latest.zip
% unzip greengrass-nucleus-latest.zip -d GreengrassInstaller && rm greengrass-nucleus-latest.zip
% sudo -E java -Droot="/greengrass/v2" -Dlog.store=FILE \
-jar ./GreengrassInstaller/lib/Greengrass.jar \
--aws-region ap-northeast-1 \
--thing-name MyGreengrassCore \
--thing-group-name MyGreengrassCoreGroup \
--thing-policy-name GreengrassV2IoTThingPolicy \
--tes-role-name GreengrassV2TokenExchangeRole \
--tes-role-alias-name GreengrassCoreTokenExchangeRoleAlias \
--component-default-user ggc_user:ggc_group \
--provision true \
--setup-system-service true
Greengrass Core サービスを確認してください。 メモリの使用状況を考慮すると、2GB 以上のメモリを搭載していると良さそうです。
% sudo systemctl status greengrass
● greengrass.service - Greengrass Core
Loaded: loaded (/etc/systemd/system/greengrass.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2022-02-16 05:09:16 UTC; 1 day 2h ago
Main PID: 1454 (sh)
Tasks: 51 (limit: 2197)
Memory: 734.2M
CGroup: /system.slice/greengrass.service
この投稿では自動リソースプロビジョニングを使用しているため、以下の AWS リソースが自動的にプロビジョニングされています。 代わりに、手動リソースプロビジョニングでセットアップすることも可能です。
リソース | 名前 |
---|---|
Thing | MyGreengrassCore |
Thing Group | MyGreengrassCoreGroup |
Thing Policy | GreengrassV2IoTThingPolicy |
Token Exchange Role | GreengrassV2TokenExchangeRole |
Token Exchange Role Alias | GreengrassCoreTokenExchangeRoleAlias |
エッジ推論用 Greengrass コンポーネント登録
推論用 Greengrass コンポーネントを登録するために recipe.yaml
を作成してください。
コンポーネントのレシピに関する詳細は、公式ドキュメントをご参照ください。
RecipeFormatVersion: '2020-01-25'
ComponentName: vgg16-inference-component
ComponentVersion: 1.0.0
ComponentDescription: Inference component for VGG16
ComponentPublisher: Iret
# Arguments to be passed.
ComponentConfiguration:
DefaultConfiguration:
Interval: 60
# Dependencies which will be installed with this component.
ComponentDependencies:
variant.DLR:
VersionRequirement: ">=1.6.5 <1.7.0"
DependencyType: HARD
vgg16-component:
VersionRequirement: ">=1.0.0"
DependencyType: HARD
Manifests:
- Name: Linux
Platform:
os: linux
Lifecycle:
Run:
RequiresPrivilege: true
Script: |
. {variant.DLR:configuration:/MLRootPath}/greengrass_ml_dlr_venv/bin/activate
python3 -u {artifacts:decompressedPath}/vgg16-inference-component-1.0.0/inference.py --interval {configuration:/Interval} --test_dir {work:path}/images/
Artifacts:
- Uri: s3://sagemaker-ml-model-artifacts-123456789012-ap-northeast-1/artifacts/vgg16-inference-component-1.0.0.zip
Unarchive: ZIP
上記の例の Interval
は推論間隔を意味します。
ComponentDependencies
でコンポーネントの依存関係を指定できます。
この例では、以下が指定されている必要があります。
variant.DLR
- SageMaker Neo でコンパイルされたモデルのロードに必要です。詳細については、公式ドキュメントをご参照ください。
- Greengrass Core デバイス上の
/greengrass/v2/work/variant.DLR/greengrass_ml/greengrass_ml_dlr_venv
に Python の仮想環境があります。
vgg16-component
- SageMaker Neo によってコンパイルされたモデル
- SageMaker Edge Manager によって登録されています。
recipe.yaml
を作成したら、 Greengrass コンポーネントを作成してください。
コンポーネントをデプロイする際、 Greengrass Core は S3 からアーティファクトをダウンロードして解凍します。 Greengrass Core はアーティファクトのチェックサムを検証するため、アーティファクトが直接上書きされると、コンポーネントのステータスが破損します。 詳細については、公式ドキュメントをご参照ください。
Greengrass コンポーネントのデプロイ
このステップでは、デプロイするコンポーネントを選択できます。
My components
では、以下を指定してください。
vgg16-inference-component
のレシピには vgg16-component
に対する HARD
依存関係があるため、指定しなくても vgg16-component
がインストールされます。
名前 | 説明 |
---|---|
vgg16-component | SageMaker Edge Manager によってパッケージングされた VGG16 コンポーネント |
vgg16-inference-component | 推論コンポーネント |
Public components
では、以下を指定してください。
vgg16-inference-component
のレシピには variant.DLR
に対する HARD
依存関係があるため、指定しなくても variant.DLR
がインストールされます。
名前 | 説明 |
---|---|
variant.DLR | モデルのロードに必要なコンポーネント |
aws.greengrass.Nucleus | Greengrass Core に必要なコンポーネント |
設定変更はせず Next
を押してください。
設定変更はせず Next
を押してください。
レビュー後、 Deploy
を押してコンポーネントのデプロイを開始してください。
テスト
Greengrass Core で推論をテストするには、以下の手順を実行してください。
- 事前に訓練された PyTorch モデルは、入力形状として4次元テンソル (N, C, H, W) を想定しているため、推論用の画像を Numpy Array に変換します。詳細については、公式ドキュメントをご参照ください。
- 変換したデータを Greengrass Core デバイスの
/greengrass/v2/work/vgg16-inference-component/images/
に転送します。 - Greengrass Core デバイス上の
/greengrass/v2/logs/vgg16-inference-component.log
ファイルを確認します。
以下の Python スクリプトを使用して、画像を Numpy Array に変換できます。
import argparse
import os
from PIL import Image
import numpy as np
import torch
from torchvision import transforms
def load_image_to_tensor(path: str) -> torch.Tensor:
preprocess = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
img = Image.open(path)
tensor_3d = preprocess(img)
return torch.unsqueeze(tensor_3d, 0)
def save(tensor: torch.Tensor, path: str) -> None:
np.save(path, tensor.numpy())
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser()
parser.add_argument('image', type=str)
args, _ = parser.parse_known_args()
return args
if __name__ == '__main__':
args = parse_args()
image = args.image
tensor = load_image_to_tensor(image)
save(tensor, os.path.basename(image) + '.npy')
以下のコマンドでスクリプトを実行してください。
% python convert_img_to_npy.py <YOUR_IMAGE>
変換された Numpy Array データを Greengrass Core デバイスに転送してください。
その後、 /greengrass/v2/logs/vgg16-inference-component.log
で推論結果を確認できます。
% scp xxx.jpg.npy <GREENGRASS_HOST>://greengrass/v2/work/vgg16-inference-component/images/
% ssh <GREENGRASS_HOST>
% tail -f /greengrass/v2/logs/vgg16-inference-component.log
…
2022-02-19T21:32:21.993Z [INFO] (Copier) vgg16-inference-component: stdout. Prediction result of /greengrass/v2/work/vgg16-inference-component/images/keyboard.jpg.npy: ['n03085013', 'computer_keyboard']. {scriptName=services.vgg16-inference-component.lifecycle.Run.Script, serviceName=vgg16-inference-component, currentState=RUNNING}
2022-02-19T21:32:22.257Z [INFO] (Copier) vgg16-inference-component: stdout. Prediction result of /greengrass/v2/work/vgg16-inference-component/images/pen.jpg.npy: ['n03388183', 'fountain_pen']. {scriptName=services.vgg16-inference-component.lifecycle.Run.Script, serviceName=vgg16-inference-component, currentState=RUNNING}
この投稿では、以下の2つの画像を使用しました。
下の推論結果は computer_keyboard
でした。
下の推論結果は fountain_pen
でした。
まとめ
AWS ユーザーは、 IoT Greengrass V2 と SageMaker エコシステムが提供するエッジ推論機能を、簡単に実装できます。
この投稿が、お役に立てば幸いです。
Footnotes
-
https://cacm.acm.org/magazines/2022/1/257437-shrinking-artificial-intelligence/fulltext CACM. Shrinking Artificial Intelligence. ↩
-
https://aws.amazon.com/about-aws/whats-new/2021/11/aws-iot-greengrass-support-windows-devices/ ↩
-
https://docs.aws.amazon.com/sagemaker/latest/dg/common-info-all-im-models.html ↩
-
https://docs.aws.amazon.com/sagemaker/latest/dg/frameworks.html ↩