Amazon SageMakerを使って商品の検出モデルを作成してみた

Amazon SageMakerを使うことで簡単にデータ探索から機械学習モデルの構築やホスティングが出来ます。
今回はAmazon SageMakerの組み込みアルゴリズムである物体検出を用いて、6種類の商品の検出モデルを作成しました。これまでに何回か物体検出を使ったことがあったので、ただ検出するだけなら余裕だろうと思ってやってみると、ハマった箇所がいくつかありました。そういった注意すべき点と合わせて商品検出モデルの作成について、紹介したいと思います。

今回はコードを出さず、内容の紹介に留めます。実装にあたりどういうコードが必要かを知りたい方は、参考に列挙したエントリやサンプルノートブックをご覧ください。

概要

Amazon SageMakerの組み込みアルゴリズムである物体検出(SSD: Single Shot MultiBox Detector)を使って、画像から商品を検出するモデルを作成します。

検出対象の商品は次の6種類です。

これらの商品を検出できるモデルを作成する基本的な流れは次の通りです。

  1. 教師データの作成(画像撮影、アノテーション、画像増幅など)
  2. 学習
  3. 検証

実際にはこの1~3を何回も繰り返して、商品検出モデルの改善や調整を行う必要があります。
商品はほとんどのものが表と裏と側面を持っています。表側の画像のみを学習させた場合と裏側の画像も学習させた場合の二つについて紹介します。

商品検出モデルを作ってみた

教師データの作成

学習用と学習時の検証用として372枚分の教師データを作成します。

商品画像の撮影

今回は極力少ないデータで学習させるために、モデルを使用する場面を再現して商品を撮影したものを教師画像として使用しました。
1種類の商品が複数写っているものから、複数種類の商品が複数写っているものまで色々なパターンがあります。

注意:教師画像を撮影する際には、どういう"物体"を検出するのが目的なのかを明確にした上で、どういう画像が教師データとして必要かを"しっかり"決めることをお勧めします。とりあえずこの画像で学習させてみようという勢いだけで進めてしまうと、認識精度が出ずに学習し直しで計算資源を浪費することになったり、画像の撮影やアノテーションをやり直すことになる可能性があります...。

アノテーション

VoTTというツールを使って、画像のアノテーションを行います。

注意:アノテーションもしくはアノテーションによって作成したラベルデータの形式を変換する際には、検出対象のクラスIDに気をつけましょう。ドキュメントにも記載されているんですが、クラスIDは0から始まる整数のインデックス(0,1,2,3...)形式が期待されています。ゆえに、1,2,3みたいなクラスIDを設定してしまうと、モデルの学習がうまく出来ない場合があるので注意が必要です。(このケースであれば0,1,2が正しい。)

画像増幅

学習に使用する画像には、回転処理とノイズを加えて10倍に画像増幅を行います。
画像増幅処理にはimgaugというpythonのライブラリを使用します。

画像増幅によって生成される画像は下のような感じになります。(確認用にバウンディングボックスが表示されていますが、実際に教師データとして使用するものにはバウンディングボックスは表示されていません。)

注意:画像増幅した際は必ず正しく処理されているか確認した方が良いです。別のデータで上手くいったから今回も大丈夫だろうと思って、そのまま学習に使用すると無駄な計算リソースを消費することになる可能性があります。自作した画像増幅処理にバグがあったり、ノイズがきつくかかり過ぎていたりすることもあります。確認は大事です。

RecordIO形式への変換とアップロード

SageMakerの物体検出に使用する教師データはRecordIO形式か画像とjson形式に対応しています。画像とラベルデータをRecordIO形式に変換して、教師データとして使用できるようにS3へアップロードします。 RecordIO形式への変換方法についてはサンプルノートブックをご覧ください。

この過程で作成した教師データは次の通りです。

学習(train)チャネル用: 1850枚(185枚を10倍に画像増幅)
検証(validation)チャネル用: 187枚

学習

以上の過程で作成した教師データを使用して、商品検出モデルを学習させます。
パラメータはサンプルノートブックを参考にしつつ、データ数の違いに合わせて一部変更したものを使用します。

結果

学習にはml.p3.8xlargeのインスタンスで20分ほど掛かりました。
最終エポックでの精度(validation mAP)は99.8%とかなりいい結果となりました。

モデルをエンドポイントに展開して、教師データとして使っていない画像で試してみます。

ちゃんと検出できています。

検出できはしたものの信頼度が低いものもあります。

商品の裏でも認識できるようにしてみた

上で学習させたモデルでは、商品の裏側は学習させていないため、裏返った商品の検出は出来ませんでした。次はそういった商品も対応すべく、教師データに含ませてみます。また、上で紹介した教師データだと同じような画像が多かったため、オリジナル教師データを大幅に少なくして精度がどうなるかも合わせて試してみます。

教師データ

今回使用する教師データとして使用する画像は次の通りです。各画像は裏面だけの商品が写ったもの、表面だけの商品が写ったものと分かれています。

学習(train)チャネル用: 3800枚(38枚を100倍に画像増幅)
検証(validation)チャネル用: 2200枚(22枚を100倍に画像増幅)

学習

パラメータは次の通りです。基本的には上で紹介したモデルの学習に使用したパラメータと同じですが、epochslr_scheduler_step等はデータ数の違いに合わせて変更しています。

結果

学習にはml.p3.8xlargeのインスタンスで24分ほど掛かりました。
最終エポックでの精度(validation mAP)は94.1%でした。上で紹介したモデルに比べると悪いですが、それなりにはいい結果となりました。
今回はオリジナルの教師データを少なくした上で、裏面を教師データに加えるという二つの試みを同時にしたため、問題の切り分けは難しいですが、オリジナルの教師データを増やすことでもう少し精度の向上を見込めると思います。また、今回は検証用データも画像増幅したので、認識が難しいものが混じってしまった可能性もあります。

モデルをエンドポイントに展開して、教師データとして使っていない画像で試してみます。

基本的に検出ができていますが、のど飴をうまい棒と誤検出してしまっています。

こちらも表示形式が違いますが同等の処理を通して確認したものです。この場合だと、誤検出は無いですが、うまい棒が検出できていません。

精度と引き換えにはなった可能性がありますが、オリジナルの教師データが372枚から60枚と約6分の1まで減ったため、アノテーションはかなり楽になりました。検出対象が1種類増えるだけで数十枚から数百枚の画像が新たに必要だと、撮影やアノテーションにかなりコストがかかることになります。しかしながら、商品検出の用途によっては、商品の側面であったり、角の部分であったりと様々な角度からも認識ができる必要が出て来るため、それだけのパターンの教師画像も必要になります。コストを掛けてでも認識能力が必要か、認識能力を制限した上でコストと速さを優先するかなど、用途を検討した上で考える必要がありそうです。

さいごに

今回はAmazon SageMakerの組み込みアルゴリズムである物体検出を使って、6種類の商品を検出するモデルの作成について紹介しました。Amazon SageMakerの組み込みアルゴリズムを利用することで基本的には簡単にモデル作成ができます。しかし、何かにハマってしまうとハマっていることに気づかず、無駄な学習を回してしまうことも多々あります。ソフトウェア開発と同様、学習ログや教師データを見て、変な挙動やミスをしていないか確認するのが大事ですね。

物体検出をしようとしている方の取っ掛かりとなれば、幸いです。
最後までお読みいただき、ありがとうございましたー!

参考