Amazon Web Services ブログ

Amazon SageMaker と Amazon Augmented AI によるオブジェクトの検出とモデルの再トレーニング

ヘルスケア、メディア、ソーシャルメディアプラットフォームなどの業界では、画像分析ワークフローを使用して、画像内のオブジェクトやエンティティを識別し、画像全体を把握しています。たとえば、e コマースのウェブサイトでは、画像内に存在するオブジェクトを使って関連する検索結果を表示することも可能です。画像がぼやけていたり、微妙なニュアンスがある場合、画像分析が困難な場合があります。このような場合には、人による判断で機械学習 (ML) のループを終了させたり、画像についてアドバイスする必要が出てくるでしょう。

この投稿では、Amazon SageMaker を使用して物体検出の ML モデルを構築、トレーニング、デプロイします。さらに Amazon Augmented AI (Amazon A2I) を使って、画像内で見つけたオブジェクトをレビュー担当者が識別またはレビューできるようにするカスタムワーカーテンプレートを作成し、レンダリングできるようにします。完全マネージドサービスの Amazon SageMaker では、開発者やデータサイエンティストが ML モデルを迅速に構築、トレーニング、デプロイできます。Amazon SageMaker により ML 処理の各ステップでの面倒な作業から解放されるため、高品質なモデルの開発がさらに容易になります。Amazon A2I は、お客様がヒューマンレビューワークフローを構築し、ML モデルの予測をレビューおよび検証するのに役立つ完全マネージドサービスです。

さらに Amazon Rekognition を使ってオブジェクトを検出し、事前に定義したクラスのセットからオブジェクトを識別したり、Amazon Rekogition Custom Labels でカスタムモデルをトレーニングします。ご自身のデータを持ち込むだけで、ビジネスニーズに固有の画像内のオブジェクトやシーンを検出することができます。

ヒューマンワークフローが必要となる他の一般的なユースケースには、画像や動画のコンテンツモデレーション、さらにドキュメント、翻訳、感情分析からのテキストやエンティティの抽出があります。ML モデルで不適切なコンテンツを識別したりエンティティを抽出したりできますが、ユースケースに基づいたモデルの予測を検証するには人の介入が必要になることもあります。Amazon A2I は、これらのヒューマンワークフローを迅速に作成する支援を行います。

Amazon A2I を使って、ML 予測のランダムなサンプルをヒューマンレビュー担当者に送信することもできます。これらの結果を使い、利害関係者にモデルのパフォーマンスを通知し、モデルの予測を監査できます。

前提条件

この投稿では、次の前提条件が必要です。

チュートリアルの概要

このソリューションを実装するには、次の手順を実行してください。

  1. Amazon SageMaker でオブジェクト検出モデルをホストする。
  2. ワーカータスクテンプレートを作成する。
  3. プライベートワークチームを作成する。
  4. ヒューマンレビューワークフローを作成する。
  5. Amazon SageMaker エンドポイントを呼び出す。
  6. ヒューマンレビューを完了する。
  7. 段階的トレーニングの JSON 出力を処理する。

この投稿では、us-east-1 でチュートリアルを実行しましたが、Amazon A2I は多くのリージョンでご利用いただけます。詳細については、リージョン表をご参照ください。

ステップ 1: Amazon SageMaker でオブジェクト検出モデルをホストする

このステップは付属の Jupyter ノートブックで行います。エンドポイントを設定するには、次の Python コードを入力します(これには数分かかる場合があります)。

# provided trained model in the public bucket
source_model_data_s3_uri = 's3://aws-sagemaker-augmented-ai-example/model/model.tar.gz'

!aws s3 cp {source_model_data_s3_uri} {MODEL_PATH}/model.tar.gz

model_data_s3_uri = f'{MODEL_PATH}/model.tar.gz'

timestamp = time.strftime("%Y-%m-%d-%H-%M-%S", time.gmtime())
endpoint_name = 'DEMO-object-detection-augmented-ai-' + timestamp

# the docker image for the SageMaker built-in object detection algorithm
image = sagemaker.amazon.amazon_estimator.get_image_uri(region, 'object-detection', repo_version='latest')

# loading up a Model object from the provided trained model 
model = sagemaker.model.Model(model_data_s3_uri,
                              image,
                              role = role,
                              predictor_cls = sagemaker.predictor.RealTimePredictor,
                              sagemaker_session = sess)
# deploying the model into one ml.m4.xlarge instance
object_detector = model.deploy(initial_instance_count = 1,
                               instance_type = 'ml.m4.xlarge',
                               endpoint_name = endpoint_name)
# defining the input content type.We will be sending images of jpeg format to the endpoint.                               
object_detector.content_type = 'image/jpeg' 

エンドポイントを起動して実行すると、 Amazon SageMaker コンソールInService のステータスが表示されます。(この URL でデモを行った us-east-1 のコンソールに移動しますが、Amazon A2I はもっと多くのリージョンでご利用いただけますので、ご自身のリージョンに切り替えてください。)

オブジェクト検出がどのように見えるかを確認するには、次のコードを入力します。予測クラスと予測確率は、付属の Jupyter ノートブックで定義されているヘルパー関数 visualize_detectionload_and_predict を使ってバウンディングボックスとともに視覚化されます。

test_photos_index = ['980382', '276517', '1571457']

if not os.path.isdir('sample-a2i-images'):
    os.mkdir('sample-a2i-images')
    
for ind in test_photos_index:
    !curl https://images.pexels.com/photos/{ind}/pexels-photo-{ind}.jpeg > sample-a2i-images/pexels-photo-{ind}.jpeg
    
test_photos = ['sample-a2i-images/pexels-photo-980382.jpeg', # motorcycle
               'sample-a2i-images/pexels-photo-276517.jpeg', # bicycle
               'sample-a2i-images/pexels-photo-1571457.jpeg'] # sofa
               
results, detection_filtered, f = load_and_predict(test_photos[1], object_detector, threshold=0.2)    

次のスクリーンショットは、ラベルとバウンディングボックスを含む画像の出力を示しています。

オブジェクト検出トレーニングノートブックでは、デモ用のこの SSD モデルのトレーニングが十分ではありません。モデルは画像内の自転車を識別しますが、現代のコンピュータービジョンにおいて信頼できる予測としては、0.245 の確率は低いと考えられます。さらに、バウンディングボックスは前輪とサドルを含んでおらず、オブジェクトのローカライズは正確とはいえません。ただし、トレーニングが十分ではないこのモデルは、モデルが信頼度の高い予測を行わない場合にヒューマンレビュー担当者が必要とされるよい例ではあります。

ステップ 2: ワーカータスクテンプレートを作成する

Amazon A2I を使用して、ヒューマンレビューを ML ワークフローに組み込むことができます。この投稿では、Amazon A2I を Amazon SageMaker がホストするエンドポイントと統合するため、カスタムタスクを作成する必要があります。カスタムタスクタイプを使用する場合、Amazon A2I ランタイム API を使ってヒューマンループを作成および開始し、ワーカータスクテンプレートを使用してレビューが必要なデータを送信します。詳細については、カスタムタスクタイプで Amazon Augmented AI を使用するをご参照ください。

Crowd HTML 要素は、聞きたい質問に合わせて調整できるタスクウィジェットとデザイン要素を提供するウェブコンポーネントです。これらの Crowd 要素を使用してカスタムワーカーテンプレートを作成し、それを Amazon A2I ヒューマンレビューワークフローと統合して、ワーカーコンソールや手順をカスタマイズできます。GitHub リポジトリには 60 個を超えるカスタムタスクテンプレートが用意されており、そのままで、あるいは独自のテンプレートをカスタマイズするためのはじめの一歩として使用できます。オブジェクト検出のユースケースの場合、レビュー担当者は通常、ラベルを選択してバウンディングボックスを描く必要があります。この投稿では、リポジトリからタスクテンプレートのサンプルの 1 つである bounding-box.liquid.html を使って、カスタマイズをいくつか行います。このテンプレートには、ラベル付け手順、ラベル付け機能(描画、拡大、縮小、ラベル検索)が含まれ、指定された Amazon S3パス から画像を読み取ります。作業者がバウンディングボックスを最初から描く代わりに、テンプレートをカスタマイズし、initial-valueバウンディングボックスを表示して、ML モデルで予測したバウンディングボックスから開始できるようにすることも可能です。

このステップは付属の Jupyter ノートブックで行います。Amazon A2I コンソールでカスタムワーカーテンプレートを作成するには、次の手順を実行します。

  1. ワーカータスクテンプレートに移動します。
  2. [テンプレートを作成] を選択します。
  3. [テンプレート名] にはアカウントのリージョン内で一意の名前、たとえば a2i-demo-object-detection-ui を入力します。
  4. [テンプレートタイプ] で、[カスタム] を選択します。
  5. [テンプレートエディタ] で、bounding-box.liquid.html のサンプルタスク HTML テンプレートを入力します。
    1. PASCAL VOC データセットとオブジェクト検出モデルに含まれるクラス( ['aeroplane', 'bicycle', 'bird', 'boat', 'bottle', 'bus', 'car', 'cat','chair', 'cow', 'diningtable', 'dog', 'horse', 'motorbike', 'person','pottedplant', 'sheep', 'sofa', 'train', 'tvmonitor'])に従って、エディターで ラベル変数を変更します。
  6. [作成] をクリックします。

ステップ 3: プライベートワークチームを作成する

Amazon A2I を使って、プライベートワーカーにレビューを簡単にルーティングできます。Amazon Mechanical Turk を介した ML 関連作業の経験のある、50 万人を超える独立した契約スタッフから人材を選択することも可能です。あるいは、データに機密性や特別なスキルが必要な場合でも、品質とセキュリティ手順に関し AWS があらかじめ選出した、レビュープロジェクトの経験を持つ実績のあるベンダーがワークフォースとして待機しています。

どちらのワークフォースタイプを選択しても、Amazon A2I が作業者へのタスク送信を処理します。この記事では、プライベートワークフォースを使ってワークチームを作成し、自分自身をチームに追加して Amazon A2I ワークフローをプレビューします。

プライベート作業者を作成して管理するには、Amazon SageMaker コンソールのラベル付けワークフォースページを使用できます。そこにある指示に従うと、作業員の E メールを入力、または Amazon Cognito ユーザープールから既存のワークフォースをインポートすることでプライベートワークフォースを作成できます。

既に Amazon SageMaker Ground Truth 用に作成したワークチームがある場合は、Amazon A2I で同じワークチームを使用して次のセクションにスキップできます。

このステップは付属の Jupyter ノートブックで行うことはできません。

プライベートワークチームを作成するには、以下の手順を実行します。

  1. Amazon SageMaker コンソールの [ラベル付けワークフォース] に移動します。
  2. [プライベート] タブで、[プライベートチームを作成] を選択します。
  3. [E メールで新しい作業者を招待] を選択します。
  4. この記事では、メールアドレスを入力して、ドキュメント処理タスクに取り組みます。

[メールアドレス] ボックスには、カンマ区切りで最大 50 個のメールアドレスのリストを入力できます。

  1. 組織名と連絡先メールアドレスを入力します。
  2. [プライベートチームを作成する] を選択します。

プライベートチームを作成すると、招待メールが届きます。以下のスクリーンショットは E メールの例です。

リンクをクリックしてパスワードを変更すると、このチームの確認済み作業者として登録されます。次のスクリーンショットは、[プライベート] タブでの更新された情報を示しています。

一人だけのチームの準備が整ったところで、ヒューマンレビューワークフローを作成できます。

付属の Jupyter ノートブックYOUR_WORKTEAM_ARN を、作成したワークチームの ARN に置き換えます。

WORKTEAM_ARN = 'YOUR_WORKTEAM_ARN'

ステップ 4: ヒューマンレビューワークフローを作成する

ヒューマンレビューワークフローはフロー定義とも呼ばれます。フロー定義を使用してヒューマンワークチームを設定し、レビュータスクを実行する方法に関する情報を提供します。フロー定義で複数のヒューマンループを作成できます。

このステップは付属の Jupyter ノートブックで行います。Amazon A2I コンソールでこれを行うには、次の手順を実行します。

  1. ヒューマンレビューワークフロー移動する
  2. [ヒューマンレビューワークフローを作成] を選択します。
  3. ワークフロー設定」セクションで、[名前] に一意のワークフロー名(a21-demo-1 など)を入力します。
  4. [S3 バケット] で、ヒューマンレビュー結果を保存する S3 バケット を入力します。

バケットはワークフローと同じリージョンに配置する必要があります。たとえば、a2i-demos というバケットを作成する場合は、パス s3://a2i-demos/ を入力します。

  1. [IAM ロール] で、ドロップダウンメニューから [新しいロールを作成] を選択します。

Amazon A2I は自動的にロールを作成できます。

  1. [指定する S3 バケット] で、[特定の S3 バケット] を選択します。
  2. 前に指定した S3 バケット(a2i-demos など)を入力します。
  3. [作成] をクリックします。

ロールの作成が完了するとその確認が表示され、IAM ロールのドロップダウンメニューにはそのロールが事前入力されています。

  1. [タスクタイプ] で、[カスタム] を選択します。

次の手順では、前に作成した UI テンプレートを選択します。

  1. ワーカータスクテンプレート」セクションで、[独自のテンプレートを使用] を選択します。
  2. [テンプレート] で、作成したテンプレートを選択します。
  3. [タスクの説明] には、タスクについての説明を簡潔に入力します。
  4. 作業者」セクションで、[プライベート] を選択します。
  5. [プライベートチーム] では、以前作成したワークチームを選択します。
  6. [作成] をクリックします。

人間によるレビューのワークフローのページにリダイレクトされ、次のスクリーンショットのような確認メッセージが表示されます。

次のセクションでヒューマンループを構成するために使用する、新しい人間によるレビューのワークフローの ARN を記録します。

ステップ 5: Amazon SageMaker エンドポイントを呼び出す

Amazon A2I ヒューマンレビューのワークフローを設定したので、Amazon SageMaker でオブジェクト検出エンドポイントを呼び出して、ヒューマンループを開始する準備ができました。このユースケースでは、検出されたオブジェクトに対してモデルから返された予測確率の最高スコアが 50% (SCORE_THREHOLD)に満たない場合にのみ、ヒューマンループを開始します。ロジック(次のコードを参照)を少し利用すると、load_and_predict ヘルパー関数を使って Amazon SageMaker エンドポイントへの各呼び出しの応答を確認できます。予測確率の最高スコアが 50% 未満の場合は、ヒューマンループを作成します。

ヒューマンループを使用して、ヒューマンレビューワークフローを開始します。ヒューマンループがトリガーされると、フロー定義で指定されているように、ヒューマンレビュータスクが作業者に送信されます。

このステップは付属の Jupyter ノートブックで行います。

human_loops_started = []
SCORE_THRESHOLD = .50
for fname in test_photos:
    # Call SageMaker endpoint and not display any object detected with probability lower than 0.4.
    response, score_filtered, fig = load_and_predict(fname, object_detector, threshold=0.4)
    # Sort by prediction score so that the first item has the highest probability
    score_filtered.sort(key=lambda x: x[1], reverse=True)

    # Our condition for triggering a human review
    # if the highest probability is lower than the threshold, send it to human review
    # otherwise proceed to the next image
    if (score_filtered[0][1] < SCORE_THRESHOLD):
        s3_fname='s3://%s/a2i-results/%s' % (BUCKET, fname)
        print(s3_fname)
        humanLoopName = str(uuid.uuid4())
        inputContent = {
            "initialValue": score_filtered[0][0],
            "taskObject": s3_fname # the s3 object will be passed to the worker task UI to render
        }
        # start an a2i human review loop with an input
        start_loop_response = a2i.start_human_loop(
            HumanLoopName=humanLoopName,
            FlowDefinitionArn=flowDefinitionArn,
            HumanLoopInput={
                "InputContent": json.dumps(inputContent)
            }
        )
        human_loops_started.append(humanLoopName)
        print(f'Object detection Confidence Score of %s is less than the threshold of %.2f' % (score_filtered[0][0], SCORE_THRESHOLD))
        print(f'Starting human loop with name: {humanLoopName}  \n')
    else:
        print(f'Object detection Confidence Score of %s is above than the threshold of %.2f' % (score_filtered[0][0], SCORE_THRESHOLD))
        print('No human loop created. \n')

上記のコードでは単純な if-else ステートメントを使用していますが、動的な条件の場合、AWS Lambda を使用してオブジェクトがヒューマンレビューを必要とするかどうかを評価することもできます。ヒューマンレビューが必要であると判断した場合、a2i.start_human_loop でヒューマンループを作成できます。

ステップ 6: ヒューマンレビューの完了

start_human_loop 呼び出しを介して予測確率の低い画像を Amazon A2I に送信した後、レビュー担当者として割り当てられた人は、ラベル付けポータルにログインして画像をレビューできます。URL は、Amazon SageMaker コンソールにあるラベル付けワークフォースページの [プライベート] タブにあります。次のコードを使用して、プログラムで URL を取得することもできます。

print('https://' + sagemaker_client.describe_workteam(WorkteamName=workteamName)['Workteam']['SubDomain'])

この投稿では、workteamNamea2i-demo-1 です。

ヒューマンレビューを完了するには、次の手順を実行します。

  1. ポータルに移動すると、ユーザー名とパスワードを使用してログインするように求められます(初めてポータルにアクセスする場合は、新しいパスワードを作成する必要があります)。

ジョブ」セクションで新しいジョブを確認できます。

  1. [オブジェクト検出 a2i demo] を選択します。
  2. [作業を開始する] をクリックします。

このページには、カスタマイズ可能な説明パネル、画像、使用可能なラベルが含まれています。

  1. ツールバーから [ボックス] を選択します。
  2. [ラベル] の下で [自転車] を選択します。
  3. オブジェクトの周りにバウンディングボックスを描きます。
  4. [送信] をクリックします。

すべての画像レビューを完了したら、ヒューマンループの出力を分析できます。Amazon A2I は結果を S3 バケットに保存し、Amazon CloudWatch イベントを送信します。

すべての作業が完了すると、ヒューマンレビューのワークフロー定義で指定した Amazon S3 出力パスで結果がわかるようになります。人による回答、ラベル、バウンディングボックスが返され、JSON ファイルに保存されます。次のコードは、サンプルの Amazon A2I 出力 JSON ファイルを示しています。

{'flowDefinitionArn': 'arn:aws:sagemaker:us-east-1:xxxxxxxx:flow-definition/fd-sagemaker-object-detection-demo-2020-05-01-18-08-47',
 'humanAnswers': [{'answerContent': { 'annotatedResult': { 'boundingBoxes': [{'height': 1801,
                                                                              'label': 'bicycle',
                                                                              'left': 1042,
                                                                              'top': 627,
                                                                              'width': 2869}],
                                                           'inputImageProperties': {'height': 2608,
                                                                                    'width': 3911}}},
                    'submissionTime': '2020-05-01T18:24:53.742Z',
                    'workerId': 'xxxxxxxxxx'}],
  'humanLoopName': 'xxxxxxx-xxxxx-xxxx-xxxx-xxxxxxxxxx',
  'inputContent': {'initialValue': 'bicycle',
                   'taskObject': 's3://sagemaker-us-east-1-xxxxxxx/a2i-results/sample-a2i-images/pexels-photo-276517.jpeg'}}

この情報を取得および解析して、さらに分析できます。次のステップでは、このヒューマンレビューしたデータを、モデルの次の再トレーニング反復に使用する方法をご紹介します。

ステップ 7: 段階的トレーニングの JSON 出力の処理

オブジェクト検出トレーニングノートブックでは、Amazon SageMaker ビルトインのオブジェクト検出アルゴリズムを使用して、モデルの最初のバージョンをトレーニングしました。このモデルを使って、いくつかのランダムなサンプルには入っていない画像に対して予測を作成すると、不十分な予測(低い確率)となりました。また、Amazon A2I を使用して、カスタム条件(信頼スコアのしきい値が 50% 未満)に基づいて画像を確認し、ラベルを付けました。ML ライフサイクルの次のステップは、通常、モデルが問題を抱えたケースを、再トレーニングの目的でトレーニングデータの次のバッチに含めることです。これで、モデルは一連の新しいトレーニングデータから学習し、改善を継続することができます。ML では、これは段階的トレーニングと言います。

このステップは付属の Jupyter ノートブックで行います。

画像データと注釈を、3 つの異なる方法でオブジェクト検出アルゴリズムに提供できます。詳細については、オブジェクト検出アルゴリズムの入出力インターフェイスをご覧ください。この投稿では、PASCAL VOC の画像と注釈を RecordIO 形式に変換したため、元のモデルを RecordIO 形式でトレーニングしました。カスタム RecordIO データの作成手順については、Prepare custom datasets for object detection をご参照ください。

または、オブジェクト検出アルゴリズムでも JSON ファイルを入力として受け取ります。画像ごとに 1 つの JSON ファイルを作成するか、拡張マニフェストファイルを入力形式としてパイプモードを利用できます。パイプモードは、トレーニングインスタンスに接続した Amazon Elastic Block Store (Amazon EBS) ボリュームにデータをコピーするのではなく、実行中にデータをトレーニングアルゴリズムにストリーミングすることで、モデルの全体的なトレーニング時間を最大 35% 加速します。次のコードを使用して、Amazon A2I 出力から拡張マニフェストファイルを作成できます。

object_categories_dict = {str(i): j for i, j in enumerate(object_categories)}

def convert_a2i_to_augmented_manifest(a2i_output):
    annotations = []
    confidence = []
    for i, bbox in enumerate(a2i_output['humanAnswers'][0]['answerContent']['annotatedResult']['boundingBoxes']):
        object_class_key = [key for (key, value) in object_categories_dict.items() if value == bbox['label']][0]
        obj = {'class_id': int(object_class_key),
               'width': bbox['width'],
               'top': bbox['top'],
               'height': bbox['height'],
               'left': bbox['left']}
        annotations.append(obj)
        confidence.append({'confidence': 1})

    augmented_manifest={'source-ref': a2i_output['inputContent']['taskObject'],
                        'a2i-retraining': {'annotations': annotations,
                                             'image_size': [{'width': a2i_output['humanAnswers'][0]['answerContent']['annotatedResult']['inputImageProperties']['width'],
                                                             'depth':3,
                                                             'height': a2i_output['humanAnswers'][0]['answerContent']['annotatedResult']['inputImageProperties']['height']}]},
                        'a2i-retraining-metadata': {'job-name': 'a2i/%s' % a2i_output['humanLoopName'],
                                                      'class-map': object_categories_dict,
                                                      'human-annotated':'yes',
                                                      'objects': confidence,
                                                      'creation-date': a2i_output['humanAnswers'][0]['submissionTime'],
                                                      'type':'groundtruth/object-detection'}}
    return augmented_manifest

これで、次のコードのような JSON オブジェクトを作成します。これは、Ground Truth が結果を出力する方法や、SageMaker ビルトインのオブジェクト検出アルゴリズムが入力を予測する方法と互換性があります。

{   'source-ref': 's3://sagemaker-us-east-1-xxxxxxx/a2i-results/sample-a2i-images/pexels-photo-276517.jpeg',
    'a2i-retraining': {   'annotations': [   {   'class_id': 1,
                                                 'height': 1801,
                                                 'left': 1042,
                                                 'top': 627,
                                                 'width': 2869}],
                          'image_size': [   {   'depth': 3,
                                                'height': 2608,
                                                'width': 3911}]},
    'a2i-retraining-metadata': {   'class-map': {   '0': 'aeroplane',
                                                    '1': 'bicycle',
                                                    '2': 'bird',
                                                    '3': 'boat',
                                                    '4': 'bottle',
                                                    '5': 'bus',
                                                    '6': 'car',
                                                    '7': 'cat',
                                                    '8': 'chair',
                                                    '9': 'cow'
                                                    '10': 'diningtable',
                                                    '11': 'dog',
                                                    '12': 'horse',
                                                    '13': 'motorbike',
                                                    '14': 'person',
                                                    '15': 'pottedplant',
                                                    '16': 'sheep',
                                                    '17': 'sofa',
                                                    '18': 'train',
                                                    '19': 'tvmonitor',},
                                   'creation-date': '2020-05-01T18:24:53.742Z',
                                   'human-annotated': 'yes',
                                   'job-name': 'a2i/fc3cea7e-ead8-4c5c-b52d-166ff6147ff0',
                                   'objects': [{'confidence': 1}],
                                   'type': 'groundtruth/object-detection'}}

上記のコードは 1 つの画像のみです。Amazon A2I コンソールでヒューマンレビュー担当者が再ラベル付けしたすべての画像からトレーニング画像のコホートを作成するには、すべての Amazon A2I 出力をループし、JSON ファイルを変換して、JSON Lines ファイルに連結し、各行に 1 つの画像の結果を表します。次のコードをご覧ください。

with open('augmented.manifest', 'w') as outfile:
    for resp in completed_human_loops: # completed_human_loops contains a list of responses from a2i.describe_human_loop() calls
        splitted_string = re.split('s3://' +  BUCKET + '/', resp['HumanLoopOutput']['OutputS3Uri'])
        output_bucket_key = splitted_string[1]

        response = s3.get_object(Bucket=BUCKET, Key=output_bucket_key)
        content = response["Body"].read()
        json_output = json.loads(content)
        augmented_manifest = convert_a2i_to_augmented_manifest(json_output)
        json.dump(augmented_manifest, outfile)
        outfile.write('\n')
!head -n2 augmented.manifest
{"source-ref": "s3://sagemaker-us-east-1-xxxxxxx/a2i-results/sample-a2i-images/pexels-photo-276517.jpeg", "a2i-retraining": {"annotations": [{"class_id": 1, "width": 2869, "top": 627, "height": 1801, "left": 1042}], "image_size": [{"width": 3911, "depth": 3, "height": 2608}]}, "a2i-retraining-metadata": {"job-name": "a2i/fc3cea7e-ead8-4c5c-b52d-166ff6147ff0", "class-map": {"0": "aeroplane", "1": "bicycle", "2": "bird", "3": "boat", "4": "bottle", "5": "bus", "6": "car", "7": "cat", "8": "chair", "9": "cow", "10": "diningtable", "11": "dog", "12": "horse", "13": "motorbike", "14": "person", "15": "pottedplant", "16": "sheep", "17": "sofa", "18": "train", "19": "tvmonitor"}, "human-annotated": "yes", "objects": [{"confidence": 1}], "creation-date": "2020-05-21T18:36:33.834Z", "type": "groundtruth/object-detection"}}
{"source-ref": "s3://sagemaker-us-east-1-xxxxxxx/a2i-results/sample-a2i-images/pexels-photo-1571457.jpeg", "a2i-retraining": {"annotations": [{"class_id": 17, "width": 1754, "top": 1285, "height": 1051, "left": 657}], "image_size": [{"width": 3500, "depth": 3, "height": 2336}]}, "a2i-retraining-metadata": {"job-name": "a2i/8241d6e4-8078-4036-b065-ccdd5ebf955f", "class-map": {"0": "aeroplane", "1": "bicycle", "2": "bird", "3": "boat", "4": "bottle", "5": "bus", "6": "car", "7": "cat", "8": "chair", "9": "cow", "10": "diningtable", "11": "dog", "12": "horse", "13": "motorbike", "14": "person", "15": "pottedplant", "16": "sheep", "17": "sofa", "18": "train", "19": "tvmonitor"}, "human-annotated": "yes", "objects": [{"confidence": 1}], "creation-date": "2020-05-21T18:36:22.268Z", "type": "groundtruth/object-detection"}}

十分なデータポイントを収集したら、段階的トレーニング用の新しい Estimator を構築できます。詳細については、Easily train models using datasets labeled by Amazon SageMaker Ground Truth をご参照ください。このブログでは、アルゴリズムに付属するトレーニング済みの重み(use_pretrained_model=0)ではなくトレーニング済みモデルの重みを使用することを以外は、オブジェクト検出トレーニングノートブックで最初のモデルをトレーニングした方法とまったく同じハイパーパラメータを使用してます。

次のコード例は、1 つまたは 2 つの新しいサンプルを使った段階的トレーニングを示しています。この投稿では 2 つの画像のみを確認したため、これは有意義な改善を行ったモデルにはなりません。

s3_train_data = 's3://bucket/path/to/training/augmented.manifest'
s3_validation_data = 's3://bucket/path/to/validation/augmented.manifest'
s3_output_location = 's3://bucket/path/to/incremental-training/'
num_training_samples = 1234

from sagemaker.amazon.amazon_estimator import get_image_uri
training_image = get_image_uri(region, 'object-detection', repo_version='latest')

# Create a model object set to using "Pipe" mode because we are inputing augmented manifest files.
new_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 = 'Pipe',
                                             output_path=s3_output_location,
                                             sagemaker_session=sess) 

# the hyperparameters are the same from how the original model is trained                                      
new_od_model.set_hyperparameters(base_network='resnet-50',
                                 use_pretrained_model=0,
                                 num_classes=20,
                                 mini_batch_size=32,
                                 epochs=1,
                                 lr_scheduler_step='3,6',
                                 lr_scheduler_factor=0.1,
                                 optimizer='sgd',
                                 momentum=0.9,
                                 weight_decay=0.0005,
                                 overlap_threshold=0.5,
                                 nms_threshold=0.45,
                                 image_shape=300,
                                 label_width=350,
                                 num_training_samples=num_training_samples)
                                 
train_data = sagemaker.session.s3_input(s3_train_data,
                                        distribution='FullyReplicated',
                                        content_type='application/x-recordio',
                                        record_wrapping='RecordIO',
                                        s3_data_type='AugmentedManifestFile',
                                        attribute_names=['source-ref', 'a2i-retraining'])
validation_data = sagemaker.session.s3_input(s3_validation_data,
                                             distribution='FullyReplicated',
                                             content_type='application/x-recordio',
                                             record_wrapping='RecordIO',
                                             s3_data_type='AugmentedManifestFile',
                                             attribute_names=['source-ref', 'a2i-retraining'])
# Use the output model from the previous job. 
model_data = sagemaker.session.s3_input(model_data_s3_uri,
                                        distribution='FullyReplicated',
                                        content_type='application/x-sagemaker-model',
                                        s3_data_type='S3Prefix',
                                        input_mode = 'File')

data_channels = {'train': train_data,
                 'validation': validation_data,
                 'model': model_data}
                 
new_od_model.fit(inputs=data_channels, logs=True)

トレーニング後、s3_output_location で新しいモデルを取得します。この後、このモデルを新しい推論エンドポイントにデプロイするか、既存のエンドポイントを更新できます。既存のエンドポイントを更新しても、可用性が失われることはありません。エンドポイントを更新するには、新しいエンドポイントを設定する必要があります。詳細については、UpdateEndpoint をご参照ください。

クリーンアップ

今後料金が発生しないようにするには、Amazon SageMaker エンドポイント、ノートブックインスタンス、Amazon S3 のモデルアーティファクトなどのリソースを使用中ではないときに削除します。

まとめ

この記事は、典型的な ML ライフサイクルで Amazon A2I ができることについて、ほんの一部に触れたに過ぎません。Amazon A2I ワーカータスクテンプレートインターフェイス、ヒューマンレビューワークフロー、ワークチームといった、ループフレームワークで作業する人材を配置するのに必要なものすべてをセットアップする方法をご紹介しました。さらに、Amazon SageMaker がホストするオブジェクト検出エンドポイントが低い信頼性推論を返した後、プログラム上で Amazon A2I ヒューマンループをトリガーする方法も説明しました。最後に、Amazon A2I 出力 JSON ファイルを使って、Amazon SageMaker ビルトインのオブジェクト検出アルゴリズムを使用した段階的トレーニング用の拡張マニフェスト形式で、トレーニングデータの新しいバッチを作成する方法について解説しました。

動画でのご紹介、Jupyter ノートブックのサンプル、またはドキュメント処理、コンテンツ管理、感情分析、テキスト翻訳などのユースケースについてのその他の情報は、Amazon AI Resources をご参照ください。

参考文献

  • Everingham, Mark. 他The pascal visual object classes challenge: A retrospective. International journal of computer vision 111.1 (2015): 98-136.
  • Liu, Wei. 他SSD: Single shot multibox detector. European conference on computer vision.Springer, Cham、2016

執筆者について

Michael Hsieh は、シニア AI/ML スペシャリストソリューションアーキテクトです。お客様とともに、AWS ML サービスと ML ドメインの知識を組み合わせて、ML の革新を続けています。シアトルに移住してからは、ハイキングトレイル、サウスレイクユニオン地区のカヤックから見る風景、シルスホールベイでの夕日など、この街の素晴らしい自然を探索するのが趣味になりました。

 

 

 

Anuj Gupta は Amazon Augmented AI のシニアプロダクトマネージャーです。お客様が機械学習をより簡単に導入できるような製品の提供に、力を注いでいます。余暇には、ロードトリップや F1 観戦を楽しんでいます。