Gpyとベイズ最適化とカーネル -kernelのlengthscaleを制御-
以前から、ベイズ最適化でベンチマーク関数を最適化する記事を書いています。
(記事中のリンクを参照)
今回はその応用で、最適化したい関数に関する事前知識を活用し、ガウス過程回帰モデルのカーネル(RBFカーネル)のlengthscaleを制御する事により最適化を効率的に進めることで、最適解を探索します。
関数形に関する事前知識を活用する
前の記事でのベイズ最適化では、ベイズ最適化のIterationの初期段階において、関数の予測平均が以下のように真っ平になるような状態が観測されていました。
カラーバーを見たら分かる通り、10のマイナス6乗のオーダーの勾配なので、ほぼ真っ平です。
もし事前に関数形が全く分かっていない場合であれば、このように「真っ平な予測平面でも出力できる」という表現力の高さは、ありがたい事です。
しかし、今回最適化したいAckley関数はこんな形です。
全くもって平らではありません。
事前に最適化したい関数形の詳細な形まで分かっていなくとも、このように「関数形のどっかになんらか極値が存在する」ことが分かっているのなら、先に示したような真っ平な予測平面を出力するのは非常に無駄です。
なぜならベイズ最適化は「少ないデータ数を効率的に活用し、最適解を探索できる」ことが強みなので、これを使用する時というのは「取得できるデータ数が限られている」場合がほとんどあり、そのような「取得できるデータ数が限られている」時に、絶対にありえない予測平面とその時の予測分散をから次の入力の提案値を得るのは、たとえそれが数回であったとしても大きな損失となりえるからです。
なので最適解を探索したい目的関数が「極値を持つ」という事前知識をもっている場合は、GPyのカーネルのlengthscaleを制御することで、上図のような「絶対にありえない平らな平面」を予測平均として出力せずに最適値を探索していくのが良いでしょう。
最適化に用いるメソッドを定義
ライブラリ
・GPy
・Scipy
・numpy
メソッド
大まかなメソッドは以下の記事で定義したBO_methodの中身と同じです。
今回はその中の、GP_modelを以下のように書き換えます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
def GP_Model(dim, data_x, data_y): """ ガウス過程回帰のモデルを構築する関数 param dim: 入力パラメータの次元数 param data_x: 入力パラメータ param data_y: y return: model """ kern = GPy.kern.RBF(dim, lengthscale=2) + GPy.kern.White(dim) Gpy_model = GPy.models.GPRegression(data_x, data_y, kern) # lengthscaleの範囲を設定 Gpy_model['sum.rbf.lengthscale'].constrain_bounded(1, 8) Gpy_model.optimize() return Gpy_model |
この変更によりOptimizeする際にRBFカーネルのlengthscaleが1 ~ 8の間の変数として扱われ、超巨大な値や極小な値になって平らな予測平均が出力されることを防ぎます。
可視化
ベイズ最適化と可視化の記事↓で定義した可視化メソッドを使用して、平らな平面が出力されることなく、最適解の探索が進んでいるか確認します。
可視化メソッドにしたがって出力したgifがこちら
(コマ送りを少しゆっくりにしました。)
Iterationの初期段階から40回目まで、一度も平らな面を出力せずに最適解の探索ができました。
心なしか、前よりも探索(予測では小さいと予測していないけど、分散が大きくなってきたところを踏んでみる事)もしっかり行われている気がします。
40回のIterationで求まる準最適解も、以前より質の良いモノになります。
まとめ
ベイズ最適化、gif動画にすると頑張って最適解を探しているのが愛くるしいですね。
次回は、今度こそ、獲得関数の可視化の記事を書こうと思います。
では。
ディスカッション
コメント一覧
まだ、コメントがありません