ふだんは音声合成と声質変換技術などの音声を用いる技術を研究

中村泰貴氏(以下、中村):「HydraとMLflowとOptunaの組み合わせで手軽に始めるハイパーパラメータ管理」というタイトルで、東京大学大学院情報理工学系研究科の修士課程2年の中村が発表します。

軽く自己紹介ですが、先ほど述べたように情報理工学系研究科の、猿渡・小山研究室の修士課程2年です。音声合成に関する技術をふだん研究しています。「Twitter」をやっているので、ぜひフォローしてください。

以前Optunaのmedium.comのブログにて、本発表と同じ題目で執筆しました。英語版と日本語版で分かれているので、ぜひご覧ください。

本発表とは関係ないのですが、せっかくなので僕の研究内容をちょっと紹介します。

私は大学で、深層ガウス過程を用いた音声合成を研究しています。ディープニューラルネットワークではなく、深層ガウス過程を用いた音声合成を提案していて、特徴としてディープニューラルネットワークを用いた音声合成よりも、高い品質の音声を合成可能です。

具体的には、Self-Attention構造やSeq2Seqの学習を深層ガウス過程音声合成の枠組みに導入する手法を新たに提案することで新規性を主張しました。

「Argparse」「hparam.py」2つのハイパーパラメーター管理それぞれのデメリット

本日は、Hydra、MLflow、Optunaを用いた効率的なハイパーパラメーター管理を説明します。単体での使い方、組み合わせた具体的な使い方などについて紹介したいと思います。それぞれのライブラリの仕組みや内部動作について具体的な詳細は話しません。本日の共有資料は、Twitterに共有しています。サンプルコードはこちらをクリックすると、PDFから取れます。

では、ハイパーパラメーター管理について説明していきます。ハイパーパラメーター管理の方法ですが、2つ考えられます。まず1つは左の図にあるArgparseによる管理です。これは代表的なディープニューラルネットワークの音声合成のものからちょっと取ってきました。

このような感じで設定する項目が非常に膨大になってしまって、どのハイパーパラメーターのモデルに対応するか、どのoptimizerに対応するかが一目では見分けがつかなくなっています。

右はhparam.pyです。具体的な名前が書いていますが、このような設定ファイルによって管理する方法なども考えられます。

これらのデメリットについて説明します。まずargparseによるハイパーパラメーター管理では、往々にして設定するハイパーパラメーター数が膨大になりがちです。階層的に書けない都合上、どのハイパーパラメーターがmodelやpreprocessなどに対応するかが見づらい状況になっています。

hparam.pyなどの設定ファイルを用いたハイパーパラメーターの管理は、例えば実験ごとにハイパーパラメーターを変更したい場合に、ハイパーパラメーターごとに設定ファイルを追加で新規作成して、編集して、それを読み込んでという感じで、ハイパーパラメーター変更のために設定ファイルを編集、あるいは作成する必要があります。

そこで本発表では、Hydra、MLflow、Optunaなどによるハイパーパラメーター管理を説明します。設定パラメーターをコマンドラインから数種類変更することができ、かつ実行可能になっているため、設定ファイルをいちいち開いて編集することがなくなります。

これはHydraの機能ですが、ハイパーパラメーターのグリッドサーチがコマンドラインから容易に可能です。かつ、結果の管理がMLflowにより容易になります。また、Optunaを組み合わせることによって、HydraのSweeperのプラグインを用いた強力なハイパーパラメーター探索がコマンドラインから利用可能になります。

「Facebook」AI Researchチームが公開しているパラメーター管理ツール「Hydra」

1つ1つのライブラリについて説明していきます。まずはHydraです。Hydraは、「Facebook」のAI Researchチームが公開しているパラメーター管理ツールです。特徴ですが、ハイパーパラメーターを階層立てて、構造的にYAMLファイルに記述できます。コマンドラインから設定を上書きすることもでき、同時に実行することもできます。また、ハイパーパラメーターの数種類のグリッドサーチを1行で実行できるという特徴があります。

基本的な使い方ですが、管理したいハイパーパラメーターをYAML形式でConfigファイルへ記述します。スライドは例ですが、このように、モデルはmodelのタグ付けをします。モデルの記述はnode1、node2のハイパーパラメーターがあって、optimizerのハイパーパラメーターももちろんあると思います。これも階層的にこのような感じで書きます。このスライド以降は、このハイパーパラメーターを具体的に使っていきます。

関数にデコレータを渡すことで、関数の内部からハイパーパラメーターの値を参照することが可能です。importは、Hydraをインポートして、Hydraの内部ではomegaconfを使っているのでomegaconfをインポートします。具体的にはomegaconfのDictConfigを使っているので、これもインポートしておきます。

このような感じでmain関数をメインの関数として入れると、main関数にこのデコレータを渡します。このデコレータを渡すことで、関数の引数として渡したConfigが、DictConfigとしてアクセスできて、辞書ではなくオブジェクトとして値にアクセスすることが可能です。

先ほどの例だと、Configのモデルのnode1とnode2をハイパーパラメーターとしたので、128とアクセスできて、optimizerだったらラーニングレートをこのような感じでアクセス可能です。

「コマンドラインから直接変更したいな」「ハイパーパラメーターの値を変えてやってみたいな」という時は、コマンドラインから直接値を変更できます。これはomegaconfがもともともっている機能だったと思います。

ハイパーパラメーターの値を調整して再実行したい場合、コマンドラインからハイパーパラメーターの値を直接変更すると、プログラムを再実行可能になります。

この例だと、はじめはConfigのモデルのnode1のハイパーパラメーターが128という設定で動いていたのですが、オプションとして「model.node1=64」と設定することで、node1のハイパーパラメーターを64に変更して実行することが可能です。このように、コマンドラインから直接実行できることがメリットになっています。

グリッドサーチもできます。node1の128、256を変えたい、あるいはnode2を16と32の2パターンで実験したいという時に、この例だと組み合わせが4なので、4つの組み合わせを実験することが可能です。数種類のハイパーパラメーターを順に用いて実行したい場合、Configを書き換えることなくコマンドラインから直接指定可能です。

指定されたハイパーパラメーターの組み合わせの数に応じて実行されます。この例だと、上から順に直列でジョブが実行されます。

さらにHydraにはハイパーパラメーター自動保存機能があります。これは実行ごとの設定値や、実行中の出力などを自動で保存する機能です。

具体的には、Outputsファイルにタイムスタンプが押されたディレクトリがたくさんできます。Hydraのデフォルトの機能だと、どうしても保存形式の可続性が低いので、タイムスタンプごとにハイパーパラメーターが違います。それらの比較ができないし、GUI上で総合的に可視化したい場合、MLflowを導入することでこのデメリットをMLflowで補えます。

ハイパーパラメーターの管理・保存・比較を容易にする「MLflow」

MLflowについて説明します。MLflowは機械学習ライフサイクルを実現するオープンソースです。Hydraと組み合わせることで、ハイパーパラメーターの管理・保存・比較が容易になります。MLflow Trackingを用いたハイパーパラメーター管理を紹介していきます。

MLflow Trackingは、機械学習などのハイパーパラメーターのlogging、loss、accuracyなどのメトリクスや、出力ファイルなどの管理を補助するAPIを提供します。pipでinstallで、簡単にインストールできます。

基本的な使い方は、ハイパーパラメーターの追跡機能と記録で、MLflowが提供するロギング関数を用いてハイパーパラメーターの記録ができます。具体的には、左の図のようになっています。

この例だと、ハイパーパラメーターがparam1しかない状況を考えています。ハイパーパラメーターのparam1が5と、このような感じでハイパーパラメーターの登録をします。log_param()という関数を使ってハイパーパラメーターの登録をします。

fooというメトリクスがあるとして、実際にここにlossの値が入ると思うのですが、このようにメトリクスをlog_metric()で登録します。ステップごとの記述も可能です。

lossやaccuracyをテキストに出したい場合は、出力されたファイルなどの記録も追加で行えます。

GUIで見たい場合は「mlflow ui」をコマンドラインで実行すると、ローカルサーバーのデフォルトだと5000ポートでGUIが立ち上がります。このような感じでMLflowを利用できます。

HydraとMLflowの具体的な実装例を、簡単に挙げています。まずmain関数を使って実行することを考えているので、main関数の上にデコレータを増やします。このあたりの処理の説明は省きます。引数として渡されたConfigのoptimizerのラーニングを直接渡して、オブジェクトベースで渡せます。

このあたりはちょっと省きますが、ここでMLflowが立ち上がっています。スライドの冒頭で挙げたコードをちょっと見てもらいたいのですが、omegaconfは階層的なオブジェクトになっていて、MLflowのlog_params()に直接渡すとちょっとおかしなことになるので、このomegaconfをプレーンなものにして、プレーンになった辞書形式をここのlog_paramに突っ込んでいます。

このような感じで、lossのメトリックを逐次的に登録できます。

これはローカルホスト5000ポートで可視化した図ですが、組み合わせ4種類の場合は、全ステップにおいてlossを4種類、登録したメトリックごとにこのような感じでGUIで可視化できます。

右はこの吐き出しを簡単にやっているのですが、自分の好きなメトリックを登録して、GUI上で可視化することが、MLflowでは可能になります。

HydraとMLflowのいったんまとめです。HydraはFacebook AI Researchが公開しているパラメーター管理ツールです。コマンドラインから設定値を複数変更して、実行可能になりました。MLflowは、機械学習の実験管理を自動で行うツールで、GUI上でパラメーターの違いによる結果の比較が容易に可能です。

Hydraで設定した変数の探索をコマンドラインから実施可能にする「Optuna」

ここにHydraのもっているプラグインを利用して、Optunaを簡単に導入できる方法を解説していきます。

Optunaとはオープンソースのハイパーパラメーター自動最適化フレームワークです。ハイパーパラメーターの値に関する試行錯誤を自動化できます。優れた性能を発揮するハイパーパラメーターの値を自動的に発見できます。

HydraとMLflowと組み合わせて、HydraのOptuna Sweeperプラグインを利用することで、Hydraで設定した変数の探索をコマンドラインから実施可能になります。最適化される変数と条件をコマンドラインから直接変更することが可能です。プラグインはpipで入れられます。

設定ファイルの追加点です。左の図のようにConfigのYAMLファイルになっていますが、追加する内容は最小限で済みます。

ここはおまじないとして書き込みます。directionや、評価関数を最小化するのか最大化するのかという指標や、探索回数の設定や、並列ワーカーの数など細かな設定はHydraのConfigファイルに追加することで、実行できます。もちろんサンプラーもここで変更できます。

main関数で、どこを変更すればいいのかですが、これも最小限で済みます。デコレータで渡した関数の返り値を、最適化する目的変数に変更するだけです。以下の例ではaccuracyを最大化したいので、accuracyに変更しています。

探索範囲の指定は、コマンドラインから最適化したい変数範囲を直接指定することが可能です。以下では、optimizerの学習率とモデルのnode数をいくつか変更して、Optunaで探索している例を挙げています。

choiceは、カテゴリ型の変数へ変換されるため、optimizerの学習率は0.1、0.001のような感じで4パターン探索したいと仮定します。

次にモデルのnode1です。node1のハイパーパラメーターを、例えばrange、int型で10から500の間の整数型で探索したい場合は、コマンドラインにオプションとしてmultirunを付け加えることによって、オプションの機能をコマンドラインから使用できます。

ほかにも、ハイパーパラメーターに対応するさまざまな分布に対応しているのですが、ちょっと説明が長くなってしまうので、公式のドキュメントなどをご覧ください。

もちろんMLflowでも可視化することが可能です。Optunaで探索されたハイパーパラメーターの値及び目的関数の値、メトリックの値を、MLflowで構築したローカルサーバー上で確認可能です。

node1とラーニングレートを探索したので、こちらではint型の探索が行われていて、こちらではカテゴリ型の探索が行われていることがわかります。このような感じで、OptunaのメリットをMLflowでも感じ取ることができます。

まとめです。本発表ではHydraとMLflowとOptunaの使い方を説明しました。学習時に煩雑になりがちなパラメーターの管理の決定版と言えると思います。HydraとOptunaでパラメーターを容易に変更・探索して、MLflowで全パラメーターを一元管理することができます。

ここではちょっと簡単に書いたのですが、本発表で説明したこの3つのモジュールはMLOpsで使われるもので、MLOpsではパイプライン管理が重要になるので、Kedroのようなパイプライン管理ツールもプラスして考慮することで、より再現率のある使い回しを意識したコードになるんじゃないかと思っています。

以上で発表を終わります。ありがとうございました。

司会者:ありがとうございました。僕から1つ質問なのですが、他にパラメータ管理ツールがあると思うのですが、Hydraを選択した理由は何があるんですかね。

中村:Hydraの中にomegaconfがあるので、実際はomegaconfでももちろん管理はできるのですが、omegaconfにはないグリットサーチができたり、プラグインがたくさんあるので、例えばプラグインを利用してOptunaのようなツールをHydraに埋め込んだりもできるので、拡張性があるという面でHydraを採用しています。もちろん他にも選択肢はあると思います。

司会者:ありがとうございます。他は質問です。OptunaではDefine-by-Runで探索空間を動的に変えられるけど、Hydraではそのような動的な変更定義できるのかという質問がきています。

中村:ちょっとこれについてはわからないですね。

開発者:開発者からお答えします。Hydraでは難しいかなと思います。動的な探索空間を書こうと思うと、今のところPythonでオブジェクティブ関数を書いてもらう必要があるかなと思います。

司会者:ありがとうございます。

中村:ありがとうございます。