BFGSメソッドまたは最も効果的な最適化メソッドの1つ。 Pythonの実装例









数値最適化の反復法であるBFGSメソッドは、その研究者にちなんで名付けられました: Bロイデン、 Fレッチャー、 Gオールドファーブ、 Sハノ。 いわゆる準ニュートン法のクラスに属します。 ニュートン法とは対照的に、準ニュートン法はヘッセ関数を直接計算しません。 二次偏導関数を見つける必要はありません。 代わりに、ヘッセ行列はこれまでに実行された手順に基づいて近似的に計算されます。



メソッドにはいくつかの変更があります。

L-BFGS (メモリ使用量の制限)-多数の未知の場合に使用されます。

L-BFGS-Bは、多次元キューブでのメモリ使用量が制限された変更です。



この方法は効果的で安定しているため、最適化機能でよく使用されます。 たとえば、Python言語の一般的なライブラリであるSciPyでは、最適化機能はデフォルトでBFGS、L-BFGS-Bを使用します。





アルゴリズム





何らかの機能を与えましょう fxy そして最適化問題を解きます: minfxy

一般的な場合の場所 fxy は、連続的な二次導関数を持つ非凸関数です。



ステップ1

開始点を初期化する x0 ;

検索の精度を設定します ε > 0;

初期近似を決定します H0=B10 どこで B10 -逆ヘッセ関数;



初期近似の選択方法 H0

残念ながら、すべての場合にうまく機能する一般的な公式はありません。 初期近似として、初期点で計算された関数のヘッセ行列を取ることができます x0 。 それ以外の場合、適切に調整された非縮退行列を使用できますが、実際には、多くの場合、単一の行列が使用されます。



ステップ番号2

検索する方向のポイントを見つけると、次のように決定されます。





pk=Hk nablafk









ステップ番号3

計算する xk+1 再帰関係を通じて:





xk+1=xk+αkpk







係数 αk 線形検索(行検索)を使用して見つける αk ウルフの条件を満たす





fxk+αkpk leqfxk+c1αk nablafTkpk











 nablafxk+αkpkTpk geqc2 nablafTkpk







定数 s1 そして s2 次のように選択します。 0 leqc1 leqc2 leq1 。 ほとんどの実装では: c1=0.0001 そして s2=0.9



実際、これを見つけます αk 関数の値 fxk+αkpk 最低限。



ステップ4

ベクトルを定義します。





sk=xk+1xk











yk= nablafk+1 nablafk







sk -反復のアルゴリズムのステップ、 yk -反復で勾配を変更します。



ステップ番号5

次の式に従ってヘッセ関数を更新します。





Hk+1=IρkskyTkHkIρkyksTk+ρsksTk







どこで ρk





ρk= frac1yTksk







I 単位行列です。



発言



式を見る yksTk 2つのベクトルの外積です

2つのベクトルを定義します U そして V その外積は行列積と同等です UVT 。 たとえば、平面内のベクトルの場合:







UVT= beginpmatrixU1U2 endpmatrix beginpmatrixV1V2 endpmatrix= beginpmatrixU1V1U1V2U2V1U2V2 endpmatrix









ステップ6

このアルゴリズムは、不等式が真になるまで実行され続けます。 | nablafk|>ε



アルゴリズムの概略











次の関数の極値を見つけます。 fxy=x2xy+y2+9x6y+20

出発点として、 x0=11 ;

必要な精度 ε=0.001 ;



関数の勾配を見つける fxy





 nablaf= beginpmatrix2xy+9x+2y6 endpmatrix







反復番号0





x0=11







ポイントで勾配を見つける x0





 nablafx0= beginpmatrix105 endpmatrix







検索の終了を確認します。





| nablafx0|= sqrt102+52=11.18











| nablafx0|=11.18>0.001







不等式は成り立たないため、反復プロセスを継続します。



検索する方向にポイントを見つけます。





p0=H0 nablafx0= beginpmatrix1001 endpmatrix beginpmatrix105 endpmatrix= beginpmatrix105 endpmatrix







どこで H0=I 単位行列です。



これを探しています α0 geq 0から fx0+α0p0=minfx0+α0p0



分析的に、問題は1つの変数の関数の極値を見つけることで軽減できます。

$$表示$$ x_0 +α_0* p_0 =(1、1)+α_0(-10、5)=(1-10α_0、1 +5α_0)$$表示$$







それから



$インライン$ f(α_0)=(1-10α_0)^ 2-(1-10α_0)(1 +5α_0)+(1 +5α_0)^ 2 + 9(1-10α_0)-6(1 +5α_0)+ 20 $インライン$



式を単純化すると、導関数が見つかります。





 frac partialf partialx=350α0125=0\右α0=0.357







次のポイントを見つける x1





x1=x0+α0p0=2.5712.786











s0=x1x0=2.5712.78611=3.5711.786







tの勾配の値を計算します。 x1







 nablafx1= beginpmatrix1.0712.143 endpmatrix











y0= nablafx1 nablafx0=1.0712.143105=8.9297.143









ヘッセ近似を求めます。





H1= beginpmatrix0.6940.3670.3670.709 endpmatrix







反復1:







x1=2.5712.786











 nablafx1= beginpmatrix1.0712.143 endpmatrix







検索の終了を確認します。







| nablafx1|=2.396>0.001









不等式は成り立たないため、反復プロセスを続けます。





H1= beginpmatrix0.6940.3670.3670.709 endpmatrix











p1=H1 nablafx1= beginpmatrix0.6940.3670.3670.709 endpmatrix beginpmatrix1.0712.143 endpmatrix= beginpmatrix1.5311.913 endpmatrix







見つける α1 > 0:



$インライン$ f(α_1)=-2.296α_1+(-1.913α_1+ 2.786)^ 2-(-1.913α_1+ 2.786)(-1.53​​1α_1-2.571)+(-1.53​​1α_1-2.571)^ 2-19.86 $ inline $





 frac partialf partialα1=6.15α15.74=0 Rightarrowα1=0.933







次に:





x2=3.5710.786











s1=x2x1=412.5712.786=1.4291.786







ポイントで勾配の値を計算する x2





 nablafx2= beginpmatrix00 endpmatrix











g1= nablafx2 nablafx1=001.0712.143=1.0712.143











H2= beginpmatrix0.6670.3330.3330.667 endpmatrix







反復2





x2=41







検索の終了を確認します。





| nablafx2|=0<0.001







不等式が満たされるため、検索は終了します。 関数の極値を分析的に見つけます;それは x2



メソッドの詳細



各反復はコストをかけて行うことができます。 On2 (さらに、関数の計算と勾配の推定のコスト)。 ここではない On3 線形システムの解法や複雑な数学演算などの操作。 このアルゴリズムは安定しており、超線形収束を備えており、ほとんどの実用的な問題には十分です。 ニュートンの手法がはるかに高速に(2次的に)収束しても、線形システムを解く必要があるため、各反復のコストは高くなります。 アルゴリズムの否定できない利点は、もちろん、二次導関数を計算する必要がないことです。



この方法が実際にうまく機能することは一般に受け入れられていますが、非凸平滑関数の場合のアルゴリズムの収束については、理論的にはほとんど知られていません。



BFGS式には自己修正プロパティがあります。 行列 H 関数の曲率を誤って推定し、この不適切な推定によりアルゴリズムの速度が低下した場合、ヘッセ行列の近似により、数ステップで状況を修正しようとします。 アルゴリズムの自己修正プロパティは、対応する線形検索が実装されている場合にのみ機能します(Wolfe条件が満たされている)。



Pythonの実装例



アルゴリズムは、numpyおよびscipyライブラリを使用して実装されます。 線形検索は、scipy.optimizeモジュールのline_search()関数を使用して実装されました。 この例では、反復回数に制限が課されています。



''' Pure Python/Numpy implementation of the BFGS algorithm. Reference: https://en.wikipedia.org/wiki/Broyden%E2%80%93Fletcher%E2%80%93Goldfarb%E2%80%93Shanno_algorithm ''' #!/usr/bin/python # -*- coding: utf-8 -*- import numpy as np import numpy.linalg as ln import scipy as sp import scipy.optimize # Objective function def f(x): return x[0]**2 - x[0]*x[1] + x[1]**2 + 9*x[0] - 6*x[1] + 20 # Derivative def f1(x): return np.array([2 * x[0] - x[1] + 9, -x[0] + 2*x[1] - 6]) def bfgs_method(f, fprime, x0, maxiter=None, epsi=10e-3): """ Minimize a function func using the BFGS algorithm. Parameters ---------- func : f(x) Function to minimise. x0 : ndarray Initial guess. fprime : fprime(x) The gradient of `func`. """ if maxiter is None: maxiter = len(x0) * 200 # initial values k = 0 gfk = fprime(x0) N = len(x0) # Set the Identity matrix I. I = np.eye(N, dtype=int) Hk = I xk = x0 while ln.norm(gfk) > epsi and k < maxiter: # pk - direction of search pk = -np.dot(Hk, gfk) # Line search constants for the Wolfe conditions. # Repeating the line search # line_search returns not only alpha # but only this value is interesting for us line_search = sp.optimize.line_search(f, f1, xk, pk) alpha_k = line_search[0] xkp1 = xk + alpha_k * pk sk = xkp1 - xk xk = xkp1 gfkp1 = fprime(xkp1) yk = gfkp1 - gfk gfk = gfkp1 k += 1 ro = 1.0 / (np.dot(yk, sk)) A1 = I - ro * sk[:, np.newaxis] * yk[np.newaxis, :] A2 = I - ro * yk[:, np.newaxis] * sk[np.newaxis, :] Hk = np.dot(A1, np.dot(Hk, A2)) + (ro * sk[:, np.newaxis] * sk[np.newaxis, :]) return (xk, k) result, k = bfgs_method(f, f1, np.array([1, 1])) print('Result of BFGS method:') print('Final Result (best point): %s' % (result)) print('Iteration Count: %s' % (k))
      
      







私の記事に関心をお寄せいただきありがとうございます。 彼女があなたにとって有益であり、あなたが多くを学んだことを願っています。



FUNNYDMANはあなたと一緒でした。 みなさんさようなら!



All Articles