當前位置: 首頁>>代碼示例 >>用法及示例精選 >>正文


Python SciPy optimize.differential_evolution用法及代碼示例


本文簡要介紹 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

變量的界限。有兩種方法可以指定邊界:

  1. Instance of Bounds class.

  2. (min, max) pairs for each element in x, 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 是一個關鍵字參數,包含帶有屬性 xfun OptimizeResult 、迄今為止找到的最佳解決方案和目標函數。請注意,參數的名稱必須是 intermediate_result 以便回調傳遞 OptimizeResult

回調還支持如下簽名:

callback(x, convergence: float=val)

val表示群體收斂的分數值。當 val 大於 1.0 時,函數停止。

內省用於確定調用哪個簽名。

如果回調引發 StopIteration 或返回 True ,則全局最小化將停止;仍然進行任何拋光。

polish 布爾型,可選

如果為真(默認),則scipy.optimize.minimizeL-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] 概述了其他可用的策略。

其中整數\(r_0, r_1, r_2, r_3, r_4\) 從區間 [0, NP) 中隨機選擇NP是總人口規模和具有索引的原始候選者i。用戶可以通過提供可調用的來完全自定義試驗候選的生成strategy.

為了提高找到全局最小值的機會,請使用更高的 popsize 值,以及更高的突變和(抖動),但重組值更低。這具有擴大搜索半徑的效果,但會減慢收斂速度。

默認情況下,最佳解向量在單次迭代內連續更新 (updating='immediate')。這是對原始差分進化算法的修改[4],它可以導致更快的收斂,因為試驗向量可以立即受益於改進的解決方案。要使用原始的 Storn 和 Price 行為,每次迭代更新一次最佳解決方案,請設置 updating='deferred''deferred' 方法與並行化和矢量化兼容('workers''vectorized' 關鍵字)。這些可以通過更有效地使用計算機資源來提高最小化速度。 'workers' 將計算分布在多個處理器上。默認情況下使用 Python multiprocessing 模塊,但其他方法也是可能的,例如集群上使用的消息傳遞接口 (MPI) [6] [7]。這些方法(創建新進程等)的開銷可能很大,這意味著計算速度不一定會隨著使用的處理器數量而變化。並行化最適合計算成本高昂的目標函數。如果目標函數成本較低,則 'vectorized' 可以通過每次迭代僅調用目標函數一次來提供幫助,而不是對所有群體成員多次調用;解釋器的開銷減少了。

參考

[1]

差異進化,維基百科,http://en.wikipedia.org/wiki/Differential_evolution

[2]

Storn, R 和 Price, K,微分進化 - 一種簡單而有效的連續空間全局優化啟發式算法,全局優化雜誌,1997, 11, 341 - 359。

[3] (1,2)

Qiang, J., Mitchell, C.,全局優化的統一差分進化算法,2014,https://www.osti.gov/servlets/purl/1163659

[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

相關用法


注:本文由純淨天空篩選整理自scipy.org大神的英文原創作品 scipy.optimize.differential_evolution。非經特殊聲明,原始代碼版權歸原作者所有,本譯文未經允許或授權,請勿轉載或複製。