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可呼叫物件(callable)
想要最小化的函數。簽名必須是
f(x: array, *args) -> array
其中
x
的每個元素都是有限實數,而args
是一個元組,可以包含任意數量的與x
可廣播的陣列。f 必須是逐元素函數:對於所有索引
i
,每個元素f(x)[i]
必須等於f(x[i])
。它不得改變陣列x
或args
中的陣列。find_minimum
尋找一個陣列x
,使得f(x)
是一個局部最小值陣列。- init3 元組的浮點數類陣列
標準純量極小化括號的橫座標。如果陣列
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布林陣列
True
如果演算法成功終止(狀態0
);否則為False
。- status整數陣列
表示演算法結束狀態的整數。
0
: 演算法已收斂到指定的容差。-1
: 演算法遇到無效的括號。-2
: 已達到最大迭代次數。-3
: 遇到非有限值。-4
: 迭代被 callback 終止。1
: 演算法正常進行中(僅在 callback 中)。
- x浮點數陣列
如果演算法成功終止,則為函數的最小值。
- f_x浮點數陣列
f 在 x 處評估的值。
- nfev整數陣列
為了找到根,f 被評估的橫座標數量。這與 f 被呼叫的次數不同,因為函數可能在單次呼叫中在多個點進行評估。
- nit整數陣列
已執行的演算法迭代次數。
- 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.])