SageMakerの物体検出によるオブジェクトカウント
Ground Truthで画像にラベルを付け、SageMakerの物体検出モデルを学習させ、推論結果からオブジェクトをカウントする。
Ground Truthでの画像ラベリングからモデルの学習・デプロイ、推論の実行までを通しで扱います。
この記事内の画像は説明用のものであり、特定の顧客プロジェクトとは関係ありません。
なお、SageMakerの推論エンドポイントはテスト目的での利用にとどめています。

Ground Truthによるラベリング
ラベリングワークフォースの作成
ラベリングを始めるには、まずラベリングワークフォースをセットアップする必要があります。この記事ではプライベートワークフォースを作成します。チームメンバーはCognitoまたはOIDCで認証できます。

ワークフォースが作成されると、招待メールがワーカーに送信されます。このメールにはラベリングポータルへのURLが含まれています。
ラベリングポータルのURLは、SageMaker管理コンソールのPrivate workforce summary > Labeling portal sign-in URLからも取得できます。

ワーカーは招待メールの手順に従ってサインアップし、ラベリングポータルにアクセスする必要があります。

招待メールの例は以下のとおりです。
Hi,
You are invited by [email protected] from <COMPANY> to work on a labeling project.
Click on the link below to log into your labeling project."https://<LABELING_PORTAL_URL>"
You will need the following username and temporary password provided below to login for the first time.User name: <USER_NAME>Temporary password: <PASSWORD>
Once you log in with your temporary password, you will be required to create a new password for your account.After creating a new password, you can log into your private team to access your labeling project.
If you have any questions, please contact us at [email protected].URLにアクセスした後、ワーカーは招待メールに記載されたユーザー名と一時パスワードを入力する必要があります。

その後、一時パスワードを新しいパスワードに変更するよう求められます。

ログインに成功すると、ワーカーはラベリングポータルのトップページにリダイレクトされます。割り当てられたラベリングジョブがこのページに表示されます。

ラベリングジョブの作成
SageMaker管理コンソールに戻り、新しいラベリングジョブの作成を開始します。以下の画像に示すとおり必要な項目を入力します。プロセスを完了させるために、必ずComplete data setupをクリックしてください。
ラベリングジョブを作成した後は削除できません。次のようなコマンドで生成した一意な値を使用してください: uuidgen | tr "[:upper:]" "[:lower:]"。

複雑なラベリングタスクの場合は、Task timeoutパラメータに長めの値を指定することを検討してください。

ラベリングの開始
ラベリングポータルにサインインすると、先ほど作成したラベリングジョブが表示されるはずです。Start workingボタンをクリックして開始します。
ラベリングジョブが一覧に表示されるまで、しばらく時間がかかることがあります。

ジョブの指示に従ってデータセットにラベルを付けます。以下はラベル付けされたデータセットの例です。

すべてのワーカーがタスクを完了したら、ラベリングジョブを停止します。

ラベリング出力の確認
ラベリングジョブが停止すると、最終的な出力が指定したS3バケットに保存されます。物体検出タスクにおいては、manifests/output/output.manifestファイルが重要です。詳細は公式ドキュメントを参照してください。
annotation-tool/annotations/consolidated-annotation/worker-response/manifests/intermediate/output/output.manifesttemp/Ground TruthはAugmented Manifest形式でラベリング結果を生成します。詳細は公式ドキュメントを確認してください。
SageMakerによる学習
ラベリングプロセスが完了したら、SageMakerコンソールを使ってモデルの学習に進みます。学習ジョブを以下のように設定します。
- Job settings
- Job name: 一意な値を使用します(例:
uuidgen | tr "[:upper:]" "[:lower:]")。 - Algorithm source: SageMaker built-in algorithm
- Choose an algorithm:
- Algorithm: Vision - Object Detection (MXNet)
- Input mode:
Pipe - Resource configuration
- Instance type:
ml.p2.xlargeのようなGPUインスタンスを使用します。 - SageMakerの物体検出アルゴリズムをサポートするのはGPUインスタンスのみです。
- Hyperparameters
num_classes: オブジェクトクラスの数を設定します(本記事では1)。num_training_samples: マニフェストファイルの行数と同じ値にします。- Input data configuration
- Training channel
- Channel name:
train - Input mode:
Pipe - Content type:
application/x-recordio - Record wrapper:
RecordIO - Data source: S3 (Augmented Manifest File)
- Attribute names:
source-refやバウンディングボックスのデータキーなどの属性を含めます。 - S3 location: 学習データのマニフェストファイルのS3 URIを指定します。
- Validation channel
- Channel name:
validation - Output data configuration
- S3 location: モデルアーティファクトを保存するS3 URIを指定します。

Augmented Manifest形式を利用することで、追加のRecordIOファイルを作成することなくPipe入力モードとRecordIOラッパー型を使用できます。詳細は公式ドキュメントを参照してください。
推論
学習ジョブからモデルを作成する
完了した学習ジョブからモデルを作成するには、SageMakerコンソールでCreate modelをクリックします。

モデルのデプロイ
モデルを作成したら、Create endpointをクリックしてデプロイします。コスト効率よく低頻度で使用する場合は、サーバーレスエンドポイントの利用を検討してください。

リクエストの送信
エンドポイント詳細ページでSageMaker推論エンドポイントを確認します。このエンドポイントにはcurl、Postman、独自のアプリケーションなどからアクセスできます。
SageMakerの推論エンドポイントを本番ワークロードに直接使用することは推奨されません。この例はあくまでテスト目的でのエンドポイント使用方法を示しています。

例: Postmanの設定
AWS Signature V4による認証には、以下のパラメータを使用します。
- AccessKey
- SecretKey
- Session Token: 永続的な認証情報ではなく、一時的な認証情報を使用してください。
- AWS Region: SageMakerエンドポイントのリージョン。
- Service Name:
sagemaker

リクエストにAccept: application/jsonヘッダーを設定します。

学習済みモデルはバイナリの画像入力を期待するため、画像がバイナリ形式で渡されるようにしてください。

例: AWS SDK(boto3)の使用
boto3のinvoke_endpoint APIを使って、プログラムから推論を実行することもできます。以下はスクリプトの例です。
import json
import boto3
# Initialize SageMaker runtime clientruntime = boto3.client('sagemaker-runtime')
# Define endpoint and input detailsendpoint_name = '<YOUR_ENDPOINT_NAME>'content_type = 'application/x-image'payload = None
# Read the image file in binary modewith open('/path/to/image.jpg', 'rb') as f: payload = f.read()
# Invoke the endpointresponse = runtime.invoke_endpoint( EndpointName=endpoint_name, ContentType=content_type, Body=payload)
# Parse and display the responsebody = response['Body'].read()predictions = json.loads(body.decode())print(json.dumps(predictions, indent=2))
# Save the response to a filewith open('./response.json', 'w') as f: json.dump(predictions, f, indent=2)レスポンスの確認
レスポンスはJSON形式で返され、以下を含みます。
- クラスラベルID
- 信頼度スコア
- バウンディングボックスの座標
バウンディングボックスの座標は実際の画像サイズに対する相対値です。詳細は公式ドキュメントを参照してください。
{ "prediction": [ [ 0.0, 0.9953756332397461, 0.3821756839752197, 0.007661208510398865, 0.525381863117218, 0.19436971843242645 ], [ 0.0, 0.9928023219108582, 0.3435703217983246, 0.23781903088092804, 0.5533013343811035, 0.6385164260864258 ], [ 0.0, 0.9911478757858276, 0.15510153770446777,... 0.9990172982215881 ] ]}レスポンスの可視化
推論結果を視覚的に解釈するには、Jupyter Notebookとmatplotlibを組み合わせて使用できます。
以下のPythonスクリプトは、入力画像にバウンディングボックスと注釈を重ねて表示する方法を示しています。
import json
import matplotlib.patches as patchesimport matplotlib.pyplot as pltfrom PIL import Image
# Configure plotplt.figure()axes = plt.axes()
# Read an imageim = Image.open('/path/to/image.jpg')# Display the imageplt.imshow(im)
# Read SageMaker inference predictionswith open('response.json') as f: predictions = json.loads(f.read())['prediction']
# Set initial countcount = 0
# Create rectanglesfor prediction in predictions: score = prediction[1] if score < 0.2: continue
# Count up count += 1
x = prediction[2] * im.width y = prediction[3] * im.height width = prediction[4] * im.width - x height = prediction[5] * im.height - y
rect = patches.Rectangle((x, y), width, height, linewidth=1, edgecolor='r', facecolor='none') axes.annotate(count, (x + width / 2, y + height / 2), color='yellow', weight='bold', fontsize=18, ha='center', va='center') axes.add_patch(rect)
# Display the rectanglesplt.show()このスクリプトは、JSON形式の予測レスポンスを読み込み、バウンディングボックスの座標を抽出して、検出されたオブジェクトの周囲に矩形を描画します。各バウンディングボックスには、対応するオブジェクトのカウント番号が注釈として付けられます。

まとめ
Ground Truthで画像にラベルを付け、SageMakerの物体検出モデルを学習させ、テスト用エンドポイントに対して推論を実行したところ、matplotlibでカウントおよび可視化できるバウンディングボックスが得られました。可視化スクリプト内のscore < 0.2というフィルタは、地味ながら大きな役割を果たしています。オブジェクトカウントの精度は、何を検出とみなすかを決める信頼度しきい値の設定次第であり、そのしきい値は1枚のテスト画像でたまたま妥当に見えるデフォルト値のままにせず、実際の検証データに対してチューニングする必要があります。また、このモデルはプライベートワークフォースによるGround Truthのラベルで学習されているため、カウントの精度は最終的に、重なり合ったオブジェクトや部分的にしか見えないオブジェクトをワーカーがどれだけ一貫してアノテーションできたかに左右されます。このパイプラインが大規模に生成する数値を信頼する前に、その点を確認しておく価値があります。
Related posts
LambdaなしでAPI GatewayからSageMakerを呼び出す
API Gatewayの統合リクエストをSageMaker推論エンドポイントに直接接続し、リクエストパスからLambda関数を完全に排除する。
Amazon SageMaker 入門: 組み込みアルゴリズムを使う
SageMaker Studioと組み込みアルゴリズムを使って、Irisデータセットでk-NN分類器を学習・デプロイします。
Cognito User PoolsとOIDCでSlackサインインを実装する
Cognito user poolをOIDC経由でSlackと連携させ、"Sign in with Slack"をAmplifyでNext.jsアプリに組み込みます。
Lambda Web AdapterでFastAPIをAWS Lambdaにデプロイする
Lambda Web Adapterを使うと、FastAPIで書いたAPIバックエンドをコンテナのまま単一のLambda関数にデプロイできます。
API Gateway WebSocket:モック統合の実装
バックエンドのLambdaを一切使わず、モック統合のみでAPI Gateway WebSocket APIを構築し、あらかじめ用意されたレスポンスを返します。
