Scipy 简明教程

SciPy - Optimize

scipy.optimize package 提供了多种常用优化算法。此模块包含以下方面:

  1. 无约束和约束多元标量函数最小化(minimize()),使用各种算法(例如,BFGS、Nelder-Mead 单纯形、牛顿共轭梯度、COBYLA 或 SLSQP)

  2. 全局(暴力)优化例程(例如,anneal()、basinhopping())

  3. 最小二乘法最小化(leastsq())和曲线拟合(curve_fit())算法

  4. 标量一元函数最小化(minimize_scalar())和根查找器(newton())

  5. 多元方程系统求解器(root()),使用各种算法(例如,混合 Powell、Levenberg-Marquardt 或大型方法,例如 Newton-Krylov)

Unconstrained & Constrained minimization of multivariate scalar functions

minimize() functionscipy.optimize 中多元标量函数的无约束和约束最小化算法提供了一个公共接口。为了演示最小化函数,考虑最小化 NN 变量的 Rosenbrock 函数的问题:

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

此函数的最小值为 0,当 xi = 1 时实现。

Nelder–Mead Simplex Algorithm

在以下示例中,minimize() 例程与 Nelder-Mead simplex algorithm (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‘s method ,可以通过在 minimize() 函数中设置 method = 'powell' 来获得。

Least Squares

求解具有变量边界的非线性最小二乘问题。给定残差 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.])

Root finding

让我们了解根查找如何在 SciPy 中提供帮助。

Scalar functions

如果有一个单变量方程,有四种不同的根查找算法可以尝试。其中每种算法都需要预期中有根的间隔端点(因为函数改变符号)。一般而言, brentq 是最佳选择,但在某些情况下或出于学术目的,其他方法可能有用。

Fixed-point solving

一个与找到函数的零点密切相关的问题是找到函数的一个不动点。函数的不动点是评估函数返回该点的点:g(x) = x。显然, gg 的不动点是 f(x) = g(x)−x 的根。等效, ff 的根是 g(x) = f(x)+x 的不动点。如果给出了一个起点,则 fixed_point 例程提供了一种简单迭代方法,使用 Aitkens sequence acceleration 来估计 gg 的不动点。

Sets of equations

可以使用 root() function 找出非线性方程组的根。有几种方法可用,其中 hybr (默认)和 lm 分别使用 MINPACK 中的 hybrid method of PowellLevenberg-Marquardt method

以下示例考虑了单变量超越方程。

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