Python scipy.optimize.differential_evolution 示例说明
查找多元函数的全局最小值。
差分进化本质上是随机的(不使用梯度方法)来寻找最小值,并且可以搜索大面积的候选空间,但通常需要比传统的基于梯度的技术更多的函数评估。
该算法归功于 Storn 和 Price [1] 。
- func: 可调用的
-
要最小化的目标函数。必须采用
f(x, *args)
的形式,其中x
是一维数组形式的参数,而args
是完全指定函数所需的任何其他固定参数的元组。参数的数量 N 等于len(x)
。 - bounds: 序列或 Bounds
-
变量的界限。有两种方法可以指定边界: 1. 实例scipy.optimize.Bounds类。 2.
(min, max)
中每个元素的对x
, 定义优化参数的有限下限和上限函数.边界的总数用于确定参数的数量,N。 - args: 元组,可选
-
完全指定目标函数所需的任何其他固定参数。
- strategy: str,可选
-
要使用的差异进化策略。应该是以下之一:
‘best1bin’
‘best1exp’
‘rand1exp’
‘randtobest1exp’
‘currenttobest1exp’
‘best2exp’
‘rand2exp’
‘randtobest1bin’
‘currenttobest1bin’
‘best2bin’
‘rand2bin’
‘rand1bin’
默认值为‘best1bin’。
- maxiter: int 可选
-
整个种群进化的最大世代数。函数评估的最大数量(没有抛光)是:
(maxiter + 1) * popsize * N
- popsize: int 可选
-
用于设置总人口规模的乘数。人口有
popsize * N
个人。如果通过在里面关键词。使用时init='sobol'
人口规模计算为 2 的下一个幂popsize * N
. - 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}, optional
如果种子是无(或np.random), 这numpy.random.RandomState使用单例。如果种子是一个int 一个新的
RandomState
使用实例,播种种子.如果种子已经是一个Generator
或者RandomState
实例然后使用该实例。指定种子用于可重复的最小化。 - disp: 布尔型,可选
-
在每次迭代时打印评估的函数。
- callback: 可调用,回调(xk,收敛=val), 可选的
-
跟踪最小化进度的函数。
xk
是迄今为止找到的最佳解决方案。val
表示总体收敛的分数值。什么时候val
大于 1 函数停止。如果回调返回True,然后停止最小化(仍然进行任何抛光)。 - polish: 布尔型,可选
-
如果为真(默认),则scipy.optimize.minimize与L-BFGS-B方法用于最后打磨最佳种群成员,可以稍微提高最小化。如果正在研究一个有约束的问题,那么trust-constr而是使用方法。
- init: str 或array-like,可选
-
指定执行哪种类型的人口初始化。应该是以下之一:
‘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’ and ‘halton’ 是更好的选择,可以最大化更多的参数空间。 ‘sobol’ 将强制执行初始种群大小,计算为
popsize * N
之后的 2 的下一个幂。 ‘halton’ 没有要求,但效率稍低。有关详细信息,请参阅 scipy.stats.qmc 。‘random’ 随机初始化总体 - 这具有可能发生聚类的缺点,从而防止整个参数空间被覆盖。例如,可以使用数组来指定总体,在已知解存在的位置创建一组紧密的初始猜测,从而减少收敛时间。
- atol: 浮点数,可选
-
收敛的绝对容差,当求解停止时
np.std(pop) <= atol + tol * np.abs(np.mean(population_energies))
, 哪里和环礁和tol分别是绝对容差和相对容差。 - updating: {‘immediate’, ‘deferred’},可选
-
如果
'immediate'
,最佳解向量在单代内不断更新scipy.optimize.differential_evolution.这可以导致更快的收敛,因为试验向量可以利用最佳解决方案的持续改进。和'deferred'
,最佳解向量每代更新一次。仅有的'deferred'
与并行化或矢量化兼容,并且工作人员和矢量化关键字可以over-ride这个选项。 - 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 边界}
-
求解器上的约束,超出了界限千瓦时。使用 Lampinen 的方法scipy.optimize.differential_evolution.
- x0: 无或array-like,可选
-
提供最小化的初始猜测。初始化种群后,此向量将替换第一个(最佳)成员。即使完成此替换在里面给定一个初始种群。
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
它说明了终止的原因。看OptimizeResult其他属性的说明。如果抛光被采用,并且通过抛光获得了较低的最小值,那么OptimizeResult 也包含jac
属性。如果最终解决方案不满足应用的约束success
将会False.
参数:
返回:
注意:
差分进化是一种基于随机种群的方法,对全局优化问题很有用。在每次通过总体时,该算法通过与其他候选解决方案混合来改变每个候选解决方案以创建一个试验候选解决方案。有几种策略[2] 可用于创建试验候选者,它们比其他问题更适合某些问题。 ‘best1bin’ 策略是许多系统的良好起点。在该策略中,随机选择两个总体成员。到目前为止,它们的差异用于变异最好的成员(‘best1bin’ 中的 ‘best’) :
然后构建试验载体。从随机选择的第 i 个参数开始,试验按顺序填充(模数)b'
或原来的候选人。是否使用的选择b'
或使用二项分布(‘best1bin’ 中的‘bin’)制作原始候选 - 生成 [0, 1) 中的随机数。如果这个数字小于重组常量,然后从加载参数b'
,否则从原始候选中加载。最后的参数总是从b'
.一旦建立了试验候选者,它的适合度就会被评估。如果试验比原来的候选人更好,那么它将取代它。如果它也比最好的整体候选人更好,它也会取代它。为了提高您找到全局最小值的机会,请使用更高的流行大小值,具有更高的突变和(抖动),但更低重组值。这具有扩大搜索半径的效果,但会减慢收敛速度。默认情况下,最佳解向量在单次迭代中不断更新(updating='immediate'
)。这是一个修改scipy.optimize.differential_evolution原始差分进化算法可以导致更快的收敛,因为试验向量可以立即从改进的解决方案中受益。要使用原始的 Storn 和 Price 行为,每次迭代更新一次最佳解决方案,设置updating='deferred'
.这'deferred'
方法兼容并行化和矢量化('workers'
和'vectorized'
关键词)。这些可以通过更有效地使用计算机资源来提高最小化速度。这'workers'
在多个处理器上分配计算。默认情况下,Pythonmultiprocessing使用模块,但也可以使用其他方法,例如集群上使用的消息传递接口 (MPI)scipy.optimize.differential_evolution scipy.optimize.differential_evolution.这些方法(创建新进程等)的开销可能很大,这意味着计算速度不一定与使用的处理器数量成正比。并行化最适合计算量大的目标函数。如果目标函数更便宜,那么'vectorized'
可以通过每次迭代只调用一次目标函数来提供帮助,而不是对所有总体成员多次调用;减少了解释器的开销。
参考:
-
Storn, R 和 Price, K,微分进化 - 一种简单而有效的连续空间全局优化启发式算法,全局优化杂志,1997, 11, 341 - 359。
-
http://www1.icsi.berkeley.edu/~storn/code.html
-
http://en.wikipedia.org/wiki/Differential_evolution
-
Wormington, M.、Panaccione, C.、Matney, K. M.、Bowen, D. K.,-使用遗传算法从 X-ray 散射数据中表征结构,Phil。反式。 R. Soc。伦敦。 A, 1999, 357, 2827-2848
-
Lampinen, J.,差分进化算法的约束处理方法。 2002 年进化计算大会论文集。 CEC'02(货号 02TH8600)。卷。 2. IEEE,2002。
-
https://mpi4py.readthedocs.io/en/stable/
-
https://schwimmbad.readthedocs.io/en/latest/
scipy.optimize.differential_evolution:
scipy.optimize.differential_evolution:
3:
4 (1,2):
scipy.optimize.differential_evolution:
scipy.optimize.differential_evolution:
scipy.optimize.differential_evolution:
例子:
让我们考虑最小化 Rosenbrock 函数的问题。此函数在 scipy.optimize 中的 rosen 中实现。
>>> 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 NonlinearConstraint, Bounds
>>> def constr_f(x):
... return np.array(x[0] + x[1])
>>>
>>> # the sum of x[0] and x[1] must be less than 1.9
>>> nlc = NonlinearConstraint(constr_f, -np.inf, 1.9)
>>> # specify limits using a `Bounds` object.
>>> bounds = Bounds([0., 0.], [2., 2.])
>>> result = differential_evolution(rosen, bounds, constraints=(nlc),
... seed=1)
>>> result.x, result.fun
(array([0.96633867, 0.93363577]), 0.0011361355854792312)
接下来求 Ackley 函数的最小值 (https://en.wikipedia.org/wiki/Test_functions_for_optimization)。
>>> from scipy.optimize import differential_evolution
>>> import numpy as np
>>> 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, result.nfev
(array([0., 0.]), 4.440892098500626e-16, 3063)
Ackley 函数是以向量化的方式编写的,因此可以使用'vectorized'
关键字。请注意函数评估次数的减少。
>>> result = differential_evolution(
... ackley, bounds, vectorized=True, updating='deferred', seed=1
... )
>>> result.x, result.fun, result.nfev
(array([0., 0.]), 4.440892098500626e-16, 190)