brute#
- scipy.optimize.brute(func, ranges, args=(), Ns=20, full_output=0, finish=<function fmin>, disp=False, workers=1)[source]#
透過暴力搜尋在給定範圍內最小化函數。
使用「暴力搜尋」方法,即計算多維網格中每個點的函數值,以找到函數的全局最小值。
函數在範圍內的所有位置進行評估,資料類型與函數的第一次呼叫相同,由
vectorize
NumPy 函數強制執行。當full_output=True
時傳回的函數評估值和類型,還會受到finish
參數的影響(請參閱「註解」)。暴力搜尋方法效率低下,因為網格點的數量呈指數級增長 - 要評估的網格點數量為
Ns ** len(x)
。因此,即使使用粗略的網格間距,即使是中等規模的問題也可能需要很長時間才能運行,和/或遇到記憶體限制。- 參數:
- funccallable
要最小化的目標函數。必須採用
f(x, *args)
的形式,其中x
是 1-D 陣列形式的引數,而args
是一個元組,包含完全指定函數所需的任何其他固定參數。- rangestuple
ranges 元組的每個組件都必須是「slice object」或
(low, high)
形式的範圍元組。程式使用這些來建立網格點,目標函數將在這些點上計算。有關更多詳細資訊,請參閱 Note 2。- argstuple, optional
完全指定函數所需的任何其他固定參數。
- Nsint, optional
沿軸的網格點數量,如果未另行指定。請參閱 Note2。
- full_outputbool, optional
如果為 True,則傳回評估網格和目標函數在其上的值。
- finishcallable, optional
一個最佳化函數,使用暴力搜尋最小化的結果作為初始猜測來呼叫。finish 應將 func 和初始猜測作為位置引數,並將 args 作為關鍵字引數。它還可以額外將 full_output 和/或 disp 作為關鍵字引數。如果沒有要使用的「polish」函數,請使用 None。有關更多詳細資訊,請參閱「註解」。
- dispbool, optional
設定為 True 以列印來自 finish callable 的收斂訊息。
- workersint or map-like callable, optional
如果 workers 是 int,則網格將細分為 workers 個部分並平行評估(使用
multiprocessing.Pool
)。提供 -1 以使用 Process 可用的所有核心。或者,提供類似 map 的 callable,例如 multiprocessing.Pool.map 以平行評估網格。此評估以workers(func, iterable)
形式執行。要求 func 可 pickle 化。在版本 1.3.0 中新增。
- 傳回值:
- x0ndarray
一個 1-D 陣列,包含目標函數達到最小值的點的座標。(請參閱 Note 1,了解傳回哪個點。)
- fvalfloat
點 x0 的函數值。(當 full_output 為 True 時傳回。)
- gridtuple
評估網格的表示。它的長度與 x0 相同。(當 full_output 為 True 時傳回。)
- Joutndarray
評估網格中每個點的函數值,即
Jout = func(*grid)
。(當 full_output 為 True 時傳回。)
註解
註解 1:程式會找到目標函數值最低的網格點。如果 finish 為 None,則傳回該點。當全局最小值出現在網格邊界內(或離邊界不遠處),並且網格足夠精細時,該點將位於全局最小值的附近。
但是,使用者通常會使用其他最佳化程式來「polish」網格點值,即在 brute's 最佳網格點附近尋找更精確的(局部)最小值。
brute
函數的 finish 選項提供了一種方便的方法來執行此操作。任何使用的 polish 程式都必須將 brute's 的輸出作為其初始猜測作為位置引數,並將 brute's 的輸入值作為 args 的關鍵字引數,否則會引發錯誤。它還可以額外將 full_output 和/或 disp 作為關鍵字引數。brute
假設 finish 函數傳回OptimizeResult
物件或(xmin, Jmin, ... , statuscode)
形式的元組,其中xmin
是引數的最小值,Jmin
是目標函數的最小值,“…”可能是其他一些傳回值(brute
不使用),而statuscode
是 finish 程式的狀態代碼。請注意,當 finish 不是 None 時,傳回的值是 finish 程式的值,而不是 網格點的值。因此,雖然
brute
將其搜尋限制在輸入網格點,但 finish 程式的結果通常不會與任何網格點重合,並且可能會落在網格邊界之外。因此,如果只需要在提供的網格點上找到最小值,請務必傳入finish=None
。註解 2:網格點是
numpy.mgrid
物件。對於brute
,ranges 和 Ns 輸入具有以下效果。ranges 元組的每個組件可以是 slice 物件或提供值範圍的二元組,例如 (0, 5)。如果組件是 slice 物件,brute
會直接使用它。如果組件是二元組範圍,brute
會在內部將其轉換為 slice 物件,該物件從其低值到高值(含)內插 Ns 個點。範例
我們說明如何使用
brute
來尋找雙變數函數的全局最小值,該函數表示為正定二次函數和兩個深「高斯形」坑的總和。具體來說,將目標函數 f 定義為三個其他函數的總和,f = f1 + f2 + f3
。我們假設這些函數中的每一個都具有簽名(z, *params)
,其中z = (x, y)
,並且params
和函數的定義如下。>>> import numpy as np >>> params = (2, 3, 7, 8, 9, 10, 44, -1, 2, 26, 1, -2, 0.5) >>> def f1(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (a * x**2 + b * x * y + c * y**2 + d*x + e*y + f)
>>> def f2(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (-g*np.exp(-((x-h)**2 + (y-i)**2) / scale))
>>> def f3(z, *params): ... x, y = z ... a, b, c, d, e, f, g, h, i, j, k, l, scale = params ... return (-j*np.exp(-((x-k)**2 + (y-l)**2) / scale))
>>> def f(z, *params): ... return f1(z, *params) + f2(z, *params) + f3(z, *params)
因此,目標函數可能在組成它的三個函數中每一個函數的最小值附近具有局部最小值。若要使用
fmin
來 polish 其網格點結果,我們可以繼續如下操作>>> rranges = (slice(-4, 4, 0.25), slice(-4, 4, 0.25)) >>> from scipy import optimize >>> resbrute = optimize.brute(f, rranges, args=params, full_output=True, ... finish=optimize.fmin) >>> resbrute[0] # global minimum array([-1.05665192, 1.80834843]) >>> resbrute[1] # function value at global minimum -3.4085818767
請注意,如果 finish 已設定為 None,我們將獲得網格點 [-1.0 1.75],其中四捨五入的函數值為 -2.892。