scipy.optimize.

minimize#

scipy.optimize.minimize(fun, x0, args=(), method=None, jac=None, hess=None, hessp=None, bounds=None, constraints=(), tol=None, callback=None, options=None)[source]#

对一个或多个变量的标量函数进行最小化。

参数:
funcallable

要最小化的目标函数。

fun(x, *args) -> float

其中 x 是一个形状为 (n,) 的一维数组,而 args 是一个包含完全指定该函数所需的固定参数的元组。

x0ndarray, shape (n,)

初始猜测。大小为 (n,) 的实数元素数组,其中 n 是自变量的数量。

argstuple, optional

传递给目标函数及其导数的额外参数 (funjachess 函数)。

methodstr or callable, optional

求解器的类型。应该是以下之一:

如果未给出,则选择为 BFGSL-BFGS-BSLSQP 之一,具体取决于问题是否有约束或边界。

jac{callable, ‘2-point’, ‘3-point’, ‘cs’, bool}, optional

计算梯度向量的算法。仅适用于 CG、BFGS、Newton-CG、L-BFGS-B、TNC、SLSQP、dogleg、trust-ncg、trust-krylov、trust-exact 和 trust-constr。如果它是可调用的,它应该是一个返回梯度向量的函数。

jac(x, *args) -> array_like, shape (n,)

其中 x 是一个形状为 (n,) 的数组,而 args 是一个包含固定参数的元组。如果 jac 是一个布尔值并且为 True,则假设 fun 返回一个包含目标函数和梯度的元组 (f, g)。方法 ‘Newton-CG’、‘trust-ncg’、‘dogleg’、‘trust-exact’ 和 ‘trust-krylov’ 要求提供可调用的函数,或者 fun 返回目标函数和梯度。如果为 None 或 False,则将使用绝对步长的 2 点有限差分估计来估计梯度。或者,可以使用关键字 {‘2-point’,‘3-point’,‘cs’} 选择有限差分方案,使用相对步长对梯度进行数值估计。这些有限差分方案会遵守任何指定的 bounds

hess{callable, ‘2-point’, ‘3-point’, ‘cs’, HessianUpdateStrategy}, optional

计算海森矩阵的方法。仅适用于 Newton-CG、dogleg、trust-ncg、trust-krylov、trust-exact 和 trust-constr。如果它是可调用的,它应该返回海森矩阵。

hess(x, *args) -> {LinearOperator, spmatrix, array}, (n, n)

其中 x 是一个 (n,) ndarray,而 args 是一个包含固定参数的元组。关键字 {‘2-point’,‘3-point’,‘cs’} 也可以用于选择有限差分方案,对海森矩阵进行数值估计。或者,可以利用实现 HessianUpdateStrategy 接口的对象来近似海森矩阵。可用的实现此接口的拟牛顿方法是:

并非所有选项都适用于每种方法;有关可用性,请参考注释。

hesspcallable, optional

目标函数的海森矩阵乘以任意向量 p。仅适用于 Newton-CG、trust-ncg、trust-krylov、trust-constr。只需要给出 hessphess 之一。如果提供 hess,则将忽略 hessphessp 必须计算海森矩阵乘以任意向量。

hessp(x, p, *args) ->  ndarray shape (n,)

其中 x 是一个 (n,) ndarray,p 是一个维度为 (n,) 的任意向量,而 args 是一个包含固定参数的元组。

boundssequence or Bounds, optional

Nelder-Mead、L-BFGS-B、TNC、SLSQP、Powell、trust-constr、COBYLA 和 COBYQA 方法的变量边界。有两种方法可以指定边界:

  1. Bounds 类的实例。

  2. 每个 x 中元素的 (min, max) 对的序列。None 用于指定无边界。

constraints{Constraint, dict} or List of {Constraint, dict}, optional

约束定义。仅适用于 COBYLA、COBYQA、SLSQP 和 trust-constr。

‘trust-constr’ 和 ‘cobyqa’ 的约束定义为一个单个对象或一个对象列表,这些对象指定了优化问题的约束。可用的约束是:

COBYLA、SLSQP 的约束定义为字典列表。每个字典都有以下字段:

typestr

约束类型:‘eq’ 表示等式,‘ineq’ 表示不等式。

funcallable

定义约束的函数。

jaccallable, optional

fun 的雅可比矩阵(仅适用于 SLSQP)。

argssequence, optional

要传递给函数和雅可比矩阵的额外参数。

等式约束表示约束函数的结果应为零,而不等式约束表示结果应为非负。请注意,COBYLA 仅支持不等式约束。

tolfloat, optional

终止容差。当指定 tol 时,所选的最小化算法会将一些相关的求解器特定容差设置为 tol。有关详细控制,请使用求解器特定的选项。

optionsdict, optional

求解器选项字典。除了 TNC 之外的所有方法都接受以下通用选项:

maxiterint

执行的最大迭代次数。根据方法的不同,每次迭代可能会使用多个函数评估。

对于 TNC,请使用 maxfun 而不是 maxiter

dispbool

设置为 True 以打印收敛消息。

有关方法特定的选项,请参阅 show_options

callbackcallable, optional

每次迭代后调用一个可调用对象。

除了 TNC、SLSQP 和 COBYLA 之外,所有方法都支持具有以下签名的可调用对象:

callback(intermediate_result: OptimizeResult)

其中 intermediate_result 是一个关键字参数,包含一个 OptimizeResult,其属性为 xfun,即参数向量和目标函数的当前值。请注意,参数的名称必须是 intermediate_result,以便回调函数被传递一个 OptimizeResult。如果回调函数引发 StopIteration,这些方法也将终止。

除了 trust-constr 之外,所有方法还支持类似的签名:

callback(xk)

其中 xk 是当前参数向量。

使用内省确定要调用上述哪个签名。

返回值:
resOptimizeResult

优化结果,表示为 OptimizeResult 对象。重要属性包括:x(解数组)、success(指示优化器是否成功退出,为布尔型标志)以及 message(描述终止原因)。有关其他属性的说明,请参阅 OptimizeResult

另请参阅

minimize_scalar

用于标量单变量函数的最小化算法接口

show_options

求解器接受的额外选项

注意事项

本节介绍可以通过“method”参数选择的可用求解器。默认方法为 BFGS

无约束最小化

方法 CG 使用 Polak 和 Ribiere 的非线性共轭梯度算法,它是 [5] pp.120-122 中描述的 Fletcher-Reeves 方法的变体。仅使用一阶导数。

方法 BFGS 使用 Broyden、Fletcher、Goldfarb 和 Shanno (BFGS) 的拟牛顿法 [5] pp. 136。它仅使用一阶导数。BFGS 即使在非光滑优化中也表现出良好的性能。此方法还会返回 Hessian 逆矩阵的近似值,存储在 hess_inv 中,位于 OptimizeResult 对象中。

方法 Newton-CG 使用 Newton-CG 算法 [5] pp. 168(也称为截断牛顿法)。它使用 CG 方法计算搜索方向。另请参阅 TNC 方法,它使用类似的算法进行带约束的最小化。适合大规模问题。

方法 dogleg 使用无约束最小化的狗腿信任域算法 [5]。此算法需要梯度和 Hessian;此外,Hessian 必须是正定的。

方法 trust-ncg 使用无约束最小化的牛顿共轭梯度信任域算法 [5]。此算法需要梯度,以及 Hessian 或计算 Hessian 与给定向量的乘积的函数。适合大规模问题。

方法 trust-krylov 使用无约束最小化的 Newton GLTR 信任域算法 [14][15]。此算法需要梯度,以及 Hessian 或计算 Hessian 与给定向量的乘积的函数。适合大规模问题。在不定问题上,它通常比 trust-ncg 方法需要更少的迭代次数,建议用于中、大规模问题。

方法 trust-exact 是一种无约束最小化的信任域方法,其中二次子问题几乎完全得到解决 [13]。此算法需要梯度和 Hessian(不要求Hessian 是正定的)。在许多情况下,它是一种牛顿方法,收敛所需迭代次数更少,建议用于中小型问题。

带约束的最小化

方法 Nelder-Mead 使用单纯形算法 [1][2]。此算法在许多应用中都非常稳健。但是,如果可以信任导数的数值计算,其他使用一阶和/或二阶导数信息的算法可能更可取,因为它们在一般情况下性能更佳。

方法 L-BFGS-B 使用 L-BFGS-B 算法 [6][7] 进行带约束的最小化。

方法 Powell 是 Powell 方法 [3][4] 的修改版本,它是一种共轭方向方法。它沿着方向集(direc 字段位于 optionsinfo 中)的每个向量进行顺序的一维最小化,方向集在主最小化循环的每次迭代中都会更新。函数不需要可微,并且不会进行任何求导。如果没有提供约束,则将使用无界线搜索。如果提供了约束,并且初始猜测位于约束范围内,则整个最小化过程中的每次函数评估都将在约束范围内。如果提供了约束,并且初始猜测位于约束范围之外,并且 direc 是满秩(默认情况下是满秩),则第一次迭代期间的一些函数评估可能位于约束范围之外,但第一次迭代之后每次函数评估都将在约束范围内。如果 direc 不是满秩,则某些参数可能无法优化,并且不能保证解位于约束范围内。

方法 TNC 使用截断牛顿算法 [5][8] 来最小化变量受约束的函数。此算法使用梯度信息;它也被称为牛顿共轭梯度法。它与上面描述的 Newton-CG 方法不同,因为它包装了 C 实现,并允许为每个变量指定上界和下界。

带约束的最小化

方法 COBYLA 使用线性逼近约束优化 (COBYLA) 方法 [9][10][11]。该算法基于目标函数和每个约束的线性逼近。该方法包装了算法的 FORTRAN 实现。约束函数“fun”可以返回单个数字,也可以返回数组或数字列表。

方法 COBYQA 使用二次逼近约束优化 (COBYQA) 方法 [18]。该算法是一种无导数信任域 SQP 方法,基于目标函数和每个非线性约束的二次逼近。边界被视为不可松弛约束,这意味着算法始终在整个优化过程中尊重它们。

方法 SLSQP 使用顺序最小二乘规划来最小化多个变量的函数,这些变量可以是任何组合的边界、等式和不等式约束。该方法包装了最初由 Dieter Kraft [12] 实现的 SLSQP 优化子程序。请注意,包装器通过将无穷大值转换为较大的浮点值来处理边界中的无穷大值。

方法 trust-constr 是一种用于带约束优化的信任域算法。它根据问题定义在两种实现之间切换。它是 SciPy 中实现的最通用的带约束最小化算法,并且最适合大规模问题。对于等式约束问题,它是 Byrd-Omojokun 信任域 SQP 方法的实现,如 [17][5],p. 549 中所述。当施加不等式约束时,它会切换到 [16] 中描述的信任域内点方法。这种内点算法反过来通过引入松弛变量并针对障碍参数的逐渐减小的值解决一系列等式约束的障碍问题来解决不等式约束。之前描述的等式约束 SQP 方法用于解决子问题,随着迭代越来越接近解,子问题会获得越来越高的精度。

有限差分选项

对于方法 trust-constr,可以使用三种有限差分方案来近似梯度和 Hessian:{‘2-point’, ‘3-point’, ‘cs’}。‘cs’ 方案可能是最精确的,但它要求函数能够正确处理复数输入并在复数平面上可微。‘3-point’ 方案比 ‘2-point’ 更精确,但需要两倍的操作。如果通过有限差分来估计梯度,则必须使用其中一种拟牛顿策略来估计 Hessian。

针对 hess 关键字的特定于方法的选项

method/Hess

None

callable

‘2-point/’3-point’/’cs’

HUS

Newton-CG

x

(n, n) LO

x

x

dogleg

(n, n)

trust-ncg

(n, n)

x

x

trust-krylov

(n, n)

x

x

trust-exact

(n, n)

trust-constr

x

(n, n) LO sp

x

x

其中 LO=线性算子,sp=稀疏矩阵,HUS=HessianUpdateStrategy

自定义最小化器

传递自定义最小化方法可能很有用,例如在使用此方法的前端(如 scipy.optimize.basinhopping 或其他库)时。您可以简单地将可调用对象作为 method 参数传递。

可调用对象被调用为 method(fun, x0, args, **kwargs, **options),其中 kwargs 对应于传递给 minimize 的任何其他参数(如 callbackhess 等),除了 options 字典,其内容也作为 method 参数逐对传递。此外,如果 jac 已作为布尔类型传递,则 jacfun 会被修改,以便 fun 只返回函数值,而 jac 会被转换为返回雅可比矩阵的函数。该方法应返回一个 OptimizeResult 对象。

提供的 method 可调用对象必须能够接受(并可能忽略)任意参数;minimize 所接受的参数集在将来的版本中可能会扩展,然后这些参数将被传递给该方法。您可以在 scipy.optimize 教程中找到一个示例。

参考文献

[1]

Nelder, J A, and R Mead. 1965. A Simplex Method for Function Minimization. The Computer Journal 7: 308-13.

[2]

Wright M H. 1996. Direct search methods: Once scorned, now respectable, in Numerical Analysis 1995: Proceedings of the 1995 Dundee Biennial Conference in Numerical Analysis (Eds. D F Griffiths and G A Watson). Addison Wesley Longman, Harlow, UK. 191-208.

[3]

Powell, M J D. 1964. An efficient method for finding the minimum of a function of several variables without calculating derivatives. The Computer Journal 7: 155-162.

[4]

Press W, S A Teukolsky, W T Vetterling and B P Flannery. Numerical Recipes (any edition), Cambridge University Press.

[5] (1,2,3,4,5,6,7,8)

Nocedal, J, and S J Wright. 2006. Numerical Optimization. Springer New York.

[6]

Byrd, R H and P Lu and J. Nocedal. 1995. A Limited Memory Algorithm for Bound Constrained Optimization. SIAM Journal on Scientific and Statistical Computing 16 (5): 1190-1208.

[7]

Zhu, C and R H Byrd and J Nocedal. 1997. L-BFGS-B: Algorithm 778: L-BFGS-B, FORTRAN routines for large scale bound constrained optimization. ACM Transactions on Mathematical Software 23 (4): 550-560.

[8]

Nash, S G. Newton-Type Minimization Via the Lanczos Method. 1984. SIAM Journal of Numerical Analysis 21: 770-778.

[9]

Powell, M J D. A direct search optimization method that models the objective and constraint functions by linear interpolation. 1994. Advances in Optimization and Numerical Analysis, eds. S. Gomez and J-P Hennart, Kluwer Academic (Dordrecht), 51-67.

[10]

Powell M J D. Direct search algorithms for optimization calculations. 1998. Acta Numerica 7: 287-336.

[11]

Powell M J D. A view of algorithms for optimization without derivatives. 2007.Cambridge University Technical Report DAMTP 2007/NA03

[12]

Kraft, D. A software package for sequential quadratic programming. 1988. Tech. Rep. DFVLR-FB 88-28, DLR German Aerospace Center – Institute for Flight Mechanics, Koln, Germany.

[13]

Conn, A. R., Gould, N. I., and Toint, P. L. Trust region methods. 2000. Siam. pp. 169-200.

[14]

F. Lenders, C. Kirches, A. Potschka: “trlib: A vector-free implementation of the GLTR method for iterative solution of the trust region problem”, arXiv:1611.04718

[15]

N. Gould, S. Lucidi, M. Roma, P. Toint: “Solving the Trust-Region Subproblem using the Lanczos Method”, SIAM J. Optim., 9(2), 504–525, (1999).

[16]

Byrd, Richard H., Mary E. Hribar, and Jorge Nocedal. 1999. An interior point algorithm for large-scale nonlinear programming. SIAM Journal on Optimization 9.4: 877-900.

[17]

Lalee, Marucha, Jorge Nocedal, and Todd Plantega. 1998. On the implementation of an algorithm for large-scale equality constrained optimization. SIAM Journal on Optimization 8.3: 682-706.

[18]

Ragonneau, T. M. Model-Based Derivative-Free Optimization Methods and Software. PhD thesis, Department of Applied Mathematics, The Hong Kong Polytechnic University, Hong Kong, China, 2022. URL: https://theses.lib.polyu.edu.hk/handle/200/12294.

示例

让我们考虑最小化 Rosenbrock 函数的问题。此函数(及其相应的导数)在 rosen(分别为 rosen_derrosen_hess)中实现,在 scipy.optimize 中。

>>> from scipy.optimize import minimize, rosen, rosen_der

Nelder-Mead 方法的一个简单应用是

>>> x0 = [1.3, 0.7, 0.8, 1.9, 1.2]
>>> res = minimize(rosen, x0, method='Nelder-Mead', tol=1e-6)
>>> res.x
array([ 1.,  1.,  1.,  1.,  1.])

现在使用 BFGS 算法,使用一阶导数和一些选项

>>> res = minimize(rosen, x0, method='BFGS', jac=rosen_der,
...                options={'gtol': 1e-6, 'disp': True})
Optimization terminated successfully.
         Current function value: 0.000000
         Iterations: 26
         Function evaluations: 31
         Gradient evaluations: 31
>>> res.x
array([ 1.,  1.,  1.,  1.,  1.])
>>> print(res.message)
Optimization terminated successfully.
>>> res.hess_inv
array([
    [ 0.00749589,  0.01255155,  0.02396251,  0.04750988,  0.09495377],  # may vary
    [ 0.01255155,  0.02510441,  0.04794055,  0.09502834,  0.18996269],
    [ 0.02396251,  0.04794055,  0.09631614,  0.19092151,  0.38165151],
    [ 0.04750988,  0.09502834,  0.19092151,  0.38341252,  0.7664427 ],
    [ 0.09495377,  0.18996269,  0.38165151,  0.7664427,   1.53713523]
])

接下来,考虑一个具有多个约束的最小化问题(即 [5] 中的示例 16.4)。目标函数是

>>> fun = lambda x: (x[0] - 1)**2 + (x[1] - 2.5)**2

有三个约束定义为

>>> cons = ({'type': 'ineq', 'fun': lambda x:  x[0] - 2 * x[1] + 2},
...         {'type': 'ineq', 'fun': lambda x: -x[0] - 2 * x[1] + 6},
...         {'type': 'ineq', 'fun': lambda x: -x[0] + 2 * x[1] + 2})

并且变量必须为正,因此有以下边界

>>> bnds = ((0, None), (0, None))

优化问题使用 SLSQP 方法解决,如下所示

>>> res = minimize(fun, (2, 0), method='SLSQP', bounds=bnds,
...                constraints=cons)

它应该收敛于理论解 (1.4 ,1.7)。