本文簡要介紹 python 語言中 scipy.optimize.differential_evolution
的用法。
用法:
scipy.optimize.differential_evolution(func, bounds, args=(), strategy='best1bin', maxiter=1000, popsize=15, tol=0.01, mutation=(0.5, 1), recombination=0.7, seed=None, callback=None, disp=False, polish=True, init='latinhypercube', atol=0, updating='immediate', workers=1, constraints=(), x0=None, *, integrality=None, vectorized=False)#
查找多元函數的全局最小值。
差分進化方法[1]本質上是隨機的。它不使用梯度方法來尋找最小值,並且可以搜索大麵積的候選空間,但通常需要比傳統的基於梯度的技術更多數量的函數評估。
該算法源自 Storn 和 Price [2]。
- func: 可調用的
要最小化的目標函數。必須采用
f(x, *args)
的形式,其中x
是一維數組形式的參數,而args
是完全指定函數所需的任何其他固定參數的元組。參數的數量 N 等於len(x)
。- bounds: 序列或
Bounds
變量的界限。有兩種方法可以指定邊界:
Instance of
Bounds
class.(min, max)
pairs for each element inx
, defining the finite lower and upper bounds for the optimizing argument of func.
邊界總數用於確定參數的數量 N。如果存在其邊界相等的參數,則自由參數的總數為
N - N_equal
。- args: 元組,可選
完全指定目標函數所需的任何其他固定參數。
- strategy: {str,可調用},可選
要使用的差異進化策略。應該是以下之一:
‘best1bin’
‘best1exp’
‘rand1bin’
‘rand1exp’
‘rand2bin’
‘rand2exp’
‘randtobest1bin’
‘randtobest1exp’
‘currenttobest1bin’
‘currenttobest1exp’
‘best2exp’
‘best2bin’
默認為‘best1bin’。 “注釋”中概述了可能實施的策略。或者,可以通過提供構建試驗向量的可調用函數來定製差分進化策略。可調用的必須具有以下形式
strategy(candidate: int, population: np.ndarray, rng=None)
,其中candidate
是一個整數,指定正在進化的種群的哪個條目,population
是一個形狀數組(S, N)
包含所有人口成員(其中 S 是總人口規模),並且rng
是求解器中使用的隨機數生成器。candidate
將在範圍內[0, S)
.strategy
必須返回具有形狀的試驗向量(N,)。該試驗向量的適合度與population[candidate]
.- maxiter: 整數,可選
整個種群進化的最大世代數。函數評估的最大數量(沒有拋光)是:
(maxiter + 1) * popsize * (N - N_equal)
- popsize: 整數,可選
用於設置總人口規模的乘數。人口有
popsize * (N - N_equal)
個人。如果通過在裏麵關鍵詞。使用時init='sobol'
人口規模計算為 2 的下一個冪popsize * (N - N_equal)
.- tol: 浮點數,可選
收斂的相對容差,求解停止時
np.std(pop) <= atol + tol * np.abs(np.mean(population_energies))
, 哪裏和環礁和tol分別是絕對容差和相對容差。- mutation: 浮點數或元組(浮點數,浮點數),可選
突變常數。在文獻中,這也稱為微分權重,用 F 表示。如果指定為浮點數,它應該在 [0, 2] 範圍內。如果指定為元組
(min, max)
,則使用抖動。抖動會在一代一代的基礎上隨機改變突變常數。該代的突變常數取自U[min, max)
。抖動有助於顯著加快收斂速度。增加變異常數會增加搜索半徑,但會減慢收斂速度。- recombination: 浮點數,可選
重組常數應在 [0, 1] 範圍內。在文獻中,這也稱為交叉概率,用 CR 表示。增加這個值可以讓更多的突變體進入下一代,但有種群穩定的風險。
- seed: {無,int,
numpy.random.Generator
,numpy.random.RandomState
},可選 如果種子是無(或np.random), 這
numpy.random.RandomState
使用單例。如果種子是一個 int,一個新的RandomState
使用實例,播種種子.如果種子已經是一個Generator
或者RandomState
實例然後使用該實例。指定種子用於可重複的最小化。- disp: 布爾型,可選
在每次迭代時打印評估的函數。
- callback: 可調用的,可選的
每次迭代後調用的可調用對象。有簽名:
callback(intermediate_result: OptimizeResult)
其中
intermediate_result
是一個關鍵字參數,包含帶有屬性x
和fun
的OptimizeResult
、迄今為止找到的最佳解決方案和目標函數。請注意,參數的名稱必須是intermediate_result
以便回調傳遞OptimizeResult
。回調還支持如下簽名:
callback(x, convergence: float=val)
val
表示群體收斂的分數值。當val
大於1.0
時,函數停止。內省用於確定調用哪個簽名。
如果回調引發
StopIteration
或返回True
,則全局最小化將停止;仍然進行任何拋光。- polish: 布爾型,可選
如果為真(默認),則scipy.optimize.minimize與L-BFGS-B方法用於最後打磨最佳種群成員,可以稍微提高最小化。如果正在研究一個有約束的問題,那麽trust-constr而是使用方法。對於具有許多約束的大型問題,由於雅可比計算,拋光可能需要很長時間。
- init: str 或類似數組,可選
指定執行哪種類型的人口初始化。應該是以下之一:
‘latinhypercube’
‘sobol’
‘halton’
‘random’
array specifying the initial population. The array should have shape
(S, N)
, where S is the total population size and N is the number of parameters. init is clipped to bounds before use.
默認值為‘latinhypercube’。拉丁超立方體采樣試圖最大化可用參數空間的覆蓋範圍。
‘sobol’ 和 ‘halton’ 是更好的選擇,可以最大化更多的參數空間。 ‘sobol’ 將強製執行初始種群大小,該大小計算為
popsize * (N - N_equal)
之後的下一個 2 的冪。 ‘halton’沒有任何要求,但效率稍低。有關更多詳細信息,請參閱scipy.stats.qmc
。‘random’ 隨機初始化總體 - 這具有可能發生聚類的缺點,從而防止整個參數空間被覆蓋。例如,可以使用數組來指定總體,在已知解存在的位置創建一組緊密的初始猜測,從而減少收斂時間。
- atol: 浮點數,可選
收斂的絕對容差,當求解停止時
np.std(pop) <= atol + tol * np.abs(np.mean(population_energies))
, 哪裏和環礁和tol分別是絕對容差和相對容差。- updating: {‘immediate’, ‘deferred’},可選
如果
'immediate'
,最佳解向量在單代內不斷更新[4].這可以導致更快的收斂,因為試驗向量可以利用最佳解決方案的持續改進。和'deferred'
,最佳解向量每代更新一次。僅有的'deferred'
與並行化或矢量化兼容,並且工作人員和矢量化關鍵字可以覆蓋此選項。- workers: int 或 map-like 可調用,可選
如果工作人員是一個int,人口被細分為工作人員部分和並行評估(使用
multiprocessing.Pool
)。提供 -1 以使用所有可用的 CPU 內核。或者提供一個 map-like 可調用對象,例如多處理.Pool.map用於並行評估總體。本次評價為workers(func, iterable)
.此選項將覆蓋更新關鍵字到updating='deferred'
如果workers != 1
.此選項覆蓋矢量化關鍵字 ifworkers != 1
.要求函數可以 pickle 。- constraints: {NonLinearConstraint, LinearConstraint, Bounds}
求解器上的約束,超出了界限千瓦時。使用 Lampinen 的方法[5].
- x0: 無或類似數組,可選
提供最小化的初始猜測。初始化種群後,此向量將替換第一個(最佳)成員。即使完成此替換在裏麵給定一個初始種群。
x0.shape == (N,)
.- integrality: 一維數組,可選
對於每個決策變量,一個布爾值指示決策變量是否被限製為整數值。數組廣播到
(N,)
.如果任何決策變量被約束為整數,它們在拋光過程中不會改變。僅使用位於下限和上限之間的整數值。如果邊界之間沒有整數值,則ValueError被拋出- vectorized: 布爾型,可選
如果
vectorized is True
,函數被發送一個x數組與x.shape == (N, S)
,並且預計會返回一個形狀數組(S,)
,其中S是要計算的解向量的數量。如果應用了約束,則用於構造一個約束對象應該接受一個x數組與x.shape == (N, S)
, 並返回一個形狀數組(M, S)
,其中M是約束組件的數量。此選項是由提供的並行化的替代方案工作人員,並且可以通過減少多個函數調用的解釋器開銷來幫助優化速度。如果出現以下情況,則忽略此關鍵字workers != 1
.此選項將覆蓋更新關鍵字到updating='deferred'
.有關何時使用的進一步討論,請參閱注釋部分'vectorized'
,以及何時使用'workers'
.
- res: OptimizeResult
優化結果表示為
OptimizeResult
目的。重要的屬性是:x
解決方案數組,success
指示優化器是否成功退出的布爾標誌,message
其中說明了終止的原因,population
總體中存在的解向量,以及population_energies
每個條目的目標函數值population
.看OptimizeResult
其他屬性的說明。如果拋光被采用,並且通過拋光獲得了較低的最小值,那麽OptimizeResult 也包含jac
屬性。如果最終解決方案不滿足應用的約束success
將會False.
參數 ::
返回 ::
注意:
差分進化是一種基於隨機群體的方法,可用於解決全局優化問題。每次通過群體時,算法都會通過與其他候選解決方案混合來改變每個候選解決方案,以創建試驗候選方案。有幾種創建試驗候選的策略[3],它們比其他問題更適合某些問題。 ‘best1bin’ 策略對於許多係統來說是一個很好的起點。在此策略中,隨機選擇群體中的兩名成員。它們的差異用於突變最好的成員(‘best1bin’中的‘best’), ,到目前為止:
然後構建試驗載體。從隨機選擇的第 i 個參數開始,試驗按順序填充(模數)
b'
或原來的候選人。是否使用的選擇b'
或使用二項分布(‘best1bin’ 中的‘bin’)製作原始候選 - 生成 [0, 1) 中的隨機數。如果這個數字小於重組常量,然後從加載參數b'
,否則從原始候選中加載。最後的參數總是從b'
。一旦建立了試驗候選者,就會評估其適應性。如果試驗比原來的候選更好,那麽它就會取代它。如果它也比最佳總體候選者更好,它也會取代它。Qiang 和 Mitchell (2014) [3] 概述了其他可用的策略。
其中整數
從區間 [0, NP) 中隨機選擇NP是總人口規模和具有索引的原始候選者i。用戶可以通過提供可調用的來完全自定義試驗候選的生成strategy
.為了提高找到全局最小值的機會,請使用更高的 popsize 值,以及更高的突變和(抖動),但重組值更低。這具有擴大搜索半徑的效果,但會減慢收斂速度。
默認情況下,最佳解向量在單次迭代內連續更新 (
updating='immediate'
)。這是對原始差分進化算法的修改[4],它可以導致更快的收斂,因為試驗向量可以立即受益於改進的解決方案。要使用原始的 Storn 和 Price 行為,每次迭代更新一次最佳解決方案,請設置updating='deferred'
。'deferred'
方法與並行化和矢量化兼容('workers'
和'vectorized'
關鍵字)。這些可以通過更有效地使用計算機資源來提高最小化速度。'workers'
將計算分布在多個處理器上。默認情況下使用 Pythonmultiprocessing
模塊,但其他方法也是可能的,例如集群上使用的消息傳遞接口 (MPI) [6] [7]。這些方法(創建新進程等)的開銷可能很大,這意味著計算速度不一定會隨著使用的處理器數量而變化。並行化最適合計算成本高昂的目標函數。如果目標函數成本較低,則'vectorized'
可以通過每次迭代僅調用目標函數一次來提供幫助,而不是對所有群體成員多次調用;解釋器的開銷減少了。參考:
[1]差異進化,維基百科,http://en.wikipedia.org/wiki/Differential_evolution
[2]Storn, R 和 Price, K,微分進化 - 一種簡單而有效的連續空間全局優化啟發式算法,全局優化雜誌,1997, 11, 341 - 359。
[4] (1,2)Wormington, M.、Panaccione, C.、Matney, K. M.、Bowen, D. K.,-使用遺傳算法從 X-ray 散射數據中表征結構,Phil。反式。 R. Soc。倫敦。 A, 1999, 357, 2827-2848
[5]Lampinen, J.,差分進化算法的約束處理方法。 2002 年進化計算大會論文集。 CEC'02(貨號 02TH8600)。卷。 2. IEEE,2002。
例子:
讓我們考慮最小化 Rosenbrock 函數的問題。此函數在
scipy.optimize
中的rosen
中實現。>>> import numpy as np >>> from scipy.optimize import rosen, differential_evolution >>> bounds = [(0,2), (0, 2), (0, 2), (0, 2), (0, 2)] >>> result = differential_evolution(rosen, bounds) >>> result.x, result.fun (array([1., 1., 1., 1., 1.]), 1.9216496320061384e-19)
現在重複,但要並行化。
>>> result = differential_evolution(rosen, bounds, updating='deferred', ... workers=2) >>> result.x, result.fun (array([1., 1., 1., 1., 1.]), 1.9216496320061384e-19)
讓我們進行約束最小化。
>>> from scipy.optimize import LinearConstraint, Bounds
我們添加了
x[0]
和x[1]
之和必須小於或等於 1.9 的約束。這是一個線性約束,可以寫為A @ x <= 1.9
,其中A = array([[1, 1]])
。這可以編碼為LinearConstraint
實例:>>> lc = LinearConstraint([[1, 1]], -np.inf, 1.9)
使用
Bounds
對象指定限製。>>> bounds = Bounds([0., 0.], [2., 2.]) >>> result = differential_evolution(rosen, bounds, constraints=lc, ... seed=1) >>> result.x, result.fun (array([0.96632622, 0.93367155]), 0.0011352416852625719)
接下來求 Ackley 函數的最小值 (https://en.wikipedia.org/wiki/Test_functions_for_optimization)。
>>> def ackley(x): ... arg1 = -0.2 * np.sqrt(0.5 * (x[0] ** 2 + x[1] ** 2)) ... arg2 = 0.5 * (np.cos(2. * np.pi * x[0]) + np.cos(2. * np.pi * x[1])) ... return -20. * np.exp(arg1) - np.exp(arg2) + 20. + np.e >>> bounds = [(-5, 5), (-5, 5)] >>> result = differential_evolution(ackley, bounds, seed=1) >>> result.x, result.fun (array([0., 0.]), 4.440892098500626e-16)
Ackley 函數是以向量化的方式編寫的,因此可以使用
'vectorized'
關鍵字。請注意函數評估次數的減少。>>> result = differential_evolution( ... ackley, bounds, vectorized=True, updating='deferred', seed=1 ... ) >>> result.x, result.fun (array([0., 0.]), 4.440892098500626e-16)
以下自定義策略函數模仿‘best1bin’:
>>> def custom_strategy_fn(candidate, population, rng=None): ... parameter_count = population.shape(-1) ... mutation, recombination = 0.7, 0.9 ... trial = np.copy(population[candidate]) ... fill_point = rng.choice(parameter_count) ... ... pool = np.arange(len(population)) ... rng.shuffle(pool) ... ... # two unique random numbers that aren't the same, and ... # aren't equal to candidate. ... idxs = [] ... while len(idxs) < 2 and len(pool) > 0: ... idx = pool[0] ... pool = pool[1:] ... if idx != candidate: ... idxs.append(idx) ... ... r0, r1 = idxs[:2] ... ... bprime = (population[0] + mutation * ... (population[r0] - population[r1])) ... ... crossovers = rng.uniform(size=parameter_count) ... crossovers = crossovers < recombination ... crossovers[fill_point] = True ... trial = np.where(crossovers, bprime, trial) ... return trial
相關用法
- Python SciPy optimize.diagbroyden用法及代碼示例
- Python SciPy optimize.direct用法及代碼示例
- Python SciPy optimize.dual_annealing用法及代碼示例
- Python SciPy optimize.rosen_der用法及代碼示例
- Python SciPy optimize.line_search用法及代碼示例
- Python SciPy optimize.rosen用法及代碼示例
- Python SciPy optimize.shgo用法及代碼示例
- Python SciPy optimize.minimize_scalar用法及代碼示例
- Python SciPy optimize.root用法及代碼示例
- Python SciPy optimize.fmin用法及代碼示例
- Python SciPy optimize.NonlinearConstraint用法及代碼示例
- Python SciPy optimize.KrylovJacobian用法及代碼示例
- Python SciPy optimize.toms748用法及代碼示例
- Python SciPy optimize.linprog_verbose_callback用法及代碼示例
- Python SciPy optimize.bracket用法及代碼示例
- Python SciPy optimize.milp用法及代碼示例
- Python SciPy optimize.bisect用法及代碼示例
- Python SciPy optimize.isotonic_regression用法及代碼示例
- Python SciPy optimize.golden用法及代碼示例
- Python SciPy optimize.brute用法及代碼示例
- Python SciPy optimize.newton用法及代碼示例
- Python SciPy optimize.fsolve用法及代碼示例
- Python SciPy optimize.Bounds用法及代碼示例
- Python SciPy optimize.fixed_point用法及代碼示例
- Python SciPy optimize.rosen_hess用法及代碼示例
注:本文由純淨天空篩選整理自scipy.org大神的英文原創作品 scipy.optimize.differential_evolution。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。