SciPy - 优化

scipy.optimize包提供了几种常用的优化算法.此模块包含以下几个方面 :

  • 使用多种变量对多变量标量函数(最小化())进行无约束和约束最小化算法(例如BFGS,Nelder-Mead simplex,Newton Conjugate Gradient,COBYLA或SLSQP)

  • 全局(强力)优化程序(例如退火( ),bashopping())

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

  • 标量单变量函数最小化器(minimize_scalar())和根查找器(newton())

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

无约束&约束最小化多元标量函数

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')(通过方法参数选择).让我们考虑以下示例.

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

找根

让我们了解root查找方式有助于SciPy.

标量函数

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

定点解决方案

与查找函数的零密切相关的问题是找到函数的固定点的问题.函数的固定点是函数的求值返回点的点:g(x)= x.显然, gg 的固定点是f(x)= g(x)-x的根.等价地, ff 的根是g(x)= f(x)+ x的fixed_point.例程fixed_point提供了一个简单的迭代方法,使用 Aitkens序列加速来估算 gg 的固定点,如果给出了一个起点.

方程组

使用 root()函数可以找到一组非线性方程的根.有几种方法可供选择,其中 hybr (默认)和lm分别使用鲍威尔的混合方法 Levenberg-Marquardt方法 MINPACK.

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

x 2 + 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])