本文简要介绍 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。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。