AllenNLPとAmazon SageMakerによる、機械学習の効率化

piqcy
programming-soda
Published in
12 min readApr 8, 2019
photo from Kurbelwelle

機械学習におけるモデルの構築と学習は、近年より速く・簡単に・自動的にできるようになってきています。この技術的な進歩は、より多くの仮説 — 様々な研究アイデア、ビジネスデータへの適用 — の検証を可能にするという点で、重要です。本記事ではAllenNLPを使うことで速く・簡単に機械学習モデルの実装を行い、さらにAmazon SageMakerを使うことで自動的に学習を行う手法を紹介します。

記事の構成は、以下のようになっています。

  1. AllenNLPによるモデル構築
  2. Amazon SageMakerによる学習の自動化

AllenNLPによるモデル構築

AllenNLPは、PyTorchをバックエンドとしたライブラリです。自然言語処理にかかわる機械学習モデルを、PyTorch(あるいはTensorFlow)でゼロから作るより簡単に構築することができます。簡単なだけではなく、AllenNLPには自然言語処理の各タスクで優秀な性能を記録したモデルが実装されており、それらを使うことで精度的にも保証されたモデルを構築することができます。

同様にPyTorchをバックエンドとしたライブラリとしては、fast.aiがあります。

AllenNLPやfast.aiを使うことは、旅行でツアーパックを使うことに似ています。ツアーパックは一定以上の満足度が保証されており、ある程度カスタマイズが可能です。初めて旅行する、また旅行先について十分な知識がない場合は、十分な選択といえるでしょう。

今回は、チュートリアルでも紹介されているPOS Taggingのモデルを使用します。POS Taggingとは、文中の各単語について品詞(Part of Speech=POS)を予測するタスクのことです。 The dog ate the apple. なら、 ["DET", "NN", "V", "DET", "NN"] となります。チュートリアルから、モデルの定義部分のみ抜粋したコードが以下となります。

Model を継承し、伝搬(forward)プロセスと loss (output["loss"])、評価メトリクス(get_metrics)を最低限定義します。

モデルを定義すれば、Trainer により簡単に学習できます。Kerasをご存知であれば、fitに近いと感じるかもしれません。

AllenNLPでは、Model/Trainerなどの定義をJSONライクな形式(Jsonnet)で記述することが可能です()。これにより、実験の設定を記録することができるほか、JSONファイル内のパラメーターを変えるだけで簡単に異なる設定でモデルの構築/学習を行うことができます。この機能は、次に解説するハイパーパラメーターチューニングととても相性が良いです。

Amazon SageMakerによる学習の自動化

モデルの学習は複数回行うのが一般的です。モデルの構築/学習に際しては様々な設定パラメーターがあり(ex: モデルのレイヤ数、最適化を担うOptimizerの学習率など)、「どの設定値がベストか」を知るには一回の実行では不十分なためです。この設定値を探る処理を、「ハイパーパラメーターチューニング」と呼びます。これまでは、ハイパーパラメーターチューニングは人間の手で行われてきました。

近年では、複数回の学習によるハイパーパラメーターチューニングを自動で行う手法が提案されています。一番簡単な手法はパラメーター候補を列挙してすべての組み合わせを試すことですが(これはGrid Searchと呼ばれます)、もちろんこれよりも上等な手法が数多くあります。Grid Searchを含む代表的な手法は、本記事で取り上げるAmazon SageMakerだけでなく、AzureやGCPでも利用することができます。

クラウドプラットフォームでハイパーパラメーターチューニングを行うメリットは2つあります。

  1. 学習に必要なリソースの調達が容易である
    各クラウドプラットフォームでは、モデルの学習に不可欠なGPU付きのインスタンスを提供しています。そのため、GPUを使ったハイパーパラメーターチューニングを容易に行うことができます。また、必要に応じ並列コンピューティングを行うことも容易です。
  2. 実験結果をログに残すことができる。
    クラウドプラットフォーム上での実験結果は、ログとして記録されます。これにより、「どんなパラメーターで実験したらどんな精度だったか忘れる」ことがなくなります。こうした事態は、人間による調整だと頻繁に観測されます(経験談として)。

では、さっそく行ってみましょう。AllenNLPのチュートリアルを、実際にSageMakerでチューニングした際のJupyter Notebookがこちらになります。

SageMakerは、基本的にJupyter Notebookを実行するインスタンスになっています。そのため、ハイパーパラメーターチューニングを行うにあたり今回は以下のような構成をとっています。

SageMakerによるハイパーパラメーターチューニングの構成
  1. Localでモデルの開発を行う
  2. GitHub経由でCloud上(SageMaker)に実装を移す
  3. 学習用データをS3にアップロードする
  4. 学習を実行するEstimatorを作成する
  5. チューニングを実行するTunerを作成する
  6. Tunerを実行する

1については問題ないと思うため、2の手順から解説を行っていきます。

GitHub経由でCloud上(SageMaker)に実装を移す

SageMakerからターミナルを起動し、以下のコマンドを実行します。

cd SageMaker
git clone https://github.com/icoxfog417/allennlp-sagemaker-tuning.git

ターミナルはSageMakerから起動したJupyterから行います。New>Other>Terminalで、起動が可能です。

SageMakerにおける、ターミナルの起動方法

SageMaker フォルダが、Notebookが格納されるフォルダになります。そのため、SageMaker フォルダに移動してgit cloneを行っています(更新を取り込む場合はgit pull)。実行後、Jupyter上から取得したファイルが見られるはずです。これで、SageMakerのNotebookから作成したモデルを参照できるようになりました。

学習用データをS3にアップロードする

次に、学習用のデータをS3にアップロードします。これは、SageMakerにデフォルトで搭載されているsagemaker パッケージを使うことで簡単に行うことができます。

sagemaker_session = sagemaker.Session()
s3_path = sagemaker_session.upload_data(path="path_to_file", bucket="your_s3_bucket", key_prefix="file_prefix")

bucket は、指定しない場合自動的に作成されます。

学習を実行するEstimatorを作成する

Estimatorは、学習を実行する単位になります。具体的には、python コマンドで起動できるスクリプト、学習データ、学習に使うリソース(インスタンス)をひとまとめにしたものになります。この後作成するTunerは、Estimatorに渡すパラメーターを変えることでチューニングを行っていきます。

AllenNLPでモデルを作成している場合、SageMakerにもAllenNLPのインストールが必要になります。pip でインストールできれば話が早いのですが、2019/4時点ではjsonnet がビルドできずエラーになります。そのため、ターミナルからビルドに必要なパッケージをインストールする必要があります。具体的には、g++clangです。gcc はデフォルトで存在するため、gcc に合うg++ を導入するようにします。2019/4時点では7.2だったため、バージョンを7.2に統一しています。

sudo yum install gcc72-c++.x86_64
sudo yum install clang

なおgccが4系だと古いため、デフォルトのgccを7.2にする必要があるかもしれません(インスタンスタイプによって異なる?)。

sudo rm /usr/bin/gcc
sudo ln -s /usr/bin/gcc72 /usr/bin/gcc

これでSageMakerにはインストールできました。しかし、SageMakerから起動するEstimatorの実行インスタンス(以下の場合、ml.p2.8xlarge)ではこのような作業を行うことができません。

Estimatorの定義

そのため、今回は実行に必要な仮想環境まで含めて実行インスタンスに渡すようにしています。その処理が、以下となります。

仮想環境の引き渡しを含めた、Estimatorの定義

source_dirdependencies を渡しています(from_rootsource_dir から指定引数までのパスを絶対パスで渡すための関数です)。 pip でインストールが可能な場合は、source_dir 内にrequirements.txt があればそれをインストールしてくれます。ただし、SageMakerのインスタンスはanacondaをベースとして作成されており、pipでパッケージをインストールするとpipanaconda でパッケージがバッティングする場合があります。Numpyは特にこの影響を受けやすいため、バッティングによる問題が発生した場合は今回のような対応を行う必要があります。

実装では、pipenv で仮想環境(.venv)を作成しそれをEstimatorにdependenciesとして渡しています。

チューニングを実行するTunerを作成する

Estimatorが作成できたら、Estimatorの実行パラメーターを最適化するTunerを作成します。

HyperParameter Rangeには以下の種別があります。

  • ContinuousParameter: 連続値のパラメーター。下限/上限、その間の補完方法(LinearやLogarithmic)を指定する
  • IntegerParameter: Continuousだが取る値が整数値のパラメーター
  • CategoricalParameter: 離散値のパラメーター。指定した数値で学習を行いたい場合にも使用可能(分散表現のサイズが100、200、300など)

なお、Boolean引数はサポートされていないため、CategoricalParameterの形に変更する必要があります。(--with-paddingといったBooleanの引数があった場合、--padding-type padにするなど)。

HyperparameterTunerのstrategyは、RandomBayesianのいずれかを選択できます。(デフォルトはBayesianです)。

注意点として、メトリクスの定義があります。Estimatorの実行結果をどのようなスコアで計測するかを指定しますが、このスコアはログから正規表現で取ることになります( validation_loss=([0-9\\.]+))。この表現を間違えているとチューニングがそもそも上手くいかないので注意してください。学習中に出力するスコアのフォーマットはフレームワークによってまちまちなので、ログの出力は自ら実装したほうが良いと思います。

max_jobsは、試行回数となります。この回数だけチューニングを実行するということです。そのため、max_jobsの回数が少ない場合はその分試行されるパラメーター候補が少なくなるため設定数には注意してください。

Tunerを実行する

最後に、Tunerを実行します。

tuner.fit({"training": s3_train_dir})

実行を行うと、SageMakerの画面から実行結果を確認できます。

SageMakerのログ

また、この実行結果sagemaker.analytics.HyperparameterTuningJobAnalytics で分析可能です。Gluon CIFAR-10 Hyperparameter Tuningでは、ハイパーパラメーター同士の相関などを分析する例を見ることができます。

--

--

piqcy
programming-soda

All change is not growth, as all movement is not forward. Ellen Glasgow