optimize-steepdescent2d.py 技術ドキュメント

プログラムの動作

optimize-steepdescent2d.py は、2変数の関数に対する勾配降下法(最急降下法)を用いて、関数の最小値を探索するPythonスクリプトです。このプログラムは以下の機能を提供します。

  • 目的関数の最小化: 定義された2つの関数(楕円体関数 ellipsoid または複雑な多項式関数 gfunc)のいずれかを選択し、その最小値を見つけます。

  • 初期値の指定: コマンドライン引数から最適化の初期点 \(x_0 = (x_0, x_1)\) を指定できます。指定がない場合はデフォルト値 [0.0, 0.0] を使用します。

  • リアルタイム可視化: 最適化の進行状況を、関数の2次元等高線図と3次元ワイヤーフレーム図の両方でリアルタイムに表示します。探索経路は青い点でプロットされ、更新のたびに視覚的に確認できます。

  • 収束判定: 1ステップでの移動量が事前に設定された閾値 eps 未満になった場合に収束と判断し、探索を終了します。

  • 詳細な出力: 各反復で、現在の点 \(x = (x_0, x_1)\)、1ステップでの移動量 \(dx\) の最大値、および関数値 \(f(x)\) を標準出力に表示します。

このプログラムは、多変数関数の最適化アルゴリズムの一つである勾配降下法の挙動を理解し、視覚的に追跡するための教育的なツールとして機能します。

原理

このプログラムは、勾配降下法(Steepest Descent Method) を用いて2変数の関数の最小値を探索します。勾配降下法は、反復的に関数の最小値に近づくための最適化アルゴリズムです。

基本的な考え方は以下の通りです。

  1. 勾配の計算: 現在の点 \(x_k\) において、目的関数 \(f(x)\) の勾配 \(\nabla f(x_k)\) を計算します。勾配は、関数が最も急峻に増加する方向を示します。

  2. 移動方向の決定: 最小値を探索するためには、勾配の逆方向(関数が最も急峻に減少する方向)に移動します。

  3. 点の更新: 現在の点 \(x_k\) を、勾配の逆方向に学習率(またはステップサイズ)\(\alpha\) を掛けた分だけ移動させて、新しい点 \(x_{k+1}\) を計算します。

勾配降下法の更新式は次のようになります。

\[x_{k+1} = x_k - \alpha \nabla f(x_k)\]

ここで、\(x_k\) は現在の点、\(x_{k+1}\) は次の点、\(\alpha\) は学習率(プログラムでは alpha)、\(\nabla f(x_k)\) は点 \(x_k\) における目的関数 \(f(x)\) の勾配ベクトルです。

プログラムでは、以下の2つの関数とその1階微分(勾配の成分)が定義されています。

  1. 楕円体関数 (ellipsoid / efunc): 目的関数: $\(f(x_0, x_1) = x_0^2 + 9.0x_1^2\)\( 勾配の成分 (\)i=0, 1\(): \)\(\frac{\partial f}{\partial x_0} = 2.0x_0\)\( \)\(\frac{\partial f}{\partial x_1} = 18.0x_1\)$

  2. 複雑な多項式関数 (gfunc): 目的関数: $\(f(x_0, x_1) = -3.0 - 10.0 x_0 - 30.0 x_0^2 + 1.5 x_0^3 + 3.0 x_0^4 + 30.0 x_1 - 30.0 x_1^2 + 3.0 x_1^4 + 3.0 x_0 x_1^2\)\( 勾配の成分 (\)i=0, 1\(): \)\(\frac{\partial f}{\partial x_0} = -10.0 - 60.0 x_0 + 4.5 x_0^2 + 12.0 x_0^3 + 3.0 x_1^2\)\( \)\(\frac{\partial f}{\partial x_1} = 30.0 - 60.0 x_1 + 12.0 x_1^3 + 6.0 x_0 x_1\)$

各反復において、現在の点 \(x_0\) における勾配の各成分 \(Si[i] = \frac{\partial f}{\partial x_i}(x_0)\) が計算され、これを用いて次の移動量 \(dx = -\alpha \cdot Si\) が計算されます。 収束は、1回の更新で移動した距離 dxmax (プログラムでは \(max(|dx_0|, |dx_1|)\)) が、事前に設定された小さな値 eps (\(1.0 \times 10^{-5}\)) より小さくなった場合に判定されます。

必要な非標準ライブラリとインストール方法

このプログラムの実行には、以下のPython非標準ライブラリが必要です。

  • NumPy: 数値計算を効率的に行うためのライブラリ。

  • Matplotlib: グラフ描画のためのライブラリ。特に3Dプロット機能も使用します。

これらのライブラリは、Pythonのパッケージマネージャーである pip を使ってインストールできます。

pip install numpy matplotlib

必要な入力ファイル

optimize-steepdescent2d.py は、実行に必要な特定の入力ファイルを必要としません。

最適化の初期点 x0 はコマンドライン引数として直接指定するか、プログラム内のデフォルト値 [0.0, 0.0] が使用されます。

生成される出力ファイル

optimize-steepdescent2d.py は、プログラムの実行によっていかなるファイルも生成しません。

すべての結果は、標準出力(コンソール)にテキストとして表示されるか、matplotlib によってリアルタイムでグラフとして可視化されます。

コマンドラインでの使用例 (Usage)

optimize-steepdescent2d.py は、オプションで初期点の座標をコマンドライン引数として受け取ります。

基本的な実行形式:

python optimize-steepdescent2d.py [初期x座標] [初期y座標]

引数の意味:

  • [初期x座標]: 最適化を開始する点のX座標 (float型)。省略された場合、x0[0] はデフォルトの 0.0 になります。

  • [初期y座標]: 最適化を開始する点のY座標 (float型)。省略された場合、x0[1] はデフォルトの 0.0 になります。

コマンドラインでの具体的な使用例

例1: 引数を指定しない場合(デフォルトの初期点 [0.0, 0.0] で実行)

python optimize-steepdescent2d.py

実行結果の説明: このコマンドを実行すると、プログラムはデフォルトの初期点 \((0.0, 0.0)\) から楕円体関数 (ellipsoid) の最小値探索を開始します。標準出力には、各反復での現在位置 \(x\)、1ステップでの移動量 \(dx\)、および関数値 \(f(x)\) が表示されます。同時に、Matplotlibのウィンドウが開き、関数の等高線図と3Dワイヤーフレーム図上に、探索経路が青い点でリアルタイムにプロットされます。収束すると、最終的な最適解と関数値が表示され、グラフはユーザーがEnterキーを押すまで表示され続けます。

Find minimum / maximum point by Newton-Raphson method

x0 = (0.0, 0.0): f = 0.0
   dx= [0. 0.]
   (中略)
  13: x = (-0.000002,  0.000000) dx = -0.000002: f =  0.000000
  14: x = (-0.000001,  0.000000) dx = -0.000001: f =  0.000000
Converged at x =  [-1.07374182e-06  0.00000000e+00]  dx = 1.073741824e-06   f = 1.1529215046068469e-12
Press enter to terminate:

(グラフが開き、原点に向かって青い点が収束していく様子が可視化されます。)

例2: 初期点を指定して実行

python optimize-steepdescent2d.py 3.0 2.0

実行結果の説明: このコマンドを実行すると、初期点が \((3.0, 2.0)\) に設定され、そこから最適化が開始されます。同様に、標準出力には反復ごとの詳細情報が表示され、グラフ上では \((3.0, 2.0)\) から探索が始まり、最小値に向かって移動する様子が可視化されます。

Find minimum / maximum point by Newton-Raphson method

x0 = (3.0, 2.0): f = 45.0
   dx= [-0.18 -1.08]
   (中略)
  22: x = (-0.000001,  0.000000) dx = -0.000001: f =  0.000000
  23: x = (-0.000001,  0.000000) dx = -0.000001: f =  0.000000
Converged at x =  [-7.38202568e-07  0.00000000e+00]  dx = 7.38202568e-07   f = 5.449429408453531e-13
Press enter to terminate:

(グラフが開き、点 (3.0, 2.0) から原点に向かって青い点が収束していく様子が可視化されます。)

例3: 初期点のX座標のみ指定(Y座標はデフォルト)

python optimize-steepdescent2d.py -2.5

実行結果の説明: このコマンドでは、初期点のX座標が \(-2.5\) に設定され、Y座標はデフォルトの \(0.0\) のままとなります。したがって、初期点 \((-2.5, 0.0)\) から最適化が開始されます。

Find minimum / maximum point by Newton-Raphson method

x0 = (-2.5, 0.0): f = 6.25
   dx= [0.15 0.  ]
   (中略)
  18: x = (-0.000001,  0.000000) dx = -0.000001: f =  0.000000
  19: x = (-0.000001,  0.000000) dx = -0.000001: f =  0.000000
Converged at x =  [-9.72978051e-07  0.00000000e+00]  dx = 9.72978051e-07   f = 9.466858164052304e-13
Press enter to terminate:

(グラフが開き、点 (-2.5, 0.0) から原点に向かって青い点が収束していく様子が可視化されます。)