find_minimum#
- scipy.optimize.elementwise.find_minimum(f, init, /, *, args=(), tolerances=None, maxiter=100, callback=None)[source]#
查找实变量的单峰实值函数的最小值。
对于 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 的数组可广播。- args类数组元组,可选
要传递给 f 的附加位置数组参数。数组必须彼此可广播,并与 init 的数组可广播。如果需要求根的可调用对象需要与 x 不可广播的参数,则将该可调用对象用 f 包装,使得 f 仅接受 x 和可广播的
*args
。- tolerances浮点数字典,可选
根和函数值的绝对和相对容差。字典的有效键为
xatol
- 根的绝对容差xrtol
- 根的相对容差fatol
- 函数值的绝对容差frtol
- 函数值的相对容差
有关默认值和明确终止条件,请参阅“备注”。
- maxiter整型,默认值: 100
算法执行的最大迭代次数。
- callback可调用对象,可选
一个可选的用户提供函数,在第一次迭代之前和每次迭代之后调用。调用形式为
callback(res)
,其中res
是一个_RichResult
对象,类似于find_minimum
返回的结果(但包含当前迭代的所有变量值)。如果 callback 引发StopIteration
,算法将立即终止,并且find_root
将返回一个结果。callback 不得修改 res 或其属性。
- 返回:
- res_RichResult
一个类似于
scipy.optimize.OptimizeResult
实例的对象,具有以下属性。描述假定值为标量;但是,如果 f 返回一个数组,则输出将是相同形状的数组。- success布尔数组
算法成功终止时(状态
0
)为True
;否则为False
。- status整型数组
表示算法退出状态的整数。
0
: 算法收敛到指定的容差。-1
: 算法遇到无效区间。-2
: 达到最大迭代次数。-3
: 遇到非有限值。-4
: 迭代被 callback 终止。1
: 算法正常进行(仅在 callback 中)。
- x浮点数组
函数的最小值点,如果算法成功终止。
- f_x浮点数组
在 x 处计算的 f 值。
- nfev整型数组
为找到根而评估 f 的横坐标数量。这与 f 被调用的次数不同,因为函数可能在单次调用中在多个点进行评估。
- nit整型数组
算法执行的迭代次数。
- bracket浮点数组元组
最终的三点区间。
- f_bracket浮点数组元组
在区间点处计算的 f 值。
另请参阅
备注
基于 Chandrupatla 的原始论文 [1] 实现。
如果
xl < xm < xr
是区间的点,并且fl >= fm <= fr
(其中一个不等式是严格的) 是在这些点评估的 f 值,那么当满足以下条件时,算法被认为已收敛:abs(xr - xm)/2 <= abs(xm)*xrtol + xatol
或(fl - 2*fm + fr)/2 <= abs(fm)*frtol + fatol
.
xrtol 的默认值是相应数据类型精度的平方根,而
xatol = fatol = frtol
是相应数据类型的最小正规数。参考文献
[1] (1,2)Chandrupatla, Tirupathi R. (1998). “An efficient quadratic fit-sectioning algorithm for minimization without derivatives”(用于无导数最小化的有效二次拟合-分段算法)。Computer Methods in Applied Mechanics and Engineering, 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
函数值在区间内仅变化几个 ULPs,因此仅通过评估函数无法更精确地确定最小值点(即,我们需要其导数才能做得更好)。
>>> 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.])