Scipy優化演算法


scipy.optimize包提供了幾種常用的優化演算法。 該模組包含以下幾個方面 -

  • 使用各種演算法(例如BFGS,Nelder-Mead單純形,牛頓共軛梯度,COBYLA或SLSQP)的無約束和約束最小化多元標量函式(minimize())
  • 全域性(蠻力)優化程式(例如,anneal()basinhopping())
  • 最小二乘最小化(leastsq())和曲線擬合(curve_fit())演算法
  • 標量單變數函式最小化(minim_scalar())和根查詢(newton())
  • 使用多種演算法(例如,Powell,Levenberg-Marquardt混合或Newton-Krylov等大規模方法)的多元方程系統求解(root)

多變數標量函式的無約束和約束最小化

minimize()函式為scipy.optimize中的多變數標量函式提供了無約束和約束最小化演算法的通用介面。 為了演示最小化函式,考慮使NN變數的Rosenbrock函式最小化的問題 -

這個函式的最小值是0,當xi = 1時達到。

Nelder–Mead單純形演算法

在下面的例子中,minimize()例程與Nelder-Mead單純形演算法(method ='Nelder-Mead')一起使用(通過方法引數選擇)。參考下面的例子。

import numpy as np
from scipy.optimize import minimize

def rosen(x):

x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='nelder-mead')

print(res.x)

上述程式將生成以下輸出 -

[7.93700741e+54  -5.41692163e+53  6.28769150e+53  1.38050484e+55  -4.14751333e+54]

簡單演算法只需要函式評估,對於簡單的最小化問題是一個不錯的選擇。 但是,由於它不使用任何梯度評估,因此可能需要較長時間才能找到最小值。

另一種只需要函式呼叫來尋找最小值的優化演算法就是鮑威爾方法,它可以通過在minimize()函式中設定method ='powell'來實現。

 最小二乘

求解一個帶有變數邊界的非線性最小二乘問題。 給定殘差f(x)(n個實變數的m維實函式)和損失函式rho(s)(標量函式),最小二乘法找到代價函式F(x)的區域性最小值。 看看下面的例子。

在這個例子中,Rosenbrock函式的最小值不受自變數的限制。

#Rosenbrock Function
def fun_rosenbrock(x):
   return np.array([10 * (x[1] - x[0]**2), (1 - x[0])])

from scipy.optimize import least_squares
input = np.array([2, 2])
res = least_squares(fun_rosenbrock, input)

print (res)

請注意,我們只提供殘差的向量。 該演算法將成本函式構造為殘差的平方和,這給出了Rosenbrock()函式。 確切的最小值是x = [1.0,1.0]

上述程式將生成以下輸出 -

active_mask: array([ 0., 0.])
      cost: 9.8669242910846867e-30
      fun: array([ 4.44089210e-15, 1.11022302e-16])
      grad: array([ -8.89288649e-14, 4.44089210e-14])
      jac: array([[-20.00000015,10.],[ -1.,0.]])
   message: '`gtol` termination condition is satisfied.'
      nfev: 3
      njev: 3
   optimality: 8.8928864934219529e-14
      status: 1
      success: True
         x: array([ 1., 1.])

求根

讓我們了解求根如何在SciPy中使用。

標量函式

如果有一個單變數方程,則可以嘗試四種不同的尋根演算法。 這些演算法中的每一個都需要預期根的時間間隔的端點(因為函式會改變符號)。 一般來說,brentq是最好的選擇,但其他方法可能在某些情況下或學術目的有用。

定點求解

與找到函式零點密切相關的問題是找到函式的固定點的問題。 函式的固定點是函式評估返回點的點:g(x)= x。 顯然,gg的不動點是f(x)= g(x)-x的根。 等價地,ff的根是g(x)= f(x)+ x的固定點。 例程fixed_point提供了一個簡單的疊代方法,使用Aitkens序列加速度來估計gg的固定點,如果給出起點的話。

方程組
使用root()函式可以找到一組非線性方程的根。 有幾種方法可供選擇,其中hybr(預設)和lm分別使用Powell的混合方法和MINPACK中的Levenberg-Marquardt方法。

下面的例子考慮了單變數超越方程。

其根可以求解如下 -

import numpy as np
from scipy.optimize import root
def func(x):
   return x*2 + 2 * np.cos(x)
sol = root(func, 0.3)
print (sol)

執行上面範例程式碼,得到以下結果 -

fjac: array([[-1.]])
fun: array([ 2.22044605e-16])
message: 'The solution converged.'
   nfev: 10
   qtf: array([ -2.77644574e-12])
      r: array([-3.34722409])
   status: 1
   success: True
      x: array([-0.73908513])