AutoGluonを使ってみた

当エントリは『機械学習 on AWS Advent Calendar 2019』の15日目のエントリです。
2019.12.15

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

概要

当エントリは『機械学習 on AWS Advent Calendar 2019』の15日目のエントリです。

MXNet由来のAutoML系パッケージであるAutoGluonを試してみたので、そのレポートです。

SageMakerでのAutoML系サービスと言うとAmazon SageMaker Autopilotもあるのですがこちらは2019年12月時点でテーブルデータにしか対応していない一方、「AutoGluon」は2019年12月時点で「画像分類」、「物体検出」、「テーブルデータの回帰と分類」、「テキスト分類」のタスクに対して対応しています。

今回は「AutoGluon」の「テーブルデータの回帰と分類」以外のタスクについて検証してみました。

目次

1.最初に

まず「AutoGluon」とはなんぞや、ということを確認するためにこちらを見てみると、とてもシンプルな説明が記述されています。

AutoGluon automates machine learning tasks enabling you to easily achieve strong predictive performance in your applications. With just a few lines of code, you can train and deploy high-accuracy deep learning models on image, text, and tabular data.

凄いな、と思ったのは「テーブルデータ」だけでなく「画像」、「テキスト」にも対応している点です。
もう少し具体的にどのようなタスクができるのか、を見てみると「画像分類」、「物体検出」、「テキスト分類」、「テーブルデータへの回帰&分類」に対応しているようです。
こちらより確認)

今回は「AutoGluon」の「テーブルデータ以外のタスク」をSageMakerノートブックインスタンス上で動かして挙動や使い方を確認しました。
サンプルコード等はこちらこちらをご参照ください。

インストール方法はこちらをご参照いただきたいのですが、2019年12月時点では対象OSがLinuxしかサポートされていない点にご注意ください。
下記は、私がSageMakerノートブックインスタンス上でGPU(P3インスタンス)を使った際のインストール手順です。
(GPUを使わない場合はmxnet-cu100の部分をmxnetに変更してください)

# cudaのバージョンを確認
!nvcc --version
!pip install --upgrade mxnet-cu100
!pip install autogluon

2.画像分類

サンプルコードGitを元に検証を進めていきます。

コード自体はとてもシンプルで、下記のような形です。

import autogluon as ag
from autogluon import ImageClassification as task

# データの取得
filename = ag.download('https://autogluon.s3.amazonaws.com/datasets/shopee-iet.zip')
ag.unzip(filename)

# トレーニング、テスト用データの指定
dataset = task.Dataset('data/train')
test_dataset = task.Dataset('data/test', train=False)

if ag.get_gpu_count() == 0:
    dataset = task.Dataset(name='FashionMNIST')
    test_dataset = task.Dataset(name='FashionMNIST', train=False)


# 学習
classifier = task.fit(dataset,
                      epochs=10,
                      ngpus_per_trial=1,
                      verbose=False)

学習用データは学習時に学習用と検証用に分割されて(割合を指定しない場合は、8:2に分割)処理がなされます。
また、最終的に取得できるモデルはこの検証用データセットでの評価結果に基づいて評価され、最も結果の良かったモデルが、「学習用データと検証用データをマージしたデータセットで再学習」した後に返却されます。

Within fit, the dataset is automatically split into training and validation sets. The model with the best hyperparameter configuration is selected based on its performance on the validation set. The best model is finally retrained on our entire dataset (i.e., merging training+validation) using the best configuration.

参照:Image Classification - Quick Start

また、Gitを見てみたところ、アルゴリズムについてはデフォルトだと「ResNet」の2種類でモデリングしてくれているようです。

net=Categorical('ResNet50_v1b', 'ResNet18_v1b'),

また、Image Classification - Search Space and HPOを見てみると、「探索したいアルゴリズムの指定」、「オプティマイザと探索するハイパーパラメータの範囲指定」、「アルゴリズムとハイパーパラメータの組み合わせでの探索」、「Early Stopping」機能等も利用できます。かなり高機能ですね。
今回はチュートリアルの試しということで触れませんが、本来なら「上記の諸々を指定」した上で「試行回数(num_trialsという変数)」も増やしておくやり方が一般的なのかと思いました。

最後に、学習したモデルに対して適当な画像で推論処理を実際にしてみましたが、確かに問題なく推論できていました。

3.物体検出

物体検出についてはこちらを参考に挑戦してみました。
下記に学習を開始するまでのコードを転載しますが、画像分類の際とほぼほぼ同じです。
(サンプルから一部修正しています)

import autogluon as ag
from autogluon import ObjectDetection as task
import os

root = './'
filename_zip = ag.download('https://autogluon.s3.amazonaws.com/datasets/tiny_motorbike.zip',
                        path=root)
filename = ag.unzip(filename_zip, root=root)


data_root = os.path.join(root, filename)
dataset_train = task.Dataset(data_root, classes=('motorbike',))

time_limits = 5*60*60 # 5 days
epochs = 20
detector = task.fit(dataset_train,
                    num_trials=1,
                    epochs=epochs,
                    batch_size=8,
                    lr=ag.Categorical(5e-4, 1e-4),
                    verbose=True,
                    ngpus_per_trial=1,
                    time_limits=time_limits
                   )

物体検出についても、トレーニングデータが検証用と分割され、検証用データセットでの評価が最も高いモデルが取得できる、という流れのようです。
処理が完了したので、テスト用データで推論をしてみましたが、問題なくモーターバイクを識別できていました。

さて、サンプルコードは以上として少し中身を見てみます。
まず、fitの引数でどのような変数が指定できるのか、ということをこちらから確認してみたところ、学習率やエポック数等の基本的なハイパーパラメータの他に、「mixup」、「Label Smoothing」といった高度な手法が利用できそうでした。

  • mixup
    • 画像拡張の1手法
  • Label Smoothing
    • 過学習を抑えるための手法の1つ

また、fitのなかで利用しているアルゴリズムも確認したところこちらは「yolov3」が基本となっており、yolov3の中で利用しているネットワークを色々指定できるようです(デフォルトだと「mobilenet1.0」)。
この辺りは「学習や推論に要する時間」と「精度」のトレードオフを検討して指定する必要がありそうですね。

net_name = '_'.join(('yolo3', args.net, 'custom'))

参照:train_object_detection

4.テキスト分類

テキスト分類についてはこちらを参考に挑戦してみました。

こちらも画像分類や物体検出とほぼほぼ同じような記述方法です。
今回利用したデータセットは「映画のレビューとそれに基づく感情を数値化(0~1の範囲で、数字が大きいほどポジティブ)」したもので、このデータセットを元に「感情を2値に分類(ポジティブなのか、ネガティブなのか)」するタスクを実施します。

We are using a subset of the Stanford Sentiment Treebank (SST). The original dataset consists of sentences from movie reviews and human annotations of their sentiment. The task is to classify whether a given sentence has positive or negative sentiment (binary classification).

参照:Create AutoGluon Dataset

import autogluon as ag
from autogluon import TextClassification as task

dataset = task.Dataset(name='ToySST')
predictor = task.fit(dataset, epochs=1)

学習が終わったので、一旦テストデータで評価をしてみます。

test_acc = predictor.evaluate(dataset)
print('Top-1 test acc: %.3f' % test_acc)
Top-1 test acc: 0.534

全然ダメでした...。
(1epochしか学習を回していないししょうがないか...)

折角なので、推論までしてみます。

sentence = 'I feel this is awesome!'
ind = predictor.predict(sentence)
print('The input sentence sentiment is classified as [%d].' % ind.asscalar())
The input sentence sentiment is classified as [1].

上記の通り精度が悪いので参考になりませんが、このように0ならネガティブ、1ならポジティブ、といった形で2値分類ができています。

続いて、もう少し中身を見ていきます。
まず、AutoGluonにおけるテキスト分類では学習済みのモデルにfine-tuningする方針が採用されています。

AutoGluon fine-tunes neural networks that have already been pretrained on large scale text dataset such as Wikicorpus. Although the dataset involves entirely different text, lower-level features captured in the representations of the pretrained network (such as edge/texture detectors) are likely to remain useful for our own text dataset.

参照:Use AutoGluon to fit Models

特にモデルを指定しない場合はbertが採用されています。

    def fit(dataset='SST',
            net=Categorical('bert_12_768_12'),

参照:text_classification.py

データをtrain,validationに分割して、validationデータでの評価結果に基づいて最善のモデルが選択され、最終的に「train,validationをマージしたデータセットで再学習」した結果が返却される、というのは「画像分類」、「物体検出」と同じです。

5.まとめ

どのタスクでも使い方の方針は殆ど同じで使いやすかったです。
また、「試行回数」や「探索するアルゴリズム」、「探索するハイパーパラメータの範囲」等、色々なものが指定できるので、とりあえずぽちぽちして使えそうだと感じた一方、「精度と処理時間のトレードオフ」や「同一タスクにおける別アルゴリズムの特徴の違い」、「分散学習させる方法」等の知識があると、更にうまく使いこなせて良さそうだと思いました。

6.参照

参照したリンク先です。