TL; DR
- Optuna に
AllenNLPExecutor
という AllenNLP のインテグレーションを追加しました.Jsonnet 形式の設定ファイルを再利用してハイパーパラメータを最適化できます. - 今後も AllenNLP 連携機能の強化を行っていく予定です(Optuna の Pruning API の対応など).これにより, Hyperband などの効率的なアルゴリズムを用いた学習が可能になります.
- 今回の記事のデモ用に作成したサンプルは GitHub で公開しています.サンプルを実際に動かしてみたい方はご利用ください.
はじめに
この記事ではハイパーパラメータ最適化ライブラリの Optuna を使い, AllenNLP を用いて実装したニューラルネットワークの ハイパーパラメータを最適化する方法について紹介します.
Optuna
Optuna はハイパーパラメータ最適化のライブラリであり,機械学習におけるハイパーパラメータの最適化を柔軟に行えます. Optuna では最適化をおこなうためには,目的関数(objective
)を定義します. 簡単な例を以下に示します.
ハイパーパラメータの探索空間は trial
インスタンスの suggest API を呼び出す形で定義します. 定義した目的関数を study.optimize
メソッドに渡すことでパラメータの最適化が行われます. より詳しい使い方については,公式チュートリアルをご覧ください.
AllenNLP
AllenNLP はニューラルネットワークを用いて自然言語処理を行うためのライブラリです. Allen Institute for Artificial Intelligence が開発を行っています. 国際会議で論文発表やチュートリアル発表を行っており,自然言語処理の研究を行う際に便利です. また,充実したチュートリアルやデモが用意されており,初心者でも最先端の自然言語処理研究に触れることが可能です.
AllenNLP を用いたモデルの学習には大きく分けて (a) Python スクリプトを作成して直接実行する方法と (b) Jsonnet 形式の設定ファイルを用意して allennlp cli を実行する方法の2種類があります.本記事では後者の Jsonnet ファイルを利用する方法について説明します.Python スクリプトで Optuna を使いたい方は GitHub の公式サンプルをご覧ください.
Jsonnet 形式の設定ファイルを用いる方法では,ユーザは実験に用いる設定を記述するだけでモデルの学習を実行できます.これにより train.py などの学習スクリプトの実装を行う必要がなくなり,モデルの構成やハイパーパラメータを見通しよく管理できるようになります.
AllenNLP 用のハイパーパラメータ最適化ツールとして有名なものに AllenTune が存在します. AllenTune も Jsonnet 形式の設定ファイルを用いた最適化に対応していています.ユーザは既存の Jsonnet ファイルに数行変更を加え,探索空間を定義した Json ファイルを作成することで最適化を行えます.AllenTune はパラメータの探索アルゴリズムとして,シンプルな Random Search と Grid Search をサポートしています.
Optuna + AllenNLP
Optuna には Tree-structured Parzen Estimator [1] や CMA Evolution Strategy [2] ,多目的最適化などが実装されており,探索アルゴリズムの選択に自由度があります.他にも, Hyperparameter Importance やVisualization などの便利な機能が提供されています. AllenNLPExecutor
はこれらの機能を AllenNLP でも利用するためのインテグレーションです.
AllenNLPExecutor は以下のようにパラメータ最適化を行っています.
- Jsonnet 形式の設定ファイルを編集し,ハイパーパラメータを std.extVar でマスクする
- Optuna の suggest API を用いて定義した探索空間からパラメータをサンプリングし, Jsonnet ファイルの設定と合わせて AllenNLP の
Params
オブジェクトを作成する Params
オブジェクトをallennlp.commands.train.train_mode
に渡し,モデルの学習を実行する
実装の詳細についてはプルリクエストをご覧ください.
上記の処理を行うモジュールをプロジェクトごとに作成するのは手間がかかります.また, AllenNLP の API は現在メジャーリリースに向けて大きく変わる可能性があります.Optuna に AllenNLPExecutor
を実装することで,ユーザの AllenNLP と Optuna の連携を行うプログラムの実装・メンテナンスをする手間を削減したいと考え,プルリクエストを作成しました.無事にマージされ, 5 月 11 日にリリースされた v1.4.0 から利用可能です.
AllenNLPExecutor のデモ
デモで取り組むタスク
Optuna の AllenNLP インテグレーションのデモとして,IMDb のレビューデータの極性分類 [3] に取り組みます. IMDb データセットには 20,000 件の学習データと 5,000 件のテストデータが含まれており, 各レコードには映画やテレビ番組のレビュー投稿,およびそのレビューが肯定的な投稿であったか否定的な投稿であったかを示すラベルが含まれています.レビュー本文のテキスト情報からレビューが肯定的なものか否定的なものかを予測することが今回のタスクです.
準備
AllenNLP のみを用いて Jsonnet 形式の設定ファイルを作成すると以下のようになります.設定ファイルおよびパラメータは AllenTune の公式サンプルをもとに作成しました.なお,パラメータのデフォルト値は公式サンプルで定義されている各パラメータ空間の中央値としています.このモデルを Baseline と呼びます.
Optuna を用いてこの AllenNLP モデルのハイパーパラメータを最適化する例を示します.Optuna の AllenNLPExecutor
を利用するためには,まず設定ファイル中の最適化したいハイパーパラメータを std.extVar
という Jsonnet のメソッド呼び出しに置き換えます.
Jsonnet の書き換えはこれだけです.以下のような設定ファイルが出来上がります.
設定ファイルの作成が終わったので, Optuna で探索空間を定義します.先程 std.extVar
で書き換えたパラメータ名と同じ名前を使用することに注意してください.目的関数は以下のようになります.
探索空間を定義できたら, trial オブジェクトを AllenNLPExecutor
に渡します.このとき,Jsonnet ファイルのパス,モデルのスナップショットのパス, 最適化中に利用する評価指標を同時に指定します. executor.run
メソッドを実行するとモデルの学習が実行され,評価指標が返り値として得られます.これを返り値とすることで Optuna は学習の結果を確認できるようになります.作成した目的関数を用いて study.optimize
を実行することでパラメータの最適化が開始します.
結果
ハイパーパラメータ最適化の結果を以下に示します.評価指標はバリデーションデータでの正解率です. Baseline
は準備の章で定義した探索空間の中央値を用いたモデルです . Optuna + AllenNLP
は AllenNLPExecutor
を用いて最適化を行った際の結果です. 乱数の seed 値を変更しながら5回最適化を行い,正解率の平均値を計算しています. Baseline
は seed とハイパーパラメータが固定して学習しているため,試行を繰り返しても正解率は一定となります. Optuna を用いて最適化を行った結果,試行回数を重ねるごとに正解率が上昇していることがわかります. 元のハイパーパラメータを用いる場合と比較して,約 2.7 ポイント正解率が向上しました.
(図2. Optuna でパラメータ最適化を行った結果)
Optuna には最適化されたハイパーパラメータを用いて AllenNLP の設定ファイルを生成する機能があります. AllenNLPExecutor
に渡した設定ファイルのパス,最適化した設定ファイルを作成したいパス,および study
オブジェクトを dump_best_config
メソッドに渡してください.
dump_best_config
を実行する指定したパスに以下のような Json ファイルが出力されます. dropout
や embedding_dim
などのパラメータの値が std.extVar
から実際の値に書き換わっていることが確認できます.また,出力されたファイルは allennlp train
コマンドに直接渡すことが可能です.これにより,ユーザは最適化されたパラメータを用いてモデルを再学習できます.
おわりに
本記事では自然言語処理のためのニューラルネットワークライブラリである AllenNLP と Optuna を組み合わせてハイパーパラメータを最適化する方法について紹介しました.AllenNLP の Jsonnet ファイルに少しの修正を加えるだけで,簡単に使えます.デモとして IMDb レビューデータの極性分析に取り組みました.
また,今後の展望として現在の AllenNLP インテグレーションではサポートされていない Pruning API のサポート も行っていく予定です. これにより, Hyperband [4] などを用いた効率的な学習が可能になります.
今回デモのために作成したサンプルは GitHub で公開しています. サンプルを実行してみたい方はご利用ください.