scipy.optimize.elementwise.

find_minimum#

scipy.optimize.elementwise.find_minimum(f, init, /, *, args=(), tolerances=None, maxiter=100, callback=None)[源代码]#

查找单峰实值实变量函数的最小值。

对于 f 的输出的每个元素,find_minimum 寻找最小化该元素的标量最小值。 此函数目前使用 Chandrupatla 的括号最小化算法 [1],因此需要参数 init 提供一个三点最小化括号:x1 < x2 < x3,使得 func(x1) >= func(x2) <= func(x3),其中一个不等式是严格的。

如果函数在括号内是连续的,则在提供了有效的括号后,find_minimum 保证收敛到满足所提供的 tolerances 的局部最小值。

initargs 包含(可广播的)数组时,此函数按元素方式工作。

参数:
f可调用对象

需要找到最小值的函数。签名必须是

f(x: array, *args) -> array

其中 x 的每个元素都是有限实数,args 是一个元组,其中可能包含任意数量的可与 x 广播的数组。

f 必须是逐元素的函数:对于所有索引 i,每个元素 f(x)[i] 必须等于 f(x[i])。它不得更改数组 xargs 中的数组。

find_minimum 寻找一个数组 x,使得 f(x) 是一个局部最小值数组。

init浮点数组的 3 元组

标准标量最小化括号的横坐标。如果数组 x1, x2, x3 = init 满足 x1 < x2 < x3func(x1) >= func(x2) <= func(x3),则括号有效,其中一个不等式是严格的。数组必须彼此之间和 args 的数组之间可广播。

argsarray_like 的元组,可选

要传递给 f 的其他位置数组参数。数组必须彼此之间和 init 的数组之间可广播。如果需要根的可调用对象需要不能与 x 广播的参数,请使用 f 包裹该可调用对象,使得 f 仅接受 x 和可广播的 *args

tolerances浮点数字典,可选

关于根和函数值的绝对和相对容差。字典的有效键是

  • xatol - 根的绝对容差

  • xrtol - 根的相对容差

  • fatol - 函数值的绝对容差

  • frtol - 函数值的相对容差

有关默认值和显式终止条件,请参阅“注释”。

maxiterint,默认值:100

算法要执行的最大迭代次数。

callback可调用对象,可选

一个可选的用户提供的函数,在第一次迭代之前和每次迭代之后调用。调用为 callback(res),其中 res 是一个 _RichResult,类似于 find_minimum 返回的对象(但包含所有变量的当前迭代值)。如果 callback 引发 StopIteration,则算法将立即终止,并且 find_root 将返回结果。callback 不得更改 res 或其属性。

返回值:
res_RichResult

一个类似于 scipy.optimize.OptimizeResult 实例的对象,具有以下属性。这些描述的编写方式就好像这些值将是标量;但是,如果 f 返回一个数组,则输出将是相同形状的数组。

successbool 数组

True 表示算法成功终止(状态 0);否则为 False

statusint 数组

表示算法退出状态的整数。

  • 0:算法收敛到指定的容差。

  • -1:算法遇到无效的括号。

  • -2:达到最大迭代次数。

  • -3:遇到非有限值。

  • -4:迭代被 callback 终止。

  • 1:算法正常进行(仅在 callback 中)。

x浮点数数组

如果算法成功终止,则为函数的最小值。

f_x浮点数数组

x 处评估的 f 的值。

nfevint 数组

为了找到根,评估 f 的横坐标数。这与 f调用的次数不同,因为该函数可能在一次调用中在多个点进行评估。

nitint 数组

执行的算法迭代次数。

bracket浮点数数组的元组

最终的三点括号。

f_bracket浮点数数组的元组

在括号点评估的 f 的值。

另请参阅

bracket_minimum

注释

基于 Chandrupatla 的原始论文 [1] 实现。

如果 xl < xm < xr 是包围区间的点,并且 fl >= fm <= fr(其中一个不等式是严格的)是在这些点上评估的 f 的值,则当满足以下条件时,算法被认为已收敛:

  • xr - xl <= abs(xm)*xrtol + xatol

  • (fl - 2*fm + fr)/2 <= abs(fm)*frtol + fatol.

请注意,第一个条件与 [1] 中描述的终止条件不同。

xrtol 的默认值是相应 dtype 的精度的平方根,而 xatol = fatol = frtol 是相应 dtype 的最小正规数。

参考文献

[1] (1,2,3)

Chandrupatla, Tirupathi R. (1998). “一种用于无导数最小化的有效二次拟合分段算法”。《计算机在应用力学和工程中的方法》,152 (1-2), 211-217。 https://doi.org/10.1016/S0045-7825(97)00190-4

示例

假设我们希望最小化以下函数。

>>> def f(x, c=1):
...     return (x - c)**2 + 2

首先,我们必须找到一个有效的包围区间。该函数是单峰的,因此 bracket_minium 可以很容易地找到一个包围区间。

>>> from scipy.optimize import elementwise
>>> res_bracket = elementwise.bracket_minimum(f, 0)
>>> res_bracket.success
True
>>> res_bracket.bracket
(0.0, 0.5, 1.5)

实际上,包围区间的点是有序的,并且中间包围点处的函数值小于周围的点。

>>> xl, xm, xr = res_bracket.bracket
>>> fl, fm, fr = res_bracket.f_bracket
>>> (xl < xm < xr) and (fl > fm <= fr)
True

一旦我们有了一个有效的包围区间,就可以使用 find_minimum 来提供最小化值的估计。

>>> res_minimum = elementwise.find_minimum(f, res_bracket.bracket)
>>> res_minimum.x
1.0000000149011612

函数值在包围区间内仅变化几个 ULP,因此仅通过评估函数本身(即我们需要其导数才能做得更好)无法更精确地确定最小化值。

>>> import numpy as np
>>> fl, fm, fr = res_minimum.f_bracket
>>> (fl - fm) / np.spacing(fm), (fr - fm) / np.spacing(fm)
(0.0, 2.0)

因此,函数的精确最小值由以下给出

>>> res_minimum.f_x
2.0

bracket_minimumfind_minimum 接受大多数参数的数组。 例如,要同时查找参数 c 的几个值的最小化值和最小值

>>> c = np.asarray([1, 1.5, 2])
>>> res_bracket = elementwise.bracket_minimum(f, 0, args=(c,))
>>> res_bracket.bracket
(array([0. , 0.5, 0.5]), array([0.5, 1.5, 1.5]), array([1.5, 2.5, 2.5]))
>>> res_minimum = elementwise.find_minimum(f, res_bracket.bracket, args=(c,))
>>> res_minimum.x
array([1.00000001, 1.5       , 2.        ])
>>> res_minimum.f_x
array([2., 2., 2.])