当前位置: 首页>>代码示例 >>用法及示例精选 >>正文


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