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 的局部最小值。当 init 和 args 包含(可广播的)数组时,此函数按元素方式工作。
- 参数:
- f可调用对象
需要找到最小值的函数。签名必须是
f(x: array, *args) -> array
其中
x
的每个元素都是有限实数,args
是一个元组,其中可能包含任意数量的可与x
广播的数组。f 必须是逐元素的函数:对于所有索引
i
,每个元素f(x)[i]
必须等于f(x[i])
。它不得更改数组x
或args
中的数组。find_minimum
寻找一个数组x
,使得f(x)
是一个局部最小值数组。- init浮点数组的 3 元组
标准标量最小化括号的横坐标。如果数组
x1, x2, x3 = init
满足x1 < x2 < x3
和func(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 的值。
另请参阅
注释
基于 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_minimum
和find_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.])