HELLO CYBERNETICS

深層学習、機械学習、強化学習、信号処理、制御工学、量子計算などをテーマに扱っていきます

ディープラーニングのハイパーパラメータ自動調整の概要

 

 

follow us in feedly

https://cdn.blog.st-hatena.com/images/theme/og-image-1500.png

 

はじめに

ディープラーニングのハイパーパラメータ調整がとんでもなく退屈なことは周知の事実(?)です。一度学習を回すとその経過が気になってログを眺めてしまう人も多いのではないでしょうか。どうも望みがなさそうならさっさと次の値を試したいという思いもあることでしょう。そして、なるべく数を打ちながら良さげなハイパーパラメータの範囲を早く絞り込みたいと思うのではないでしょうか。

 

こういうこと自体を上手く自動化するような試みが欲しくなります。古典的な方法ではグリッドサーチで、とにかく考えうるパターン全部試してやれ!というものがあります。しかしこの方法はディープラーニングのように一回の学習に時間が掛かる場合には有効ではありません。

 

今回は上手いハイパーパラメータの選び方をしてくれて、勝手に実験を進めてくれる便利な手法たちの概要について説明します。

 

ハイパーパラメータ自動調整の概要

学習という関数

まずハイパーパラメータの自動調整について概要を抑えるために、「ニューラルネットの学習」という関数を考えましょう。例として、「2つのハイパーパラメータを入力してやると、その結果Lossという評価指標を返す関数」という設定で行きます。

 

f:id:s0sem0y:20180210072145p:plain

 

私たちが知りたいのは「どのようなハイパーパラメータ\alpha, \betaを使ってやると小さなLossになるのか」ということです。これは未知のTraining(\alpha,\beta)という関数の最小値が知りたいということに相当します。

 

グリッドサーチ

さて、上記で考えたTraining(\alpha,\beta)という関数をグリッドサーチによって総当たりに調べることは、ひたすら(\alpha,\beta)の組を関数に代入して、その出力を記録することで関数の形状を知ろうという試みになります。

 

関数の形状を調べつくせば、当然最小値がどこかもわかります。上手いハイパーパラメータが見つかってめでたしめだたしというわけです。

 

さて、関数が直ちに値を返してくれるのならばこのような方法でも構いません。しかし、今考えている関数は引数を受け取ってから値を返すまでに1時間掛かるかもしれません。こんな方法はとてもとっていられないのです。

 

関数近似器(ガウス過程)による方法

時間の都合上、私たちが試すことのできる(\alpha,\beta)には限りがあります。ならば、既に試したハイパーパラメータの値から他の組ではどうなっていそうかを予測しながら選んでいくしかありません。

 

f:id:s0sem0y:20180210075729p:plain

すなわち、ここで考えられるのはTraining(\alpha,\beta)という関数それ自体を関数近似器で予測してしまうという方法です。

 

1.少数の(\alpha,\beta)を使ってその出力Training(\alpha,\beta)を観測し、関数がどんな形をしていそうかを関数近似器で表現する(つまり未観測の(\alpha,\beta)ではどうなっていそうかを予測させる)。

 

2.関数近似器による予測から、更に良い値を示しそうな(\alpha,\beta)を使って実際に出力を観測する。この時、「1.」の関数近似器での予測は外れているかもしれない。

 

3.「2.」の結果を新たな観測データとして関数近似器の情報を更新し、再度良さそうな(\alpha,\beta)を試す。

 

4.良さそうなTraining(\alpha,\beta)を試し切るまで「2.」と「3.」ループさせる(あるいは適当な回数を指定して止める)。

 

という方法がとれます。ではどんな関数近似器を使えば良いのか?というところですが、どうやら、ガウス過程がよく用いられるようです。

 

ガウス過程は万能な近似器ですからなんだかよくわからん学習なる関数を近似「1.」することに使えそうです(いや、本当は入力が近ければ、出力値も近いことが期待される)。またベイズ更新で関数の近似をデータが観測されるごとに更新していくことができます。つまり「2.」「3.」のことができます。

 

更に観測データが少ない段階ではベイズ的手法では強い確信を持って関数の形状を決定しません。従って最初は良いところ(Training(\alpha,\beta)の値が小さくなるような(\alpha,\beta))がどこかほとんどわからない(つまり関数の形状が全く分からない)という予測をします。なので割と幅広く(\alpha,\beta)を試していくことができます。データが増えてくれば、だいたいTraining(\alpha,\beta)の予測に自信が持てるようなっていき、値を小さくしそうな(\alpha,\beta)については全て試し切っただろうということで「4.」の判断を下すことができます。

 

最適化って言っていますが、基本的にはガウス過程自体は関数近似器であって近似に基づいて予測を行いながら探す場所を決めていくという方法になります(ベイズによる関数近似の特性を上手に使った最適化ということです)。

 

ちなみにガウス過程の予測結果に基づいて、どのように次の探索場所を決めるのかということに関しては幾つか方法があります。

 

以下がとても分かりやすいです。

www.slideshare.net

 

 

メタヒューリスティック最適化

これはある意味当然の発想かな?と私もずっと思っていましたが、計算コストは馬鹿高いこと間違いなしです。俗にいう遺伝的アルゴリズムや群知能(粒子群最適化)、進化計算の類を用いて、Training(\alpha,\beta)という関数の最小値を見つける方法です。

 

遺伝的アルゴリズムも群知能も進化計算も、要するに上手く試すべき(\alpha,\beta)を絞り込んでいく方法ですから、ガウス過程を用いた方法よりも発想としては直感的です。

 

ちなみに遺伝的アルゴリズムや群知能などはメタヒューリスティック最適化と呼ばれる、問題の形式によらず何にでも使える(良い結果が出るとは言っていない)タイプの最適化法で、だいたいノーフリーランチ定理なんてのは(ディープラーニングの批判でも見かけるけど)本来はこの手の最適化手法に対して言及されているものです。

 

s0sem0y.hatenablog.com

 

 

強化学習

 Training(\alpha,\beta)を未知環境と見なして、ハイパーパラメータの選定を行動とすれば見事に強化学習の問題に帰着できます。

 

f:id:s0sem0y:20180210081834p:plain

報酬はLossが下がったら与えればいいのでしょうか?細かい設定はともかくとして、問題としては上記の図のような形式を取るでしょう。

 

最近の強化学習ではエージェントの方がニューラルネットワークで表現されるようになっており、もやはニューラルネットワーク学習のハイパーパラメータを決めてやるためにニューラルネットワークで構成したエージェントによる強化学習を使うという馬鹿みたいな人工知能ここに極まりけり!なことも考えられます。

 

 

まとめ

どの手法でも大体以下のようなパラダイムです。

 

f:id:s0sem0y:20180210083032p:plain

 

意外と単純です。

なんというか面倒な単純作業(?)の自動化という類の解決方法ですね。

 

 

ライブラリ

ベイズ最適化のライブラリは便利なのが2つありまして1つは、GPyOptです。

sheffieldml.github.io

 

以下の利用方法を解説してくれている記事もあります。

qiita.com

 

 

 

もう1つはscikit optimizeです。使い方はGPyOptとほとんど変わりません。GPyOptの方がオブジェクト指向っぽい程度の違い(プロットとかが)。

 

github.com

 

 

 

一方ベイズ推論はハイパーパラメータ自体を同時に推定したり、ハイパーパラメータを積分消去したりして上記のような必要性をなくしております(現代的なニューラルネットワークのパラメータとハイパーパラメータをベイズ推論するのは、計算量的にかなり厳しいと思われます。画期的サンプリング法が必要となりそうです)

 

 

s0sem0y.hatenablog.com

s0sem0y.hatenablog.com

s0sem0y.hatenablog.com