推論コンテナの用意
S3へモデルのアップロード
使用するAIモデルのデータはS3にアップロードしておく必要があります。今回は重みデータ以外にmodelとutilフォルダのコードも含めてtar.gz形式でアップロードしておきます。アップロードしたモデルデータは後ほど推論エンドポイントを作成する際に指定し、推論コンテナを起動する際には自動的にコンテナ内にダウンロードされます。ただし、S3に配置するデータが大きすぎる場合、コンテナのメモリが不足する可能性があるため、AIモデルと重みデータのサイズには注意が必要です。
推論コンテナの実装
Serverless Inferenceで推論するための推論コンテナは、 Amazon ECR(Elastic Container Registry)にデプロイしておく必要があります。公式が提供するテンプレートをベースにして書き換えながら実装します。以下のリンクに詳しい実装例があります。
推論コンテナが必要とする仕様は主に2つあります。
- -/pingへのHTTPリクエストに対する応答(生きている場合はステータス200を返す)
- -/invocationsへのHTTPリクエストに対する応答(推論実行時に呼ばれる)
テンプレート内で提供されている/pingリクエストへの応答はそのまま利用でき、/invocationsリクエストで呼ばれるtransformation()関数の中に、先ほど実装した推論処理を記述します。テンプレートには既に実装されている別の処理がありますので、それを適宜書き換え、関数名を分かりやすいものに変更します。
今回はナンバープレートを黒塗りした画像を、そのままではなく一時的にS3に保存してそのURLを返すようにしています。これはLINE上でBotから画像メッセージを返す際に、画像URLを指定して表示させるためです。
s3 = boto3.resource('s3') image_string = cv2.imencode('.jpg', image_original)[1].tostring() image_name = randomName(15) + ".jpg" s3.Bucket("バケット名").put_object(Key = image_name, Body=image_string) url = S3_path + image_name response = url return flask.Response(response=response, status=200, mimetype="text/plain")
また、S3に配置したAIモデルデータは推論コンテナ起動時に自動的にダウンロードされます。これらのデータはコンテナ内の/opt/ml/model/以下に格納されます。ScoringServiceクラスのget_model()内にモデル読み込みの処理を、predict()内にモデル使用の処理を記述します。これらのコードもテンプレートのものを書き換えながら進めていきましょう。
AWSコンソールでの設定手順
ここまでの手順が完了したら、AWSコンソールで推論エンドポイントを作成していきます。まず、Amazon SageMakerページの左タブから「推論」 > 「モデル」を選択し、「モデルの作成」ボタンをクリックします。
推論コードイメージの場所には、ECRにアップロードした推論コンテナのパスを記載し、アーティファクトの場所にはS3にアップロードしたモデルの重みデータなどのパスを指定します。
モデルの作成が完了したら、「推論」 > 「エンドポイント設定」ページに移動し、「エンドポイント設定の作成」を行います。
サーバーレスで実行する場合、エンドポイントのタイプは「サーバーレス」に設定します。本番稼働用バリアントを作成ボタンから、先ほど作成したモデルを選択します。メモリサイズは最大3GBまで、最大同時実行数は10までに設定します。これらのパラメータは、エンドポイントの作成時にエラーが発生するため注意が必要です。
エンドポイント設定が完了したら、「推論」 > 「エンドポイント」ページに移動し、「エンドポイントの作成」を行います。
エンドポイント設定の欄には先ほど作成した設定が表示されるので、これを選択してエンドポイントを作成します。これで推論エンドポイントの作成は完了です!
フロント側の開発
今回、推論APIを呼び出すフロントエンドはLINE Botで構築しました。詳細な実装内容は割愛しますが、このシステムはAWS Lambda上でホストされています。
ユーザーがLINE上で画像を送信すると、BotはLINEサーバーからバイナリデータとして画像を取得します。この画像データはbase64形式でエンコードされ、その後、推論エンドポイントへのリクエストを実行します。この際、AWS SDKであるboto3を使用し、invoke_endpoint()メソッドに推論エンドポイント名やエンコードされた画像データなどのパラメータを含めてリクエストを送信します。
sagemaker_runtime = boto3.client("sagemaker-runtime") # 推論エンドポイントにリクエスト response = sagemaker_runtime.invoke_endpoint( EndpointName="推論エンドポイント名", Body=image_base64, ContentType="application/json", Accept="application/json" )
このリクエストが推論エンドポイントで処理され、推論コンテナで実装した通り、ナンバープレートが黒塗りされた画像はS3に保存されます。そして、その保存された画像のURLがレスポンスとしてLINE Botに返され、LINE上で画像メッセージとして表示されます。
まとめ
今回は主にAWSのサービスを活用して、物体検知を行うAIシステムの実装について詳細に解説しました。ただし、Amazon SageMakerを使わず、低コストでプロトタイプを作成するためにServerless Inferenceというサーバーレスのアプローチを採用しました。
Serverless InferenceやAWS Lambda、Google Cloud Functionsなどのサーバーレス技術全般に関して言えることですが、APIが一定時間以上呼び出されない場合、次回の起動時にコールドスタートと呼ばれる遅延が発生し、実行時間が延びることがあります。特に今回のケースでは推論コンテナの起動時にモデルや重みのデータをダウンロードする処理があるため、起動時間が長くなりがちです。実際にサービスに組み込む際は、この点が許容されるかどうかは考慮しておいた方が良いでしょう。