dual_annealing#
- scipy.optimize.dual_annealing(func, bounds, args=(), maxiter=1000, minimizer_kwargs=None, initial_temp=5230.0, restart_temp_ratio=2e-05, visit=2.62, accept=-5.0, maxfun=10000000.0, rng=None, no_local_search=False, callback=None, x0=None)[源代码]#
使用双退火法找到函数的全局最小值。
- 参数:
- func可调用对象
要最小化的目标函数。必须采用
f(x, *args)
的形式,其中x
是以 1 维数组形式表示的参数,args
是完全指定该函数所需的任何其他固定参数的元组。- bounds序列或
Bounds
变量的界限。有两种方法可以指定界限
Bounds
类的实例。对于 x 中的每个元素,都是
(min, max)
对的序列。
- argstuple, 可选
完全指定目标函数所需的任何其他固定参数。
- maxiterint, 可选
全局搜索迭代的最大次数。默认值为 1000。
- minimizer_kwargsdict, 可选
要传递给局部最小化器 (
minimize
) 的关键字参数。一个重要的选项可能是要使用的最小化器方法的method
。如果未提供任何关键字参数,则局部最小化器默认为“L-BFGS-B”并使用已提供的边界。如果指定了 minimizer_kwargs,则该字典必须包含控制局部最小化所需的所有参数。args 在此字典中被忽略,因为它会自动传递。bounds 不会自动传递给局部最小化器,因为该方法可能不支持它们。- initial_tempfloat, 可选
初始温度,使用较高的值有助于更广泛地搜索能量分布,从而使 dual_annealing 能够逃脱其陷入的局部最小值。默认值为 5230。范围为 (0.01, 5.e4]。
- restart_temp_ratiofloat, 可选
在退火过程中,温度会降低,当达到
initial_temp * restart_temp_ratio
时,会触发重新退火过程。该比率的默认值为 2e-5。范围为 (0, 1)。- visitfloat, 可选
访问分布的参数。默认值为 2.62。较高的值会使访问分布具有较重的尾部,这会使算法跳到更远的区域。值的范围为 (1, 3]。
- acceptfloat, 可选
接受分布的参数。它用于控制接受的概率。接受参数越低,接受的概率越小。默认值为 -5.0,范围为 (-1e4, -5]。
- maxfunint, 可选
目标函数调用次数的软限制。如果算法正在进行局部搜索,则此数字将被超出,算法将在局部搜索完成后立即停止。默认值为 1e7。
- rng{None, int,
numpy.random.Generator
}, 可选 如果通过关键字传递了 rng,则除
numpy.random.Generator
之外的类型会传递给numpy.random.default_rng
以实例化Generator
。如果 rng 已经是Generator
实例,则会使用提供的实例。指定 rng 以实现可重复的函数行为。如果此参数通过位置传递,或者通过关键字传递了 seed,则适用参数 seed 的旧行为
如果 seed 为 None (或
numpy.random
),则会使用numpy.random.RandomState
单例。如果 seed 是一个整数,则会使用一个新的
RandomState
实例,并使用 seed 进行播种。如果 seed 已经是
Generator
或RandomState
实例,则会使用该实例。
在 1.15.0 版本中进行了更改: 作为从使用
numpy.random.RandomState
到numpy.random.Generator
的 SPEC-007 过渡的一部分,此关键字从 seed 更改为 rng。在过渡期间,这两个关键字将继续工作,但一次只能指定一个。在过渡期之后,使用 seed 关键字的函数调用将发出警告。上述概述了 seed 和 rng 的行为,但新代码中应仅使用 rng 关键字。指定 rng 以进行可重复的最小化。生成的随机数仅影响访问分布函数和新坐标的生成。
- no_local_searchbool, 可选
如果将 no_local_search 设置为 True,将执行传统的广义模拟退火法,而不应用局部搜索策略。
- callback可调用对象, 可选
签名为
callback(x, f, context)
的回调函数,该函数将针对找到的所有最小值调用。x
和f
是最近找到的最小值的坐标和函数值,context
具有以下值之一0
: 在退火过程中检测到最小值。1
: 在局部搜索过程中检测到。2
: 在双退火过程中完成的检测。
如果回调实现返回 True,则算法将停止。
- x0ndarray, shape(n,), 可选
单个 N 维起点的坐标。
- 返回:
- resOptimizeResult
优化结果表示为一个
OptimizeResult
对象。重要的属性包括:x
解的数组,fun
解处的目标函数值,以及message
描述终止原因。有关其他属性的描述,请参阅OptimizeResult
。
说明
此函数实现了对偶退火优化算法。这种源于 [3] 的随机方法结合了 CSA (经典模拟退火) 和 FSA (快速模拟退火) 的泛化 [1] [2],并结合了在接受的位置应用局部搜索的策略 [4]。 在 [5] 中描述了此相同算法的另一种实现方式,并且在 [6] 中展示了基准测试。此方法引入了一种先进的方法来改进广义退火过程找到的解。该算法使用扭曲的柯西-洛伦兹访问分布,其形状由参数 \(q_{v}\) 控制。
\[g_{q_{v}}(\Delta x(t)) \propto \frac{ \ \left[T_{q_{v}}(t) \right]^{-\frac{D}{3-q_{v}}}}{ \ \left[{1+(q_{v}-1)\frac{(\Delta x(t))^{2}} { \ \left[T_{q_{v}}(t)\right]^{\frac{2}{3-q_{v}}}}}\right]^{ \ \frac{1}{q_{v}-1}+\frac{D-1}{2}}}\]其中 \(t\) 是人工时间。 此访问分布用于生成在人工温度 \(T_{q_{v}}(t)\) 下变量 \(x(t)\) 的试验跳跃距离 \(\Delta x(t)\)。
从起始点开始,在调用访问分布函数后,接受概率计算如下
\[p_{q_{a}} = \min{\{1,\left[1-(1-q_{a}) \beta \Delta E \right]^{ \ \frac{1}{1-q_{a}}}\}}\]其中 \(q_{a}\) 是接受参数。 对于 \(q_{a}<1\), 当以下情况时,接受概率被设为零。
\[[1-(1-q_{a}) \beta \Delta E] < 0\]人工温度 \(T_{q_{v}}(t)\) 按照以下方式降低
\[T_{q_{v}}(t) = T_{q_{v}}(1) \frac{2^{q_{v}-1}-1}{\left( \ 1 + t\right)^{q_{v}-1}-1}\]其中 \(q_{v}\) 是访问参数。
1.2.0 版本新增。
参考文献
[1]Tsallis C. Boltzmann-Gibbs 统计的可能推广。统计物理学杂志,52, 479-487 (1998)。
[2]Tsallis C, Stariolo DA. 广义模拟退火算法。物理学 A,233,395-406(1996)。
[3]Xiang Y, Sun DY, Fan W, Gong XG. 广义模拟退火算法及其在汤姆逊模型中的应用。物理快报 A, 233, 216-220 (1997)。
[4]Xiang Y, Gong XG. 广义模拟退火的效率。物理评论 E,62,4473 (2000)。
[5]Xiang Y, Gubian S, Suomela B, Hoeng J. 用于高效全局优化的广义模拟退火:R 的 GenSA 包。 R 期刊,第 5/1 卷 (2013)。
[6]Mullen, K. R 中的连续全局优化。统计软件杂志,60(6), 1 - 45, (2014)。 DOI:10.18637/jss.v060.i06
示例
以下示例是一个 10 维问题,具有许多局部最小值。所涉及的函数称为 Rastrigin (https://en.wikipedia.org/wiki/Rastrigin_function)
>>> import numpy as np >>> from scipy.optimize import dual_annealing >>> func = lambda x: np.sum(x*x - 10*np.cos(2*np.pi*x)) + 10*np.size(x) >>> lw = [-5.12] * 10 >>> up = [5.12] * 10 >>> ret = dual_annealing(func, bounds=list(zip(lw, up))) >>> ret.x array([-4.26437714e-09, -3.91699361e-09, -1.86149218e-09, -3.97165720e-09, -6.29151648e-09, -6.53145322e-09, -3.93616815e-09, -6.55623025e-09, -6.05775280e-09, -5.00668935e-09]) # random >>> ret.fun 0.000000