
种群优化算法:模拟退火(SA)。第 1 部分
内容
1. 概述
模拟退火算法由 Scott Kirkpatrick、George Gelatt 和 Mario Vecchi 于 1983 年开发。在研究高温下液体和固体的性质时,发现金属转变为液态,颗粒随机分布,而能量最小的状态是在初始温度足够高、冷却时间足够长的条件下实现的。如果不满足此条件,那么材料将发现自身处于具有非最小能量的亚稳态 — 这称为硬化,它是由材料的急剧冷却造成。在这种情况下,原子结构不具备对称性(各向异性状态,或晶格内材料的性质不均匀)。
在缓慢的退火过程中,材料也变成固态,但具有组织化的原子和对称性,故此拟议使用该过程开发一种优化算法,该算法可以在复杂问题中找到全局最优。该算法也被提议作为解决组合优化问题的方法。
因此,该算法的主要思路是基于金属退火过程的数学模拟。在退火过程中,为了均匀分布其内能,将金属加热到高温后缓慢冷却,令金属分子移动,并有序进入更稳定的状态,同时释放金属中的内应力,去除晶间缺陷。术语“退火”也与热力学自由能有关,热力学自由能是材料的一个属性,取决于其状态。
模拟退火优化算法使用类似的过程。该算法应用了类似于加热和冷却材料的操作。该算法从初始解开始工作,该初始解可以是随机的,也可从以前的迭代中获得。然后,它应用操作来更改解的状态(可以是随机的、或受控的),从而获得新状态,即使它比当前状态更差。做出更差决策的概率由“冷却”函数决定,该函数降低了随着时间的推移做出更差决策的概率,允许算法暂时“跳出”局部最优值,并在搜索空间的其它地方寻找更好的解。
模拟退火算法基于三个主要概念:
- 随机性的应用:该算法使用随机操作来改变解的状态,并选择下一个状态。这允许探索搜索空间的不同区域,并避免陷入局部最优状态。
- 接受更糟糕的决策:SA 是极少数算法之一,它更喜欢具有一定概率的更糟糕决策,而不是更好的决策。
- 逐渐降低做出更糟糕决策的可能性:该算法使用“冷却”过程,随着时间的推移降低做出更糟糕决策的可能性。这令我们能够首先更广泛地探索搜索空间,然后专注于改进解,平衡搜索空间的探索和拓展。
模拟退火优化算法是元启发式中所用的方法之一,它描述了一类用于求解复杂优化问题的算法。它们基于启发式方法,允许在搜索空间中搜索近似解,而无需完全搜索所有可能的选项。随机性是元启发式的关键要素之一,它令它们能够发现新的和有前途的解区域。该算法属于一组称为“随机优化方法”的算法。
SA 算法有其缺点,我们将在下面讨论。其它基于 SA 的算法也有所开发,例如自适应模拟退火(ASA),和量子归一化(QN),也称为量子退火(QA)。
2. 算法
作者提议的模拟退火算法的基本版本非常简单,但如果没有直观地显示温度变化过程的图形,和做出最坏决策的概率图,就不容易想象该算法是如何工作的。
我们一步一步地弄清楚。该算法在一定的初始高温(外部参数)下开始工作,这对应于冶金中加热材料。高温意味着分子的高能量在不同能量状态(较低或较高)间移动。与金属中的这种高能运动过程类似,该系统可以按一定的概率做出更糟糕的决策。
如果我们想象一个滑雪者从山顶上移动,那么当他发现自己所在是某个低地时,滑雪者可能会决定他已经到达了山脚下。为了确保这个决定是正确的,我们需要稍微调整我们的位置,并上升到一定的高度,以便以更快的速度冲下来。这就是以某种概率做出更糟糕决定的意义所在。为了跳出局部“陷阱”,开发了一种量子退火算法,该算法模拟了同时在两个地方的量子效应,其中推测它穿过隧道跳过“壁垒”,但尝试摆脱一些缺点,量子退火还有其它,特别是选择量子跃迁强度的问题。
使用若干简单的方程来描述模拟退火。能量计算方程:
E = f (x)
换言之,E 表示个体当前状态的适应度函数值。
能量变化计算方程:
ΔE = E_new - E_old
其中:
- ΔE - 从当前状态过渡到新状态期间的能量变化(两次连续迭代时,适应度函数值的差值)
- E_new - 新状态的能量值
- E_old - 先前状态的能量值
计算做出更糟糕决策概率的公式:
P = exp (-ΔE / T)
其中:
- P - 做出更糟糕决定的概率
- T - 当前温度
从下图中可以看出,P 概率依赖性越高,ΔE 越高,概率越低。这意味着随着温度的降低,高能向下跃迁的概率比能量差值较小时向下跃迁得更快。换言之,算法在尝试摆脱“陷阱”时承担的风险越来越小,而只倾向于改进解。概率图如图例 1 所示,尽管该算法使用温度的非线性变化,但为了清楚起见,使用了温度的线性降低。
图例 1. 随着温度线性下降,能量变化的决策概率图变得更糟
温度更新方程:
Tnew = α * Tprev
其中:
- α - 冷却比。α 通常在 0.8 到 0.99 之间
- Tnew - 新温度
- Tprev - 以前的温度
在起始温度 T = 500 时,α = 0.99、0.8、0.5 和 0.1 的每次迭代时温度变化图如图例 2 所示。温度逐渐降低,这对应于材料的冷却。每次迭代时降低温度,会导致做出更糟糕决策的可能性降低,这相当于分子随着温度降低,而改变其能量状态的能力降低。
图例 2. α = 0.99、0.8、0.5 和 0.1 的温度变化图
生成新系统状态的公式:
x_new = GenerateNeighbor (x)
其中:
- x_new - 基于当前 x 状态生成的新状态
- GenerateNeighbor(x) - 通过引入对当前状态具有均匀分布的随机变化,来生成新状态的函数
现在我们已经了解了模拟退火算法的所有理论基础,编写 SA 代码对我们来说并不难。我们可以按结构(S_Agent)的形式表示改变其能量状态的分子运动,该结构包含有关优化问题中个体的信息。字段和结构方法:
- Init(int coords) - 方法初始化个体,并为 “c” 和 “cPrev” 数组分配内存大小为 “coords”。它还将 “f” 和 “fPrev” 的初始值设置为 “-DBL_MAX”(负无穷大)
- c [] - “c” 数组表示个体在优化空间中的坐标
- cPrev [] - “cPrev” 数组表示个体的先前坐标
- f - 个体当前坐标的适应度函数值
- fPrev - 个体的适应度函数的上一个值
//———————————————————————————————————————— struct S_Agent { void Init (int coords) { ArrayResize (c, coords); ArrayResize (cPrev, coords); f = -DBL_MAX; fPrev = -DBL_MAX; } double c []; //coordinates double cPrev []; //previous coordinates double f; //fitness double fPrev; //previous fitness }; //————————————————————————————————————————
我们来讲述一下 SA 算法类,并将其命名为 C_AO_SA。结果会非常简单,因为它不包含任何我们以前没有用到过的异常内容,除了特定的热变量和常数。
类的字段和方法:
- cB [] - 优化算法在当前迭代时找到的最佳坐标数组
- fB - 最佳坐标的适应度函数值
- a [] - 表示个体的数组。它用于存储有关优化问题中每个个体的信息。数组的每个元素都是 S_Agent 结构的一个实例
- rangeMax [] - 用于判定每个个体坐标的搜索上边界,每个坐标的最大搜索范围值的数组
- rangeMin [] - 每个坐标的最小搜索范围值数组,用于判定每个个体坐标的搜索下边界
- rangeStep [] - 数组表示每个坐标的搜索步骤
- Init(const int coordsP, const int popSizeP, const double tP, const double aP, const double dP) - 该方法初始化优化算法,接受参数:坐标数 “coordsP”、种群大小 “popSizeP”、初始温度 “tP”、温度降低比 “aP”、和扩散系数 “dP”。该方法初始化类和个体字段
- Moving () - 该方法在优化期间移动个体,并使用该算法判定个体的新坐标
- Revision () - 该方法根据个体的当前值,执行最佳坐标和适应度函数的修订和更新
- SeInDiSp(double In, double InMin, double InMax, double Step) - 用于规范从 “InMin” 到 “InMax” 范围内的 “In” 值的私密方法,步长为 “Step”
- RNDfromCI(double min, double max) - 在给定范围内从 “min” 到 “max” 生成随机数的私密方法
应该注意的是,原始 SA 版本中不存在 dP 扩散比。作者的思路是生成系统的新状态,并相应地在每个坐标从 “min” 到 “max” 的整个范围内生成一个新的个体坐标。这对应于接受退火的金属在整个“体积”中的分子混沌运动。我的实验表明,如果分子振动的范围仅限于以整个允许区间的一部分表示的某个区间,则结果会有所改善。这是扩散比参数的确切目标 - 限制分子可能混合的区域。
为了获得与原始 SA 等效的结果,只需将参数设置为 1(默认为 0.2)。
//———————————————————————————————————————— class C_AO_SA { //---------------------------------------------------------------------------- public: double cB []; //best coordinates public: double fB; //FF of the best coordinates public: S_Agent a []; //agent public: double rangeMax []; //maximum search range public: double rangeMin []; //manimum search range public: double rangeStep []; //step search public: void Init (const int coordsP, //coordinates number const int popSizeP, //population size const double tP, //temperature const double aP, //temperature reduction coefficient const double dP); //diffusion coefficient public: void Moving (); public: void Revision (); //---------------------------------------------------------------------------- private: int coords; //coordinates number private: int popSize; //population size private: double T; private: double α; private: double d; private: bool revision; private: double SeInDiSp (double In, double InMin, double InMax, double Step); private: double RNDfromCI (double min, double max); }; //————————————————————————————————————————
Init 函数将用作初始化方法,其初始化类的所有字段,并分配优化算法工作所需的数组大小。
//———————————————————————————————————————— void C_AO_SA::Init (const int coordsP, //coordinates number const int popSizeP, //population size const double tP, //temperature const double aP, //temperature reduction coefficient const double dP) //diffusion coefficient { MathSrand ((int)GetMicrosecondCount ()); // reset of the generator fB = -DBL_MAX; revision = false; coords = coordsP; popSize = popSizeP; T = tP; α = aP; d = dP; ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); ArrayResize (rangeMax, coords); ArrayResize (rangeMin, coords); ArrayResize (rangeStep, coords); ArrayResize (cB, coords); } //————————————————————————————————————————
编写 Moving 方法,以便在搜索空间中移动个体。在第一次迭代时,当算法刚刚启动时,变量 - “revision” 标志等于 “false”。有必要用位于均匀分布的 [min;max] 坐标范围内的初始值初始化种群个体。我们调用 SeInDiS 函数对获得的个体坐标值进行常规化,以便维护所需的移动步长。接下来,“revision” 标志设置为 “true”,指示需要在下一次迭代中应用模拟退火算法运算。
如果这是原始的 SA,那么我们将执行我们在第一次迭代中所做的操作,即继续在给定范围内生成随机数,并在第二次和后续迭代中均匀分布。而在我们略微修正的版本中,我们将做同样的事情,但调整了值的范围,从而限制了分子在金属中的扩散相互作用区域,而运动是从分子在上一次迭代中的位置进行的。我们调用 SeInDiS 函数对获得的个体坐标值进行常规化,以便维护所需的移动步长。
//———————————————————————————————————————— void C_AO_SA::Moving () { //---------------------------------------------------------------------------- if (!revision) { for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { a [i].c [c] = RNDfromCI (rangeMin [c], rangeMax [c]); a [i].c [c] = SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } revision = true; return; } //---------------------------------------------------------------------------- double rnd = 0.0; for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { rnd = RNDfromCI (-0.1, 0.1); a [i].c [c] = a [i].cPrev [c] + rnd * (rangeMax [c] - rangeMin [c]) * d; a [i].c [c] = SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } } //————————————————————————————————————————在 “Moving” 方法中,我们生成了系统的新状态,即在热熔金属中移动的分子,然后在 “Revision” 方法中,我们将计算 “热平衡” 和分子过渡到新状态的概率。
在方法伊始,我们将检查个体的所有适应度函数值。如果我们发现该值比全局值更好,那么我们将更新它。
接下来,在 “for” 循环中,针对种群中的每个个体执行以下操作:
- 值 “ΔE” 计算为 “a[i].f” 和 “a[i].fPrev” 之间差值的绝对值,即当前迭代和上一次迭代时适应度函数值之间的差值
如果 “a[i].f” 的值大于 “a[i].fPrev” 的值(即当前适应度优于前一个适应度),则执行以下代码模块:
- 值 “a[i].fPrev” 替换为 “a[i].f”
- “a[i].cPrev” 数组的值是从 “a[i].c” 数组复制而来
否则,将执行以下代码模块(适应度函数的当前值比前一个值差):
- 概率值 “P” 计算为 “ΔE” 与 “T” 的负比的指数
- 从范围 [0.0;1.0] 给 “rnd” 生成一个随机数,模拟过渡到比前一个状态更差的新状态的概率
如果 “rnd” 的值小于 “P” 的值(即概率满足),则:
- 值 “a[i].fPrev” 替换为 “a[i].f”
- “a[i].cPrev” 数组的值是从 “a[i].c” 数组复制而来
温度值 “T” 乘以 “α” 热比,每次新的迭代都会降低温度。
//———————————————————————————————————————— void C_AO_SA::Revision () { //---------------------------------------------------------------------------- int ind = -1; for (int i = 0; i < popSize; i++) { if (a [i].f > fB) ind = i; } if (ind != -1) { fB = a [ind].f; ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY); } //---------------------------------------------------------------------------- double rnd = 0.0; double ΔE; double P; for (int i = 0; i < popSize; i++) { ΔE = fabs (a [i].f - a [i].fPrev); if (a [i].f > a [i].fPrev) { a [i].fPrev = a [i].f; ArrayCopy (a [i].cPrev, a [i].c, 0, 0, WHOLE_ARRAY); } else { P = exp (-ΔE / T); rnd = RNDfromCI (0, 1.0); if (rnd < P) { a [i].fPrev = a [i].f; ArrayCopy (a [i].cPrev, a [i].c, 0, 0, WHOLE_ARRAY); } } } T = α * T; } //————————————————————————————————————————
3. 测试结果
原始算法的试验台结果在整个允许值范围内生成随机数:
C_AO_SA:50:1000.0:0.1:0.2
=============================
5 Rastrigin's; Func runs 10000 result: 61.3646399742684
Score: 0.76034
25 Rastrigin's; Func runs 10000 result: 47.454223750487884
Score: 0.58798
500 Rastrigin's; Func runs 10000 result: 39.06494648961887
Score: 0.48404
=============================
5 Forest's; Func runs 10000 result: 0.4708272303190655
Score: 0.26632
25 Forest's; Func runs 10000 result: 0.17553657864203864
Score: 0.09929
500 Forest's; Func runs 10000 result: 0.0538869772164491
Score: 0.03048
=============================
5 Megacity's; Func runs 10000 result: 2.6
Score: 0.21667
25 Megacity's; Func runs 10000 result: 1.0
Score: 0.08333
500 Megacity's; Func runs 10000 result: 0.3044
Score: 0.02537
=============================
All score: 2.55383
该算法的试验台结果加上扩散比:
C_AO_SA:50:1000.0:0.1:0.2
=============================
5 Rastrigin's; Func runs 10000 result: 65.78409729002105
Score: 0.81510
25 Rastrigin's; Func runs 10000 result: 52.25447043222567
Score: 0.64746
500 Rastrigin's; Func runs 10000 result: 40.40159931988021
Score: 0.50060
=============================
5 Forest's; Func runs 10000 result: 0.5814827554067439
Score: 0.32892
25 Forest's; Func runs 10000 result: 0.23156336186841173
Score: 0.13098
500 Forest's; Func runs 10000 result: 0.06760002887601002
Score: 0.03824
=============================
5 Megacity's; Func runs 10000 result: 2.92
Score: 0.24333
25 Megacity's; Func runs 10000 result: 1.256
Score: 0.10467
500 Megacity's; Func runs 10000 result: 0.33840000000000003
Score: 0.02820
=============================
All score: 2.83750
我们可以看到,通过应用扩散比,该算法的性能得到了显著提升。原始算法需要改进,才能包含在我们的表格中。如此知名、且流行的优化方法,结果却如此微弱是出乎意料的,尤其是因为它已应用于训练神经网络。
SA 可视化没有在搜索空间中显示个体行为的任何明显特征。这些点表现混乱,没有形成类似于热布朗运动的结构。此外,该算法被困在局部极值和收敛性中,尽管不乏种群多样性,即种群在迭代结束时不会耗尽。
SA 基于 Rastrigin 测试函数
SA 基于 Forest 测试函数
SA 基于 Megacity 测试函数
模拟退火算法排在表格的底部。比较表格显示,该算法在单个测试中没有任何显著特征。所有结果均低于平均水平。表中有一些算法,例如 CSS,尽管它们位于表的底部,但在某些测试中展现了出色的结果。不幸的是,SA 算法不是其中之一。
# | AO | 说明 | Rastrigin | Rastrigin 最终 | Forest | Forest 最终 | Megacity (离散) | Megacity 最终 | 最终结果 | ||||||
10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | 10 p (5 F) | 50 p (25 F) | 1000 p (500 F) | |||||||
1 | SDSm | 随机扩散搜索 M | 0.99809 | 1.00000 | 0.69149 | 2.68958 | 0.99265 | 1.00000 | 1.00000 | 2.99265 | 1.00000 | 1.00000 | 1.00000 | 3.00000 | 100.000 |
2 | SSG | 树苗播种和生长 | 1.00000 | 0.92761 | 0.51630 | 2.44391 | 0.72120 | 0.65201 | 0.83760 | 2.21081 | 0.54782 | 0.61841 | 0.99522 | 2.16146 | 77.683 |
3 | DE | 差分进化 | 0.98295 | 0.89236 | 0.51375 | 2.38906 | 1.00000 | 0.84602 | 0.65510 | 2.50112 | 0.90000 | 0.52237 | 0.12031 | 1.54268 | 73.099 |
4 | HS | 谐声搜索 | 0.99676 | 0.88385 | 0.44686 | 2.32747 | 0.99148 | 0.68242 | 0.37529 | 2.04919 | 0.71739 | 0.71842 | 0.41338 | 1.84919 | 70.623 |
5 | IWO | 入侵性杂草优化 | 0.95828 | 0.62227 | 0.27647 | 1.85703 | 0.70170 | 0.31972 | 0.26613 | 1.28755 | 0.57391 | 0.30527 | 0.33130 | 1.21048 | 48.250 |
6 | ACOm | 蚁群优化 M | 0.34611 | 0.16683 | 0.15808 | 0.67103 | 0.86147 | 0.68980 | 0.64798 | 2.19925 | 0.71739 | 0.63947 | 0.05579 | 1.41265 | 47.387 |
7 | MEC | 心智进化计算 | 0.99270 | 0.47345 | 0.21148 | 1.67763 | 0.60244 | 0.28046 | 0.21324 | 1.09615 | 0.66957 | 0.30000 | 0.26045 | 1.23002 | 44.049 |
8 | SDOm | 螺旋动力学优化 M | 0.69840 | 0.52988 | 0.33168 | 1.55996 | 0.59818 | 0.38766 | 0.37600 | 1.36183 | 0.35653 | 0.15262 | 0.25842 | 0.76758 | 40.289 |
9 | NMm | Nelder-Mead 方法 M | 0.88433 | 0.48306 | 0.45945 | 1.82685 | 0.46155 | 0.24379 | 0.21903 | 0.92437 | 0.46088 | 0.25658 | 0.16810 | 0.88555 | 39.660 |
10 | COAm | 布谷鸟优化算法 M | 0.92400 | 0.43407 | 0.24120 | 1.59927 | 0.57881 | 0.23477 | 0.13842 | 0.95200 | 0.52174 | 0.24079 | 0.17001 | 0.93254 | 37.830 |
11 | FAm | 萤火虫算法 M | 0.59825 | 0.31520 | 0.15893 | 1.07239 | 0.50637 | 0.29178 | 0.41704 | 1.21519 | 0.24783 | 0.20526 | 0.35090 | 0.80398 | 33.139 |
12 | ABC | 人工蜂群 | 0.78170 | 0.30347 | 0.19313 | 1.27829 | 0.53379 | 0.14799 | 0.11177 | 0.79355 | 0.40435 | 0.19474 | 0.13859 | 0.73768 | 29.766 |
13 | BA | 蝙蝠算法 | 0.40526 | 0.59145 | 0.78330 | 1.78002 | 0.20664 | 0.12056 | 0.21769 | 0.54488 | 0.21305 | 0.07632 | 0.17288 | 0.46225 | 29.499 |
14 | CSS | 收费系统搜索 | 0.56605 | 0.68683 | 1.00000 | 2.25289 | 0.13961 | 0.01853 | 0.13638 | 0.29452 | 0.07392 | 0.00000 | 0.03465 | 0.10856 | 27.930 |
15 | GSA | 重力搜索算法 | 0.70167 | 0.41944 | 0.00000 | 1.12111 | 0.31390 | 0.25120 | 0.27812 | 0.84322 | 0.42609 | 0.25525 | 0.00000 | 0.68134 | 27.807 |
16 | BFO | 细菌觅食优化 | 0.67203 | 0.28721 | 0.10957 | 1.06881 | 0.39364 | 0.18364 | 0.17298 | 0.75026 | 0.37392 | 0.24211 | 0.18841 | 0.80444 | 27.542 |
17 | EM | 类电磁算法 | 0.12235 | 0.42928 | 0.92752 | 1.47915 | 0.00000 | 0.02413 | 0.29215 | 0.31628 | 0.00000 | 0.00527 | 0.10872 | 0.11399 | 19.002 |
18 | SFL | 蛙跳 | 0.40072 | 0.22021 | 0.24624 | 0.86717 | 0.19981 | 0.02861 | 0.02221 | 0.25063 | 0.19565 | 0.04474 | 0.06607 | 0.30646 | 13.200 |
19 | SA | 模拟退火 | 0.36938 | 0.21640 | 0.10018 | 0.68595 | 0.20341 | 0.07832 | 0.09372 | 0.37545 | 0.16956 | 0.08422 | 0.10394 | 0.35772 | 13.138 |
20 | MA | 猴子算法 | 0.33192 | 0.31029 | 0.13582 | 0.77804 | 0.09927 | 0.05443 | 0.07482 | 0.22852 | 0.15652 | 0.03553 | 0.10669 | 0.29874 | 11.777 |
21 | FSS | 鱼群搜索 | 0.46812 | 0.23502 | 0.10483 | 0.80798 | 0.12730 | 0.03458 | 0.05458 | 0.21647 | 0.12175 | 0.03947 | 0.08244 | 0.24366 | 11.332 |
22 | IWDm | 智能水滴 M | 0.26459 | 0.13013 | 0.07500 | 0.46972 | 0.28358 | 0.05445 | 0.05112 | 0.38916 | 0.22609 | 0.05659 | 0.05054 | 0.33322 | 10.423 |
23 | PSO | 粒子群优化 | 0.20449 | 0.07607 | 0.06641 | 0.34696 | 0.18734 | 0.07233 | 0.18207 | 0.44175 | 0.16956 | 0.04737 | 0.01947 | 0.23641 | 8.426 |
24 | RND | 随机 | 0.16826 | 0.09038 | 0.07438 | 0.33302 | 0.13381 | 0.03318 | 0.03949 | 0.20648 | 0.12175 | 0.03290 | 0.04898 | 0.20363 | 5.054 |
25 | GWO | 灰狼优化器 | 0.00000 | 0.00000 | 0.02093 | 0.02093 | 0.06514 | 0.00000 | 0.00000 | 0.06514 | 0.23478 | 0.05789 | 0.02545 | 0.31812 | 1.000 |
总结
模拟退火算法存在一些弱点,可能会限制其解决某些优化问题的有效性。其中一些弱点包括:
- 对初始解的依赖性:与许多其它优化方法一样,模拟退火算法可能依赖于随机选择的初始解。如果初始解不好,则算法可能会卡在局部优化中,无法找到全局最优值。
需要注意的是,该算法需要调整参数,例如初始“温度”和温度变化步长,这会影响做出更糟糕决策的可能性。这些参数会影响解决方案的性能和质量,因此在将模拟退火算法应用于特定优化问题时,参数选择和调整是重要方面。设置这些参数可能具有挑战性。不正确的设置可能会导致效果不佳。选择默认设置是为了在测试功能集中获得最佳结果。 - 模拟退火算法的另一个弱点是可能卡在局部极端。当算法找到最优解时,就会发生这种情况,该解是局部极值,但不是全局极值。在这种情况下,算法无法进一步前进,并停在局部优化。这在上面的可视化中非常清晰可见。
- 收敛速度慢:SA 收敛到最优解的速度可能很慢,特别是对于复杂的优化问题。这是因为该算法使用随机性,可能会做出更糟糕的决策,而这可能会减慢优化过程。
- 需要大量迭代:为了实现最优解,仿真退火算法可能需要大量的迭代。对于执行时间是关键因素的任务,这可能是一个问题。
- 解决变量多的问题效率低:由于搜索空间可能太大,SA 在解决变量多的问题时可能无效。在这种情况下,其它优化方法,如遗传算法或基于梯度的优化方法,可能更有效。该算法可以很好地处理少量变量(1-2),就像任何算法一样,即使是简单的随机 RND。
模拟退火算法可以应用若干项改进,以提高其性能和效率:
1. 冷却函数的修改:冷却函数是算法调节系统冷却速度和温度的重要参数。
2. 使用更有效的方法选择下一个状态:SA 使用随机选择下一个状态。不过,还有更有效的方法来选择下一个状态,例如突变和交叉方法。
3. 使用自适应参数:算法参数,如初始温度和冷却比,可以根据优化问题的特点进行自适应调整。
4. 采用算法组合:SA 可以与其它优化算法相结合,如遗传算法、或梯度下降方法,以提高优化性能和效率。
在生成系统的新状态、而不是统一状态时,使用随机变量的不同分布无助于改善结果。然而,有一种方法可以从根本上改变这种非常著名和流行的算法,令其能够与表格上的领先者竞争。这怎么可能?- 我将在文章的第二部分分享这种方法,并讨论完成修改的所有阶段。但是,正如我们所知,没有通用的方法来改进任何优化算法,它完全取决于算法本身的搜索策略。因此,改进将只涉及旧的(但实际上无用的)模拟退火算法。
图例 3. 算法的颜色渐变是根据相关测试
图例 4. 算法测试结果的直方图(标尺从 0 到 100,越多越好,
存档包含文章中应用的计算评级表格的方法脚本)。
SA 的优点和缺点:
优势:
- 少量外部参数。
- 高速操作
- 简单实现
缺点:
- 设置不明显(目前尚不清楚温度的影响方式和影响方式)。
- 可伸缩性非常差。
- 结果高度分散。
- 有陷入局部极值的倾向。
- 收敛性差。
本文附有一个存档,其中包含前几篇文章中讲述的算法代码的当前更新版本。文章作者不对规范算法讲述的绝对准确性负责。对其中进行了多处修改,从而提升搜索能力。文章中呈现的结论和论断是基于实验的结果。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/13851


