aptpod Tech Blog

株式会社アプトポッドのテクノロジーブログです

Amazon SageMakerとintdashでお菓子の高速検出システムをサクッと構築してみた

f:id:apt-k-ueno:20200107191420j:plain

aptpod Advent Calendar 2019 2日目担当のキシダです。もともとただのエンジニアだったのですが、半年前ほどこちらに入社して、今では機械学習系の案件やデータ解析向け製品の開発に従事してます。周りの人も心優しい人ばかりで、楽しくお仕事しています。 (職種はデータサイエンティストですが、他にもいろいろやらせていただいてます)
よろしくお願いいたします。

さて本記事では、私が入社したての頃に弊社の機械学習系案件の技術紹介の一貫で、 お菓子のリアルタイム検出システムデモ をAmazon SageMakerと自社製品を使って構築することになり、その際に奮闘した記録をこの場をかりてご紹介したいと思います。

このデモは、今開催されている 『AWS re:Invent 2019』 にも展示されているので、もしラスベガスにいらっしゃる方、ぜひ弊社 aptpod のブースまで!

※Amazon Sagemakerについてはこちらへ

Amazon SageMaker(機械学習モデルを大規模に構築、トレーニング、デプロイ)| AWS

どんなシステム?

当初の願望としてはこんな様子でした。

  • アプトポッドのロゴ入りお菓子(かわいい)をカメラにうつすと、お菓子の種類をシステム側が検出
  • 検出結果はリアルタイムで弊社製品の可視化ツール Visual M2M (後述に簡単な説明記載)上で常に表示されている
  • お客さんがお菓子をとったりおいたりすると、それに伴って Visual M2M 上でシステムが反応するので楽しい
  • かわいいお菓子ももらえてさらにハッピー
  • お客さんがよろこんで僕もハッピー
  • みんなハッピー

・・・
という感じで作りたいね、となりました。

その結果・・・ 一ヶ月足らずで以下のようなデモができました。

f:id:aptpod_tech-writer:20191202152935p:plain
Visual M2Mで写すお菓子たち

f:id:aptpod_tech-writer:20191202154637j:plain
お菓子の撮影現場

f:id:aptpod_tech-writer:20191202153221p:plain
弊社デザインチームがデザインした主役のおかしたち。うん。かわいい。

f:id:aptpod_tech-writer:20191202154733j:plain
意外に好評なデモの展示会場

と、イメージとしてはこのような感じです。

このデモで使用する自社製品/サービス

僭越ながら、今回のデモで使用している製品をざっくり紹介させていただきます。

intdash

aptpodの主力製品である『intdash』 はご存知ですか??
弊社HP(https://www.aptpod.co.jp/products/)ではこう記載されています。

intdashとは、世界高速レベルの100ミリ秒∼1ミリ秒間隔程度の高頻度で、 発生する時系列データを品質保証のないネットワークを経由して、 高速・大容量かつ安定的にストリーミングするための双方向データ伝送プラットフォームです

ちょっとあまりピンとこない方が多いかもしれませんが 「ものすごい速く、しかもデータが欠けることなく双方向に通信できるプラットフォーム」 とイメージいただければよいかと。。。  

このブログでもintdashについて触れているのですが、より詳細を知りたいという方がいらっしゃいましたらこちらをご参照ください!

Visual M2M

既に上記で紹介しましたが、今回の検出結果の可視化には『intdash Visual M2M(通称VM2M)』(https://www.aptpod.co.jp/products/vm2m/) と呼ばれるイケてる可視化ツールを使います。

f:id:aptpod_tech-writer:20191202145532p:plain
intdash Visual M2M

intdash Analytics Services

intdashのみだとデータを双方向にストリーミングするため、通常はデータ通信途中のデータをストリーミングで解析・加工することができません。そこで、『intdash Analytics Services』 と呼ばれる「データの解析用実行基盤」も提供しています。この製品を使うことで、以下のユースケースに対応できます。今回は、お菓子を撮影した動画データを加工する基盤として使っています。

  • 時系列データの計算処理・分析処理を実装したコードをintdashに反映し、処理することができる
  • 機械学習環境の構築にも適用でき、高速な推論パイプラインを回す

などなど

システムのアピールポイント

前述も触れてますが、このシステムのポイントは リアルタイム性 です。 ローカルデータを分析して可視化するというパターンとは違い、動画の撮影中と同時にシステムはお菓子を検出し、UIに表示してくれるというわりと難しめなシステムを短期間で開発できることがこのデモのアピールポイントです。

intdashべんり。

展示会のコンテンツとしての旨味

  • お菓子が動画に映ると、システムがリアルタイムで反応して、「動いてる動いてる!!!」となって楽しい

アプトポッドとしてのアピールポイント

お客様向けには、欠損なくリアルタイムで機械学習の推論が回せることと、その開発が容易であることをアピールしました。

  • intdash Analytics Serviceによって、外部サービスと連携してストリーミングデータの加工を容易にする
  • 加工を行っても、データ通信のリアルタイム性を担保する
  • 開発者側は加工処理をスクリプトを書くだけで、あとはAPIを叩くだけでデータのストリーミングシステムの簡単に組み込むことができる

実現方法

いよいよ本題です。ここでは本システムを構築した手順をざっと記し、次項でより詳細な奮闘記を記します。 今回のシステム構築に伴い使用したサービスとその関係は以下の図の通りです。

f:id:aptpod_tech-writer:20191202181742p:plain
使用サービスとその流れ

実現までのおおまかな手順

f:id:aptpod_tech-writer:20191202153604p:plain
手順イメージ

  1. 通常の動画データを画像で切り出し、Amazon SageMaker Ground Truth にてアノテーションしトレーニング用データを作る
  2. Amazon SageMakerを使用してモデルをトレーニング
  3. モデルを通して推論できるようなエンドポイントを構築する(このエンドポイントに画像を渡すと、検出結果が返ってくるようになります)
  4. intdashから取得した動画データをSageMakerのエンドポイントに投げて、検出結果を可視化するスクリプトを、intdash Analytics Serviceにデプロイする

これができればあとはWebカメラから実際に繋げてVM2Mで見ればOKです。

手順2,3箇所はこちらを参考にしました:  SageMakerで「うまい棒検出モデル」を作ってみた  https://dev.classmethod.jp/cloud/aws/sagemaker-umaibo-object-detection/

トレーニング用データの作成

お菓子の撮影

まずはお菓子の画像を撮影します。方向を45度ずつかたむけたり、複数お菓子を映したり、関係ないお菓子をいれたり、試行錯誤を続けました。

f:id:aptpod_tech-writer:20191202153650p:plain
撮影したお菓子たち


アノテーションの実施

実際に教師データ(正解データ)をつくるため、撮影したデータに対して、「どこに何がうつっているか」をツールを使って定義していきます。いわゆる アノテーション というものです。
今回は、AWSで展開されている、Amazon SageMaker Ground Truthを使用します。 実際には以下のように、対象のお菓子に対して四角(Bounding Box)で囲っていきます。

f:id:aptpod_tech-writer:20191202181121p:plain
アノテーション実施中のUI

※Amazon SageMaker Ground Truthの詳細はこちらから  https://aws.amazon.com/jp/sagemaker/groundtruth/

細かな手順を記載すると膨大な文章量となるので、こちらは割愛し個人的なGround Truthのお得ポイントをこちらにまとめておきました

f:id:aptpod_tech-writer:20191202153905p:plain
Amazon SageMaker Ground Truth お得ポイント

せっかくなのでいくつか補足します。

1. ラベリングの種類が豊富

Ground Truthは作りたいモデルによって様々なアノテーションの種類が用意されています。また、自分用にアノテーションツールのカスタマイズもでき、自由度がだいぶ高いです。

2. ラベリングの作業をGround Truthがよしなにメンバーに割り振ってくれる

ここでのGoodポイントは、 管理者はアドレスを追加するだけで一発で作業環境を提供できることです。IAMとかのセキュリティ設定や各ローカル環境の構築手順準備、作業結果のとりまとめなどなど、、、すべてやる必要がなくなります。超絶べんり。

今回はプライベートグループを使用して、こんな感じで社内の人たちに有志を募って作業をお願いしました。 ※お手伝いいただいた方々、ありがとうございました!

f:id:aptpod_tech-writer:20191202154014p:plain
依頼したときの画面

モデルをトレーニングして、推論のAPIを構築する

ここからは実際にAmazon SageMakerのモデルトレーニング機能を使用して、モデルをトレーニングしていきます。

使用するAPI

ちなみにSageMakerを扱うAPIは2種類存在し、どちらを使用いただいても問題ないようです。

  • boto3 API
    • s3などの処理を行うのにおなじみのAPIです。以下のインスタンスを起動すると、boto3 から sagemaker 用のランタイムを起動できます
client = boto3.client(service_name='sagemaker')
  • SageMaker API
    • こちらがメジャーとなっているAPIで、基本的にはこちらを使用するようです。

今回は馴染みのある 『boto3 API』を使用しました。

ハイパーパラメーターを指定する

モデルを作成するにあたって、すべてSageMakerのAPIにおまかせ!!ってわけではなく、ある程度モデルに対するパラメーターをこちらで指定する必要があります。これは使用するモデルのアルゴリズムによって異なるので今回の記載は割愛しますが、詳細を見たい方は以下を参照ください。

オブジェクト検出アルゴリズムのハイパーパラメーター

ちなみに今回指定したパラメーターは以下の通り

training_params = \
{
    "AlgorithmSpecification": {
        "TrainingImage": training_image, 
        "TrainingInputMode": "Pipe"
    },
    "RoleArn": role,
    "OutputDataConfig": {
        "S3OutputPath": s3_output_path
    },
    "ResourceConfig": {
        "InstanceCount": 1,   
        "InstanceType": "ml.p3.2xlarge",
        "VolumeSizeInGB": 50
    },
    "TrainingJobName": job_name,
    "HyperParameters": { 
         "base_network": "resnet-50",
         "use_pretrained_model": "1",
         "num_classes": "4",
         "mini_batch_size": "16",
         "epochs": "50",
         "learning_rate": "0.001",
         "lr_scheduler_step": "3,6",
         "lr_scheduler_factor": "0.1",
         "optimizer": "rmsprop",
         "momentum": "0.9",
         "weight_decay": "0.0005",
         "overlap_threshold": "0.5",
         "nms_threshold": "0.45",
         "image_shape": "300",
         "label_width": "350",
         "num_training_samples": str(num_training_samples)
    },
    "StoppingCondition": {
        "MaxRuntimeInSeconds": 86400
    },
    "InputDataConfig": [
        {
            "ChannelName": "train",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "AugmentedManifestFile",
                    "S3Uri": s3_train_data_path,
                    "S3DataDistributionType": "FullyReplicated",
                    "AttributeNames": attribute_names 
                }
            },
            "ContentType": "application/x-recordio",
            "RecordWrapperType": "RecordIO",
            "CompressionType": "None"
        },
        {
            "ChannelName": "validation",
            "DataSource": {
                "S3DataSource": {
                    "S3DataType": "AugmentedManifestFile", # NB. Augmented Manifest
                    "S3Uri": s3_validation_data_path,
                    "S3DataDistributionType": "FullyReplicated",
                    "AttributeNames": attribute_names # NB. This must correspond to the JSON field names in your augmented manifest.
                }
            },
            "ContentType": "application/x-recordio",
            "RecordWrapperType": "RecordIO",
            "CompressionType": "None"
        }
    ]
}
 
トレーニングを実行

ハイパーパラメーターを定義したら、実際に実行してみます!

client.create_training_job(**training_params)

モデルをデプロイし、コンテナ上で推論を動かす

SageMakerのすごいところは、予め用意された 組み込みアルゴリズム 以外にも、作成されたモデルを1ボタンで簡単にデプロイして、推論APIまでの構築を行ってくれることです。今までエンドポイント構築に苦労してきたデータサイエンティストにとっては、これからはモデルの作成や調整に時間をかけることができるというすぐれものです!!

実際にエンドポイントの設定を行い、

from time import gmtime, strftime
import  time
import sagemaker as sage

sage  = boto3.Session().client(service_name='sagemaker')

timestamp = time.strftime('-%Y-%m-%d-%H-%M-%S', time.gmtime())
endpoint_config_name = 'apt-snacks-endpoint-config'
endpoint_config_response = sage.create_endpoint_config(
    EndpointConfigName = endpoint_config_name,
    ProductionVariants=[{
        'InstanceType':'ml.m4.xlarge',
        'InitialInstanceCount':1,
        'ModelName':'apt-snacks-model',
        'AcceleratorType': 'ml.eia1.xlarge',
        'VariantName':'AllTraffic'}])

エンドポイントをたてます。

endpoint_params = {
    'EndpointName': endpoint_name,
    'EndpointConfigName': endpoint_config_name,
}
endpoint_response = sage.create_endpoint(**endpoint_params)

エンドポイントがたったことを確認したら、テスト用に推論APIを読み出すスクリプトを簡単に書き、実行してみます。

 session = boto3.Session(region_name='us-east-2')
    runtime = session.client('sagemaker-runtime', config=config)
    #SageMakerのエンドポイント名の指定
    endpoint_name = 'apt-snacks-endpoint'

response = runtime.invoke_endpoint(
            EndpointName=endpoint_name,
            ContentType='image/jpeg',
            Body=payload
        )
result = json.loads(response['Body'].read().decode())

そして返ってきたデータを元に、Bounding Boxを出力してみると・・・

f:id:aptpod_tech-writer:20191202154243p:plain
検出結果たち

いい感じに実行できました!(一部誤検出していますが。。) ものすごく簡単!!!

intdashとSageMakerの仲介役となるスクリプトを作り、intdash Analytics Servicesにデプロイする

上記にて作成したスクリプトを拡張して、以下の処理を行うスクリプトを作成します。

  1. raspiに導入している intdash edge から送られてきた画像データを取得する
  2. SageMakerの推論APIに画像データを送付し、推論結果を取得する
  3. 推論結果を可視化し、intdash に アップロードする

作成したコードは、実際に動かすための実行環境である 『intdash Analytics Services』にデプロイします。

動かしてみる

上記を構築した上で、raspiから動画をストリーミングすると以下のように動かすことができます!


Real-time object detection with Amazon SageMaker & intdash Services

まとめ

いかがでしたでしょうか。

今回はintdashとAmazon SageMakerを使ってお菓子のリアルタイム検出システムを簡単に構築することができました。難しいイメージの機械学習でも、SageMakerのAPIを使うことで簡単にモデルの作成からエンドポイントの構築まで自分で作成することができます。そこに弊社の高速データストリーミングプラットフォームと組み合わせることで、検出結果を動画の撮影と同時にリアルタイムで可視化でき、開発者側はインフラストラクチャーレベルを考慮せずシステムの構築を行うことができました。この記事を通して、Amazon SageMakerと弊社製品のintdashに少しでも興味をもっていただければ幸いです。

※宣伝です。
ちなみにaptpodではデータサイエンティストを絶賛採用中です!もし本記事を見て、『intdashと機械学習の技術を使ってサービス作ってみたい!』 など思ってくれる方がいらっしゃいましたら、ぜひ以下のHPまでどうぞ!
一緒に世界レベルの高速データ解析の実現を目指していきましょう!

採用情報: https://www.aptpod.co.jp/recruit/