Amazon Web Services ブログ

Amazon SageMaker に組み込みの物体検出アルゴリズムと AWS DeepLens を使用してエッジで鳥の種を識別する

カスタムの物体検出は、MRI での腫瘍の発見、病気に罹った農作物の特定、鉄道駅ホームの監視など、さまざまな産業やユースケースにとって重要な要素となっています。このブログ記事では、アノテーションが付けられた公開データセットに基づいて鳥を識別します。このタイプのモデルは、さまざまな方法で使用できます。建設プロジェクトの環境調査の自動化で使用したり、バードウォッチングの時に鳥愛好家が使用したりすることができます。また、このモデルを実用的な例として利用し、独自のユースケースの新しいアイデアを生み出すこともできます。

この例では、Amazon SageMaker が提供している組み込みの物体検出アルゴリズムを使用します。Amazon SageMaker は、エンドツーエンドの機械学習 (ML) プラットフォームです。組み込みアルゴリズムを使用することで、開発者は TensorFlow や MXNet などの低レベルの ML フレームワークの使用に関する専門知識を必要とせずに機械学習を加速させることができます。モデルは、Amazon SageMaker の完全に管理されたオンデマンドトレーニングインフラストラクチャでトレーニングします。AWS IoT Greengrass を使用すると、トレーニング済みモデルをクラウドまたはエッジで簡単にホストすることができます。

カスタムの物体検出をエッジで使用する方法を示すために、トレーニング済みモデルを開発者向けの世界初の深層学習対応ビデオカメラである AWS DeepLens にデプロイする方法も示します。AWS DeepLens により、開発者は文字どおり完全にプログラム可能なビデオカメラ、チュートリアル、コード、および深層学習スキルを向上させるよう設計された事前トレーニング済みのモデルを使って深層学習を利用できます。

次の図は、鳥の識別ソリューションの構築方法の概要を示しています。

データセットの理解

CUB 200-2011 鳥類データセットには、200 種の鳥の種にわたる 11,788 枚の画像が含まれています (元の技術レポートはこちらにあります)。それぞれの種には約 60 枚の画像が付属しており、一般的なサイズは約 350 ピクセル × 500 ピクセルです。鳥の部分のアノテーションとして、バウンディングボックスが提供されています。推奨されるトレーニング/テストの分割は与えられますが、画像サイズデータは与えられていません。

画像データセットの準備

Amazon SageMaker の物体検出アルゴリズムに画像データを提供する最も効率的な方法は、RecordIO 形式を使用することです。MXNet には、データセット用の RecordIO ファイルを作成するための im2rec.py というツールがあります。このツールを使用するには、一連の画像を記述するリストファイルを用意します。

物体検出データセットでは、Amazon SageMaker は、バウンディングボックスを、フル画像に対するボックスのコーナーの比率である xmin、ymin、xmax、ymax で記述する必要があります。CUB データセットのバウンディングボックスは、代わりに x、y、ピクセル単位で表した幅、高さを指定します。次の図を参照して、メタデータの違いを理解してください。

この食い違いに対処するために、各画像のサイズを取得し、絶対バウンディングボックスを変換して画像サイズを基準とした寸法を設定します。次の例で、データセットのボックス寸法は黒色で表示され、RecordIO に必要な寸法は緑色で表示されています。

次の Python コードスニペットは、元のバウンディングボックスの寸法を im2rec で必要な寸法に変換した方法を示しています。完全なコードについては、サンプルの Amazon SageMaker ノートブックを参照してください。

# Amazon SageMaker の組み込み物体検出アルゴリズムが要求する形式で 
# バウンディングボックスを定義する。
# xmin/ymin/xmax/ymax パラメータは、 
# 画像の総ピクセルサイズに対する比率で指定する

df['header_cols'] = 2 # ヘッダ列の数とラベル幅
df['label_width'] = 5 # ラベル列: class, xmin, ymin, xmax, ymax

df['xmin'] =  df['x_abs'] / df['width']
df['xmax'] = (df['x_abs'] + df['bbox_width']) / df['width']
df['ymin'] =  df['y_abs'] / df['height']
df['ymax'] = (df['y_abs'] + df['bbox_height']) / df['height']

リストファイルを作成すると、次のコマンドを実行することで、im2rec ユーティリティを使用して RecordIO ファイルを作成することができます。

python im2rec.py --resize 256 --pack-label birds CUB_200_2011/images/

RecordIO ファイルは、作成された後、以下の Python コードを使用して、物体検出アルゴリズムへの入力として Amazon S3 にアップロードされます。

train_channel      = prefix + '/train'
validation_channel = prefix + '/validation'

sess.upload_data(path='birds_ssd_sample_train.rec',
                 bucket=bucket,
                 key_prefix=train_channel)
sess.upload_data(path='birds_ssd_sample_val.rec',
                 bucket=bucket,
                 key_prefix=validation_channel)

Amazon SageMaker の組み込みアルゴリズムを使用した物体検出モデルのトレーニング

Amazon S3 で画像が利用可能になったので、次の手順はモデルをトレーニングすることです。物体検出ハイパーパラメータのドキュメントはこちらから入手できます。この例では、いくつか興味深いハイパーパラメータがあります。

  • クラスの数とトレーニングサンプル。
  • バッチサイズ、エポック、画像サイズ、事前トレーニング済みモデル、およびベースネットワーク。

Amazon SageMaker の物体検出アルゴリズムでは、モデルを ml.p3.2xlarge などの GPU インスタンスタイプでトレーニングする必要があります。以下は、Estimator を作成し、ハイパーパラメータを設定するための Python コードスニペットです。

od_model = sagemaker.estimator.Estimator(
                 training_image,
                 role,
                 train_instance_count=1,
                 train_instance_type='ml.p3.2xlarge',
                 train_volume_size = 50,
                 train_max_run = 360000,
                 input_mode= 'File',
                 output_path=s3_output_location,
                 sagemaker_session=sess)  

od_model.set_hyperparameters(
                 base_network='resnet-50',
                 use_pretrained_model=1,
                 num_classes=5,
                 mini_batch_size=16,
                 epochs=100,              
                 learning_rate=0.001,
                 lr_scheduler_step='33,67',
                 lr_scheduler_factor=0.1,
                 optimizer='sgd',
                 momentum=0.9,
                 weight_decay=0.0005,
                 overlap_threshold=0.5,
                 nms_threshold=0.45,
                 image_shape=512,
                 label_width=350,
                 num_training_samples=150)

データセットをアップロードし、ハイパーパラメータを設定すると、以下の Python コードを使用してトレーニングを開始することができます。

s3_train_data      = 's3://{}/{}'.format(bucket, train_channel)
s3_validation_data = 's3://{}/{}'.format(bucket, validation_channel)

train_data      = sagemaker.session.s3_input(
                         s3_train_data,
                         distribution='FullyReplicated',
                         content_type='application/x-recordio',
                         s3_data_type='S3Prefix')
validation_data = sagemaker.session.s3_input(
                         s3_validation_data,
                         distribution='FullyReplicated',
                         content_type='application/x-recordio',
                         s3_data_type='S3Prefix')

data_channels = {'train': train_data, 'validation': validation_data}

od_model.fit(inputs=data_channels, logs=True)

ml.p3.2xlarge インスタンスタイプでの 5 つの種のサブセットの場合、約 11 分で 100 エポックについて 70 パーセント以上の精度を得ることができます。

AWS CLI、ノートブック、または Amazon SageMaker コンソールを使用してトレーニングジョブを作成できます。

Amazon SageMaker エンドポイントを使用してモデルをホストする

モデルのトレーニングが終わったら、Amazon SageMaker でホストします。CPU インスタンスを使用しますが、GPU インスタンスを使用することもできます。Amazon SageMaker ノートブックからのデプロイには、次の 1 行の Python コードが必要です。

object_detector = od_model.deploy(
                     initial_instance_count = 1,
                     instance_type = 'ml.m4.xlarge')

モデルをテストする

モデルのエンドポイントが使用可能になった後、モデルがまだ表示していない画像を渡して、鳥がどれほどよく検出されているかを確認できます。visualize_detections 関数については、サンプルのノートブックを参照してください。鳥の画像への URL が指定された場合、エンドポイントを起動し、予測された鳥の種とそれらのバウンディングボックスのセットを取得し、結果を視覚化する Python コードは以下のとおりです。

b = ''
with open(filename, 'rb') as image:
    f = image.read()
    b = bytearray(f)

endpoint_response = runtime.invoke_endpoint(
                                 EndpointName=ep,
                                 ContentType='image/jpeg',
                                 Body=b)
results    = endpoint_response['Body'].read()
detections = json.loads(results)

visualize_detection(filename,
                    detections['prediction'],
                    OBJECT_CATEGORIES, thresh)

以下は、アオカケスの画像のサンプル結果です。

AWS DeepLens を使用してモデルをエッジで実行する

ユースケースによっては、Amazon SageMaker がホストするエンドポイントで十分な展開メカニズムとなるでしょうが、エッジでリアルタイムの物体検出を必要とするユースケースも数多くあります。鳥類保護区にある電話ベースのアシスタントアプリを想像してみてください。保護区を歩き回って、アプリを鳥に向けると即座にその種についての詳細が得られます (その鳥の鳴き声を聞く、生息地を理解するなど)。今、見た鳥を推測する必要はもうありません。

AWS DeepLens を使用すると、深層学習をエッジで試すことができ、開発者はトレーニングしたモデルを簡単にデプロイし、Python コードを使用して興味深いアプリケーションを思いつくことができます。この例の鳥の識別については、鳥の餌箱を見下ろすキッチンの窓の横に AWS DeepLens デバイスを取り付けることができます。このデバイスは、検出した鳥のトリミング画像を Amazon S3 に送信することができます。あなたの携帯電話へテキストを送って、どんな鳥が訪れたかを知らせることさえできます。

前回のブログ記事では、AWS DeepLens でカスタム画像分類モデルをデプロイする方法について説明しました。カスタムの物体検出モデルには、2 つの違いがあります。

  • モデルのアーティファクトは、デプロイする前に変換する必要があります。
  • モデルは、ロードする前に最適化されなければなりません。

それでは、これらの違いのそれぞれについてもっと詳しく見てみましょう。

AWS DeepLens にデプロイする前にモデルのアーティファクトを変換する

Amazon SageMaker によって作成されたカスタムの物体検出モデルの場合、モデルを AWS DeepLens にデプロイする場合は追加の手順を実行する必要があります。MXNet は、モデルを変換するためのユーティリティ機能を提供しています。変換を始めるには、まず GitHub リポジトリを複製します。

git clone https://github.com/apache/incubator-mxnet

次の手順は、トレーニングの結果として Amazon S3 に保存されたモデルのアーティファクトのコピーをダウンロードすることです。実際のアーティファクト (パラメータファイル、シンボルファイル、ハイパーパラメータファイル) を抽出し、トレーニングで使用された基本ネットワークおよび画像サイズを反映するようにそれらの名前を変更します。以下は、変換を実行するために使用できる bash スクリプトのコマンドです。

BUCKET_AND_PREFIX=s3://<your-bucket>/<your-prefix>/output
TARGET_PREFIX=s3://<your-deeplens-bucket>/<your-prefix>
rm -rf tmp && mkdir tmp
aws s3 cp $BUCKET_AND_PREFIX/model.tar.gz tmp
gunzip -k -c tmp/model.tar.gz | tar -C tmp -xopf –
mv tmp/*-0000.params tmp/ssd_resnet50_512-0000.params
mv tmp/*-symbol.json tmp/ssd_resnet50_512-symbol.json

内容を抽出して名前を変更したら、変換ユーティリティを起動します。

python incubator-mxnet/example/ssd/deploy.py --network resnet50 \
  --data-shape 512 --num-class 5 --prefix tmp/ssd_

これで、元のファイルを削除し、変換したアーティファクトを含む新しい圧縮 tar ファイルを作成することができます。  新しい AWS DeepLens 物体検出モデルをインポートするときに使用できる、新しいモデルのアーティファクトのファイルを Amazon S3 にコピーします。

rm tmp/ssd_* && rm tmp/model.tar.gz
tar -cvzf ./patched_model.tar.gz -C tmp \
  ./deploy_ssd_resnet50_512-0000.params \
  ./deploy_ssd_resnet50_512-symbol.json \
  ./hyperparams.json
aws s3 cp patched_model.tar.gz $TARGET_PREFIX-patched/

パッチを適用したモデルの保存先バケットでは、バケット名に「deepplens」という単語が含まれている必要があります。そうでないと、AWS DeepLensコンソールでモデルをインポートするときにエラーが発生します。モデルのアーティファクトにパッチを適用するための完全なスクリプトは、こちらにあります。

AWS DeepLens で AWS Lambda 関数からモデルを最適化する

AWS DeepLens プロジェクトは、トレーニングを受けたモデルと AWS Lambda 関数で構成されています。AWS DeepLens で AWS IoT Greengrass を使用して、推論 Lambda 関数は次の 3 つの重要な機能を実行します。

  • ビデオストリームから画像をキャプチャする。
  • デプロイされた機械学習モデルに対して、画像を使用して推論を実行する。
  • 結果を、AWS IoT と出力ビデオストリームの両方に提供する。

AWS IoT Greengrass を使用すると、AWS Lambda 関数をローカルで実行し、埋め込みソフトウェアの開発の複雑さを軽減できます。推論 Lambda 関数の作成と公開の詳細については、こちらのドキュメントを参照してください。

Amazon SageMaker によって作成されたカスタムの物体検出モデルを使用する場合、AWS DeepLens 推論 Lambda 関数に追加の手順があります。推論関数は、モデルを使用して推論を実行する前に MXNet のモデルオプティマイザを呼び出す必要があります。以下は、モデルを最適化して読み込むための Python コードです。

ret, model_path = mo.optimize('deploy_ssd_resnet50_512',
                              input_width, input_height)
model = awscam.Model(model_path, {'GPU': 1})

AWS DeepLens でモデル推論を実行する

AWS Lambda 関数からのモデル推論は、Amazon SageMaker がホストするエンドポイントを使用してモデルを呼び出すための前述した手順と非常によく似ています。以下は、AWS DeepLens ビデオカメラが提供するフレーム内で鳥を見つける Python コードの一部です。

frame_resize = cv2.resize(frame, (512, 512))

# 推論エンジンを介して画像を実行し、
# パーサー API を使用して結果を解析する。 doInference の出力を取得して手動で解析することは可能ですが、
# これは ssd モデルであるため、
# 単純な API が提供されています。
parsed_inference_results = model.parseResult(
                                 model_type,
                                 model.doInference(frame_resize))

この物体検出モデルによって AWS DeepLens で使用するための完全な推論 Lambda 関数は、ここにあります。

結論

このブログ記事では、Amazon SageMaker の組み込み物体検出アルゴリズムを使用して、一般に利用可能なデータセットに基づいて鳥類を検出するカスタムモデルを作成する方法を説明しました。また、AWS DeepLens を使用して、ホストされている Amazon SageMaker エンドポイントおよびエッジでそのモデルを実行する方法についても説明しました。この例を複製して、独自のユースケースに合わせて拡張することができます。新しい方法でこのコードをどのように適用できるかについて、皆さんのご意見をお聞きしたいです。コメントを追加することで、ぜひフィードバックをお知らせください。


著者について

Mark Roy は、機械学習を専門とするソリューションアーキテクトであり、顧客やパートナーがコンピュータビジョンソリューションを設計するのを支援することに特に関心を持っています。  余暇には、Mark はバスケットボールのプレー、コーチ、フォローするのが好きです。