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可呼叫物件(callable)

想要最小化的函數。簽名必須是

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

其中 x 的每個元素都是有限實數,而 args 是一個元組,可以包含任意數量的與 x 可廣播的陣列。

f 必須是逐元素函數:對於所有索引 i,每個元素 f(x)[i] 必須等於 f(x[i])。它不得改變陣列 xargs 中的陣列。

find_minimum 尋找一個陣列 x,使得 f(x) 是一個局部最小值陣列。

init3 元組的浮點數類陣列

標準純量極小化括號的橫座標。如果陣列 x1、 x2、 x3 = init 滿足 x1 < x2 < x3func(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浮點數陣列

fx 處評估的值。

nfev整數陣列

為了找到根,f 被評估的橫座標數量。這與 f呼叫的次數不同,因為函數可能在單次呼叫中在多個點進行評估。

nit整數陣列

已執行的演算法迭代次數。

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.])