Julia(Optim)で2変数関数の最小値・最大値を求める方法

どうも、木村(@kimu3_slime)です。

今回は、Julia(Optim)で2変数関数の最小値・最大値を求める方法を紹介します。

 

準備

Optimを使うので、持っていなければインストールしておきましょう。

準備として、以下のコードを実行しておきます。

 

2変数関数の最小値・最大値を求める方法

最初に、2変数関数

\[ f_1(x_1,x_2)  =x_1 ^2 +x_2 ^2\]

の最小値を求めてみましょう。

「optimize(関数,初期値)」で、初期値を出発点として関数の最小値を探索した結果が得られます。

「Candidate solution Final objective value:」が最小値です。今回の例ならば、1.251398e-09、すなわち\(10^{-9}\)と0に近い値が求まっています。

「Algorithm:」は探索に使ったアルゴリズムで、ネルダー・ミード法と呼ばれるものです。

 

最小値は「minimum(res)」、最小点(最小化点)は「Optim.minimizer(res)」で表示できます。

 

ネルダー・ミード法は微分の情報を使わない探索法なので、多少の誤差があるのが気になりますね。アルゴリズムとして、2次の微分を参照するニュートン法を指定してみましょう。

きれいに原点で最小値0を取ることがわかりました。

 

\(f_2(x_1,x_2)  =x_1 ^2 -x_2 ^2 \)の最小値を調べてみましょう。

探索は失敗し、最終値は負の方向に大きくなっていることがわかります。この関数に最小値(と最大値)は存在しません。

 

\(f_3 (x) = e^{-(x_1^2 +x_2 ^2)}\)の最大値を求めたいとしましょう。符号を反転させた\(-f_3\)の最小値を求めれば、最大値が求められます。

最小値が\(-1\)となっているので、求めたい関数の最大値は\(1\)です。

 

与える関数と探索のアルゴリズムによって、得られる結果は変わります。

非常に粗いヒューリスティックとして

解析的な勾配とヘシアンを持つ低次元問題には、トラスト領域を持つニュートン法を使用します。より大きな問題や解析的なヘシアンがない場合は,LBFGSを使用し,必要に応じてパラメータmを調整します.関数が微分不可能な場合、Nelder-Meadを使用します。ロバスト性にはHagerZhangラインサーチを、スピードにはBackTrackingを使用します。

引用、DeepL:Algorithm choice – Optim.jl

公式マニュアルによると、関数の解析的な性質の良さに応じて、ニュートン法、LBFGS法、Nelder-Mead法を試すと良いようです。

 

少し複雑な例として、

\[ \begin{aligned}f_4 = \sqrt{x_1^2+x_2^2}(|\sin(x_1)|+1)\end{aligned} \]

の最小値を、各アルゴリズムで求めてみましょう。

 

 

 

ニュートン法、LBFGS法では、ほぼ原点で最小値0が得られています。一方、ネルダー・ミード法では、\(x_1= 4\pi\)付近の極小値が得られていて、大域的な最小値が得られませんでした。

調査した関数\(f_4\)は絶対値により微分不可能な点(直線)を持っていますが、それは例外的で、多くの点で2階微分が計算できるので、その情報を使った方が最適な値にたどり着けるようですね。

 

以上、Julia(Optim)で2変数関数の最小値・最大値を求める方法を紹介してきました。

微分の計算を自分で行わなくても、関数を与えるだけで最小値を求めてくれるので便利ですね。

木村すらいむ(@kimu3_slime)でした。ではでは。

 

1から始める Juliaプログラミング
進藤 裕之(著), 佐藤 建太(著)
コロナ社 (2020-03-26T00:00:01Z)
5つ星のうち4.5
¥7,353 (コレクター商品)

 

こちらもおすすめ

2変数関数の極値の求め方、ヘッセ行列とは?

2次形式、正定値行列とは:2変数関数の極値判定を例に

2変数関数と偏微分、勾配:グラフ、接平面を描いてみよう

Julia(Plotly)でグリグリ動かせる3Dグラフを作る方法

ニュートン法によってルート、円周率の近似値を求めてみよう

Julia(SymPy)で1変数関数の最大値最小値を求める方法