Amazon SageMakerの「画像の分類」アルゴリズムの「データ拡張」オプションについて

2018.09.01

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

概要

こんにちは、yoshimです。 今回はSageMakerの「画像分類」ビルトインアルゴリズムのハイパーパラメータとして指定できる「データ拡張オプション(augmentation_type)」についてエントリーを書こうと思います。 「データ拡張」は画像分類タスクでは一般的な前処理で、汎化性能を向上するためには必須な工程と言っても大げさでは無い処理です。 「データ拡張」について端的に説明すると、「元の画像データを少し変形させたデータを学習に利用する」ことで、「画像を少ししか持っていなくても、あたかもたくさんの画像を使っているかのように学習する」手法です。

目次

1.最初に

今回はネジ画像の分類タスクを通して「データ拡張」の有用性について確認してみます。

先日ご紹介したチュートリアルでは、ネジ画像の分類を100%の精度で達成できたのですが、これは過学習に陥っていることが容易に想像できます。 具体的には、上記のエントリーで利用した画像は全て「紙の上にネジが乗っている」状態のデータで学習していました。これでは、「背景が異なる画像」で推論した際に誤分類する可能性があります。あくまでも「学習、検証に利用したデータ」で精度が100%になっただけであり、実用性は皆無と言っていいでしょう。

画像分類で汎化性能を向上する方法の1つに「データ拡張」という手法があります。これは「元の画像データを少し変形させて作成したデータを学習に利用する」手法です。kerasを利用している場合は「ImageDataGenerator」等を使えば手間をかけずに拡張できるのですが、SageMakerの「画像分類」ビルトインアルゴリズムでは学習時にハイパーパラメータを指定することで同様の処理が可能となります。

今回は、この「データ拡張」機能を使って「ネジ画像分類」の汎化性能が向上するかを確認します。 具体的には、「紙の上にネジが乗っている画像」と少量の「背景がバラバラな画像」を使って学習したモデルに対して、「背景がバラバラな画像」のみで推論した際の精度を確認して、「データ拡張」機能の有用性を確認しようと思います。

今回利用する画像は下記のようなイメージです。

・1.紙の上に乗っているネジ

・2.背景が黄色

・3.背景がティッシュの箱

上記の「1.紙の上に乗っているネジ」のような画像を200枚、「2.背景が黄色」、「3.背景がティッシュの箱」のような背景がバラバラな画像を38枚の計238枚(トレーニング、検証を合わせて)でモデルを学習させます。 また、学習後に「2.背景が黄色」、「3.背景がティッシュの箱」のような背景がバラバラな画像27枚を使って汎化性能をテストします。

いずれの画像も黒い部分があるのですが、学習のために「サイズ調整」をした際に、欠損部分について黒塗りしたためです。

2.検証方法について

2-1.方針

今回の検証の方針は下記の通りです。 ・ネジの画像分類を行う。分類対象は「なべネジ」、「皿ネジ」、「蝶ネジ」の3種類。 ・モデルの学習には、「紙の上にネジが乗っている画像」と少量の「背景がバラバラな画像」を使い、推論には「背景がバラバラな画像のみ」を利用する。 ・データ拡張オプションの利用有無での汎化性能(学習に利用していない「背景がバラバラな画像」を使った推論精度)を比較する。

2-2.コード

今回利用するコードは基本的にこちらのバケット名や利用するデータを変更しただけです。 また、混同行列の作成方法については先日ご紹介したエントリーをご参照ください。

2-3.ハイパーパラメータ

上記に記載の通り、「データ拡張オプション(augmentation_type)」の指定以外は同一のパラメータで学習を実行しました。 具体的なハイパーパラメータは下記の通りです。 また、今回検証に利用する「augmentation_type」は'crop_color_transform'です。

num_layers = 50
image_shape = "3,224,224"
num_training_samples = 180
num_classes = 3
mini_batch_size = 30
epochs = 50
learning_rate = 0.01
top_k = 1
checkpoint_frequency = 2
use_pretrained_model = 1

# augmentation_type(データ拡張オプション。今回の検証で変更するのはここだけ!)
# augmentation_type = 'crop_color_transform'

3.結果

データ拡張オプション有無のそれぞれにおける混同行列を作成して結果を確認しました。 いずれの場合においても、学習の後半からはlossの変化が落ち着き、train,valの精度に差は殆ど生じていませんでした。

3-1.データ拡張オプション無

学習で利用した検証用データセットでの結果は下記の通りで、ほぼほぼ問題なく推論できています。

しかし、「背景がバラバラなデータ」で推論したところ、なべネジの約半分を「皿ネジ」と判断してしまいました。

ハイパーパラメータの調整をすればもう少しよくなるのかもしれませんが、そもそも学習で利用しているデータに対してのみ調整することになるので、汎化性能の向上はあまり期待できなさそうです。

3-2.データ拡張オプション有

学習で利用した検証用データセットでの結果は下記の通りで、ほぼほぼ問題なく推論できています。

「背景がバラバラなデータ」での確認結果は下記の通りでした。 完璧とは言えないものの、25/27が正解ということで、データ拡張が無い時よりはいい結果と言えそうです。

4.まとめ

今回のパターンでは、「データ拡張」オプションを指定することで汎化性能が向上することが確認できました。 また、本手法は画像認識において汎化性能を向上するための一般的な手法であるため、本ビルトインアルゴリズムを利用する際は、「特に問題がない限りはデータ拡張オプションを利用」するのが一般的だと思います。

また、今回はしていないのですが、分類対象のクラス数が少ない場合は「その他」のクラスを追加してもいいと思います。 というのも、本アルゴリズムでは推論結果は「全てのクラスの確率を足し合わせると100%」になるので、「全く未知のデータ」が入った際に「いずれかのクラス」に誤分類する可能性があります。 例えば、よほど高性能なモデルでない限りは、「スマホ」の画像を推論用として投入した際に「なべネジである可能性が70%、皿ネジである確率が20%、蝶ネジである確率が10%」等の結果を返すことがありえます。 このような事態になると「推論結果の確率で閾値を設定」するだけでは対応しきれない場合があります。 (例えば、閾値を70%に指定した場合は、上記のスマホはなべネジと認識してしまうことになる)

例えば、下記のような真っ黒な画像を今回のモデルに適用したところ、「蝶ネジである確率が93%」と返ってきてしまいましたので閾値の設定だけでは対処できなさそうです。

このような誤分類を減らす、つまり「全く未知のデータに対する誤分類」を減らす方法として「その他」クラスを利用することは有用な手段になることもあります。また、オープンに公開されている「画像分類タスク用データセット」には上記のことを考慮してあらかじめ「その他」クラスのデータを用意しているものもあります。 例えば、画像分類ビルトインアルゴリズムのチュートリアルの一つである「Image-classification-transfer-learning.ipynb」で利用しているデータセット「caltech-256」では、分類対象256クラス+その他1クラスの合計257クラス分の画像を利用しています。

結果

一応、最後にデータ拡張オプションの有無による推論用データセットでの結果をまとめておきます。 今回は利用したデータサイズも小さく、モデルのハイパーパラメータの調整もほとんどしていないため、良い検証とは言えませんが、データ拡張による汎化性能向上の一端は感じ取れたかと思います。

・正解数

augmentation_type なべネジ 蝶ネジ 皿ネジ
なし 8(57%) 9(90%) 3(100%)
crop_color_transform 13(92%) 9(90%) 3(100%)

5.引用

先日ご紹介したチュートリアル ImageDataGenerator awslabsのGithub