ベイズ最適化で、Ackley関数の最適解を探索

2019年12月29日

今回は、ベイズ最適化によってAckley関数の最適解を探索し、任意のベイズ最適化の繰り返しの回数ごとに、ガウス過程回帰によってどのような関数推定が成されているのかを可視化します。

細かい説明はまた別日にするとして、今回はGPyでの実装コードと結果を述べる程度の記事です。

僕が書いたコードよりももっと良い方法がある。or 間違いがある等あれば、どんどん指摘してください!お願いします。

ベイズ最適化に用いる関数を定義

まず、ベイズ最適化で用いるメソッドを関数化しておきます。

環境はPython 3.5。

ライブラリは、

・GPy

・numpy

・scipy

コードの中でも言及していますが、

・GP_Model : ガウス過程回帰のモデルを構築

・Produce_Best : 現状での最適値を返す関数(最大化、最小化のベイズ最適化で使用)

・EI_forMax : 最大化(または最小化)のための獲得関数EI

・EI_forApproach : 目的関数をある値に漸近させるための獲得関数EI(みたいなやつ)

・Optimization : 獲得関数を最適化する関数

これらの関数を使って、関数の最適解を探索します。

Ackley 関数について

推定する関数は、Ackley functionと呼ばれる、有名なベンチマーク関数。

可視化してみると、以下のような感じになります。

これは、プロットのメッシュ間隔を 1 にした時。

これを見た感じ、かなり単純な形に見えます。

しかし実際はかなり細かくギザギザとしている関数であり、局所解が複数存在します。

メッシュを二倍に細かくした図が以下。

ベイズ最適化による最適解の探索

ベイズ最適化によってAckley関数の最小値(最適解)を探索していきます。

また、その過程でガウス過程回帰がどのような予測分布を出力しているのかを可視化します。

コードは以下。

可視化にはmatplotlibを使用。

一番初めに紹介したファイルを「BO_Method」という名前にし、冒頭で中身の関数を取り出しています。

・Optimization を、BO_Methodで書いたものから便宜的に書き直しています。
(Ackley関数を(-30 ≦ x ≦ 30)で最適化するため。)

・初期点は20個で、ベイズ最適化の繰り返しの回数は、40回としている。

・matplotlibのimshowで軸がちゃんと表示されないところで、結構ハマりました。
普通にmeanの値をmesh状にして可視化するだけだと、軸が[0, 60]になってしまうんですね。
軸の数値を書き換えたり色々試しましたが、今回のように、ax.imshow の extent=[]をイジるのがベターのようです。

・(修正)メッシュグリッドを生成する時、
x1_mesh, x2_mesh = np.meshgrid(x1, x2)
としていましたが、これだと描画したい図に対してX2が上下逆の関係性で出力されていました。
なので、
x1_mesh, x2_mesh_inversion = np.meshgrid(x1, x2)
x2_mesh = np.flipud(x2_mesh_inversion)
として、上下関係を反転させ、目的にあったメッシュに直しています。

出力結果

gp_heat_mapという関数を使って、ベイズ最適化繰り返しの2回ごとに推定した関数形のヒートマップを出力しました。

たとえば、繰り返し6回目の推定関数は以下のような感じ。

推定関数のヒートマップ

大まかな形は予測できています。

もっと探索を進めていくと、Ackley関数の「ギザギザ具合」を学習し始め、濃淡のブチがはっきりしていきます。

繰り返し40回目だと以下の感じ。

推定関数の評価関数

ベイズ最適化の繰り返しにおける、関数推定の様子を可視化できました。

まとめ

次回はヒートマップに探索点のプロットを追加し、最適解探索の様子を可視化したいと思います。

また、別の機会に、このベイズ最適化が私の専攻である材料工学でどのように活用されているのかも紹介したいと思います。

では。

↓1日1タップで応援よろしくお願いします!

にほんブログ村 にほんブログ村へ

Python

Posted by arabica