Nelder-Mead法による探索#

ここでは、Nelder-Mead法を用いて Himmelblau関数の最小値を探索する方法について説明します。 具体的な計算手順は以下の通りです。

  1. 入力ファイルを用意する

    入力パラメータをTOML形式で記述した入力ファイルを作成します。

  2. メインプログラムを実行する

    odatse コマンドを用いて計算を実行し、最適化問題を解きます。

サンプルファイルの場所#

サンプルファイルは sample/analytical/minsearch にあります。 フォルダには以下のファイルが格納されています。

  • input.toml

    メインプログラムの入力ファイル

  • do.sh

    本チュートリアルを一括計算するために準備されたスクリプト

また、計算結果を可視化するために sample/analytical フォルダ内の plot_himmel.py を利用します。

入力ファイルの説明#

メインプログラム用の入力ファイル input.toml を作成します。記述方法の詳細については「入力ファイル」の項を参照してください。

[base]
dimension = 2
output_dir = "output"

[solver]
name = "analytical"
function_name = "himmelblau"

[runner]
[runner.log]
interval = 20

[algorithm]
name = "minsearch"
seed = 12345

[algorithm.param]
min_list = [-6.0, -6.0]
max_list = [ 6.0,  6.0]
initial_list = [0, 0]

[base] セクションではプログラム全体で利用するパラメータを設定します。

  • dimension は最適化したい変数の個数です。Himmelblau関数は 2変数関数ですので、今の場合は 2 を指定します。

  • output_dir は出力先のディレクトリを指定します。

[solver] セクションではメインプログラムの内部で使用するソルバーとその設定を指定します。

  • name は使用するソルバーの名前です。このチュートリアルでは analytical ソルバーに含まれる解析関数の解析を行います。

  • function_nameanalytical ソルバー内の関数名を指定します。

[runner] セクションでは、逆問題解析アルゴリズムからソルバーの呼び出しに関する設定を行います。

  • [runner.log]interval は、ソルバー呼び出しのログをファイルへ書き出す間隔(バッファ件数)を指定します。呼び出しはすべて記録され、interval 件たまるごとにまとめて書き出されます。

[algorithm] セクションでは、使用するアルゴリズムとその設定をします。

  • name は使用するアルゴリズムの名前です。このチュートリアルでは、Nelder-Mead法 を用いた解析を行うので、 minsearch を指定します。

  • seed は乱数の初期値を指定します。

[algorithm.param] セクションでは、探索するパラメータの範囲や初期値を指定します。

  • min_listmax_list はそれぞれ探索範囲の最小値と最大値を指定します。

  • initial_list は初期値を指定します。

ここではデフォルト値を用いるため省略しましたが、その他のパラメータ、例えば Nelder-Mead 法で使用する収束判定条件などは、[algorithm.minimize] セクションで設定できます。詳細は 局所最適化アルゴリズムによる最適値探索 minsearch を参照してください。 詳細については「入力ファイル」の章を参照してください。

計算の実行#

最初にサンプルファイルが置いてあるフォルダへ移動します。(以下では、ODAT-SE パッケージをダウンロードしたディレクトリの直下にいることを仮定します。)

$ cd sample/analytical/minsearch

メインプログラムを実行します。計算時間は通常のPCで数秒程度で終わります。

$ odatse input.toml | tee log.txt

実行すると、以下のような出力がされます。

name            : minsearch
seed            : 12345
param.max_list  : [6.0, 6.0]
param.min_list  : [-6.0, -6.0]
param.initial_list: [0, 0]
eval: x=[0.375 0.375], fun=151.96923828125
eval: x=[0.0625 0.9375], fun=137.88186645507812
eval: x=[0.65625 1.46875], fun=100.34764289855957
eval: x=[0.328125 2.859375], fun=66.79089844226837
...
eval: x=[2.99996696 1.99999734], fun=4.2278370361994904e-08
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 40
         Function evaluations: 79
end of run

x1, x2 に各ステップでの候補パラメータと、その時の関数値が出力されます。 最終的に推定されたパラメータは output/res.txt に出力されます。今の場合、

fx = 4.2278370361994904e-08
x1 = 2.9999669562950175
x2 = 1.9999973389336225

が得られ、最小値を与える解の一つが求められたことが分かります。

計算結果の可視化#

Nelder-Mead法による解の探索の経路は output/0/SimplexData.txt に出力されています。 これをプロットするツールが sample/analytical/plot_himmel.py に用意されています。

$ python3 ../plot_himmel.py --xcol=1 --ycol=2 --output=output/res.pdf output/0/SimplexData.txt

上記を実行すると output/res.pdf が出力されます。

../_images/res_minsearch.png

Nelder-Mead法を用いた Himmelblau 関数の最小値探索。黒線は Himmelblau関数の関数値を表す等高線、青色のシンボルは探索経路。#

Himmelblau関数の関数値を表す等高線の上に Nelder-Mead法による探索の経路がプロットされます。初期値 (0, 0) からスタートして最小値を与える解の一つ (3, 2) に到達していることが分かります。