SciPy - 最佳化



scipy.optimize 包提供了一些常用的最佳化演算法。此模組包含以下方面:

  • 使用各種演算法(例如 BFGS、Nelder-Mead 單純形、牛頓共軛梯度、COBYLA 或 SLSQP)進行多元標量函式的無約束和約束最小化 (minimize())

  • 全域性(蠻力)最佳化例程(例如,anneal()、basinhopping())

  • 最小二乘最小化 (leastsq()) 和曲線擬合 (curve_fit()) 演算法

  • 標量單變數函式最小化器 (minimize_scalar()) 和根查詢器 (newton())

  • 使用各種演算法(例如混合 Powell、Levenberg-Marquardt 或大規模方法,如 Newton-Krylov)的多元方程組求解器 (root())

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

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

$$f(x) = \sum_{i = 1}^{N-1} \:100(x_i - x_{i-1}^{2})$$

此函式的最小值為 0,當 xi = 1 時達到。

Nelder-Mead 單純形演算法

在以下示例中,minimize() 例程與 Nelder-Mead 單純形演算法 (method = 'Nelder-Mead') 一起使用(透過 method 引數選擇)。讓我們考慮以下示例。

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]

單純形演算法可能是最小化一個相當良好的函式的最簡單方法。它只需要函式評估,並且是簡單最小化問題的不錯選擇。但是,因為它不使用任何梯度評估,所以找到最小值可能需要更長時間。

另一個只需要函式呼叫即可找到最小值的最佳化演算法是 Powell 方法,可以透過在 minimize() 函式中設定 method = 'powell' 來使用。

最小二乘法

求解具有變數邊界的非線性最小二乘問題。給定殘差 f(x)(n 個實變數的 m 維實函式)和損失函式 rho(s)(標量函式),least_squares 找到成本函式 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 分別使用來自 MINPACK 的 Powell 的混合方法Levenberg-Marquardt 方法

以下示例考慮了單變數超越方程。

x2 + 2cos(x) = 0

其根可以如下找到:

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])
廣告

© . All rights reserved.