
种群优化算法:进化策略,(μ,λ)-ES 和 (μ+λ)-ES
内容
1. 概述
2. 算法
3. 替换测试函数
4. 测试结果
5. 结束语
1. 概述
进化策略算法中的优化方法,基于从自然界中观察到的原理。它们模拟自然选择,其中最优解得以生存,并将其特性传递给下一代。这些算法广泛用于解决优化问题,尤其是在机器学习和人工智能领域。它们是由德国的 Ingo Rechenberg 教授及其同事在 1960 年代开发的,用于解决工业和工程中的优化问题。
进化策略的基本思想是创建一个解集,然后使用类似于自然进化中所用的突变和选择运算符来改进它们。进化策略使用真实向量来表示解。这令我们能够更灵活、更准确地描述解空间,并搜索最优值,这与二元运算的经典遗传算法形成鲜明对比。
进化策略有若干种不同的变体,它们在种群的生成和处理方式,以及所用的突变和选择运算符上有所不同。一些最常见的选项包括:
- (1+1)-ES:在该变体中,仅为每个亲本创建一个子代,两者的最优解将成为下一代的亲本。这种简单快速的方法对于某些问题可能有效,但对于优化复杂问题时效果较差。(1+1)-ES 算法创建于 1960 年代,是优化所有进化策略的最简单方法之一。它包括生成一个随机向量,然后将其按随机步骤变更。如果修改后的向量更好,则替换原始向量,否则原始向量保持不变。重复此过程,直到达成最优态。
- (μ,λ)-ES:在该算法中,创建了一个 μ 大小的亲本群落,并产生 λ 个子代,且最佳子代会取代亲本。它可以有效地解决各种优化问题。(μ,λ)-ES 算法由 Reinhard Speigelmann 创建于 1965 年。在对子代进行评估后,只保留最佳的 μ 解,并成为下一代的亲本,因此亲本在每个世代都完全被子代替换。
- (μ+λ)-ES:在该选项中,将创建 λ 个后代。他们中的佼佼者,与亲本一起参与下一代的创造。在这种方法中,亲本和子代相互竞争,这与 (μ,λ)-ES 是一个重要的区别。(μ+λ)-ES 算法由 Johannes Reichenbacher 和 Hans-Paul Schwefel 于 1970 年代创建,是优化所有进化策略的一种方法。这种方法允许对解空间进行更完整的探索,并且可以更有效地解决复杂问题。
进化策略还有其它变体,但在本文中,我们仅研究 (μ,λ)-ES 和 (μ+λ)-ES。(1+1)-ES 选项太简单,不适合求解多维问题。由于在代码、文件名、以及变量名中使用希腊字母和特殊字符的困难,我们将分别使用 PO 和 P_O,其中 P 代表亲本,O 意即幼崽(后代)。
计算机科学中的进化策略令我们能够对进化和自然选择进行建模,从而解决复杂的优化问题。它们使用类似于自然选择的原理在参数空间中寻找最优解。
在没有明显的分析解、或搜索空间非常大的问题中,这些算法特别实用。它们可以采用受进化启发的操作(如杂交、突变、和选择)有效地搜索最优解。
“进化策略”这个名字可能具有误导性,因为研究人员也许认为它是一类进化算法的通用名称。然而,事实并非如此。事实上,它是一套特定的算法,它们利用进化的思想来解决优化问题。
2. 算法
(μ,λ)-ES 表示在算法的每次迭代中,选择 μ 个亲本,并生成 λ 个子代。然后,从 λ 个子代中选择最佳 μ 子代,成为下一次迭代的亲本。因此,在 (μ,λ)-ES 中,新的幼崽完全取代了他们的亲本,并参与下一代的创造。
(μ+λ)-ES 按类似的方式工作,但不是从 λ 中选择最佳幼崽,而是将它们与亲本结合形成 μ+λ 大小的新群落。然后从这个组合群落中选择 μ 个最佳个体成为下一次迭代的亲本。因此,在 (μ+λ)-ES 中,新的幼崽与他们的亲本一起形成下一个群落,并相互竞争。
(μ,λ)-ES 和 (μ+λ)-ES 之间的主要区别在于新生幼崽如何与亲本竞争在下一个群落中的位置。在 (μ,λ)-ES 中,新生子代与亲本争夺有限数量的名额,这可能导致过早地收敛到局部最优值。在 (μ+λ)-ES 中,新生子代与亲本一起工作,从而对解空间进行了更广泛的探索。
两种进化策略算法都基于遗传算子的组合:突变和选择。在算法的每次迭代中,从当前群落中选择一位个体,并对其应用突变算子,然后计算所得个体的适应度,并将最适者放入下一个群落之中。为了生成初始群落,为变化参数向量里的每个分量指定一个区间,并假设分量的初始值在指定的区间内均匀分布。该算法可以使用各种停止条件,例如达到指定的世代数量、指定的群落状态、或指定的收敛水平。在 (μ+λ) 算法中,所有个体都包含在群落中,而在 (μ,λ) 算法中,仅包含后代。对于 (μ+λ) 算法,概率收敛性已经得到证明,但对于 (μ,λ) 算法,收敛性问题仍然悬而未决。
(μ+λ) 和 (μ,λ) 算法的比较表明,(μ+λ) 算法在使用高度适应的个体方面更节省,保留他们与后代竞争。这增加了搜索的强度,但可能导致过早收敛到局部极值。传统进化策略算法中的突变算子是唯一的进化算子,使用高斯突变算法。
经典的 (μ,λ)-ES 算法可以用以下伪代码来描述:
1. 以随机个体初始化初始群落。
2. 重复直到达到停止标准:
2.1. μ 个亲本中的每一个都使用突变算子生成 λ 个幼崽,并入当前群落。
2.2. 选择最佳的 μ 个后代组成下一个群落。
3. 从最后一个群落中返回最佳个体。
传统的 (μ+λ)-ES 算法可以用以下伪代码来描述:
1. 以随机个体初始化初始群落。
2. 重复直到达到停止标准:
2.1. μ 个亲本中的每一个都使用突变算子生成 λ 个幼崽,并入当前群落。
2.2. 将亲本和幼崽合并,得到 μ+λ 大小的组合群落。
2.3. 从组合群落中选择最佳的 μ 位个体组成下一个群落。
3. 从最后一个群落中返回最佳个体。
我们查看了两种主要“进化策略”算法的经典版本。在这两种情况下,亲本仅使用他们的遗传信息产生 λ 个幼崽。该结局呈星形分支,其中每个后代都彼此独立发育。亲本之间也没有信息交流,这排除了结合他们的遗传特性的可能性。如此这般,组合品质彻底缺失。
测试结果表明,这两种 ES 选项的效率都较低。我尝试使用重组来提升它。
重组允许将来自不同个体的遗传物质组合在一起,从而创建可能具有更好属性或性状的新组合。这一过程促进了群落的多样性。
重组(或杂交)是将亲本的遗传物质结合,从而产生幼崽的过程。这个过程模拟了生物进化中的自然交叉。在重组期间,亲本的基因结合,为幼崽创造新的遗传物质。重组通常发生在基因或遗传性状的级别上。基因是生物体基因组中特定属性或特征的编码信息片段。
重组后,后代的基因将使用突变算子进行更改,可对基因进行随机更改。这有助于将新的研究变体引入群落,并促进遗传物质的多样性。
因此,对于每个后代基因,我们将使用随机选择的亲本基因,其中基因是相应的亲本坐标。因此,幼崽将继承群落中所有亲本的特征。
(μ,λ)-ES 算法。
我们继续回顾代码,从更简单的算法 (μ,λ)-ES 开始,通过添加重组(来自多个亲本的基因遗传)进行修改。
对于充当个体的亲本和子代,S_Agent 是一个好的结构,其中包含一个坐标 “c” 的数组,和一个变量 “f” — 适应度值。Init 函数初始化个体时,会调整数组 “c” 的大小,并将 “f” 的值设置为 “-DBL_MAX”(可能的最差适应度值)。
//—————————————————————————————————————————————————————————————————————————————— struct S_Agent { void Init (int coords) { ArrayResize (c, coords); f = -DBL_MAX; } double c []; //coordinates double f; //fitness }; //——————————————————————————————————————————————————————————————————————————————
声明 C_AO_POES 类来描述 (μ,λ)-ES 算法。
- “cB”、“fB”、“a”、“rangeMax”、“rangeMin”、“rangeStep” 公开变量:这些变量分别用于存储最佳坐标、对应的适应度函数值、个体、最大和最小搜索值、以及搜索步骤。
- Public Init():该函数初始化优化算法。它需要几个参数,例如坐标数量、群落大小、亲本个体数量、突变强度、和西格玛值。在函数内部,算法所用的变量和数组被初始化。
- “Moving()” 和 “Revision()” 公开函数:这些函数分别用于执行个体移动和群落修订。
- “coords”、“popSize”、“parentsNumb”、“mutationPower”、“sigmaM”、和 “revision” 私密变量:这些变量分别用于存储坐标数量、群落大小、亲本个体数量、突变强度、西格玛值、和修订标志。
- “parents”、“ind”、“val” 和 “pTemp” 私密数组:这些数组分别用于存储有关亲本个体、索引、值、和临时变量的信息。
- GaussDistribution()、SeInDiSp()、RNDfromCI()、Scale()、Sorting() 私密函数:这些函数用于执行随机数生成、值缩放、和数组排序。
//—————————————————————————————————————————————————————————————————————————————— class C_AO_POES { //---------------------------------------------------------------------------- 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 int parentsP, //number of parents, < Population size const double mutationPowerP, //mutation power const double sigmaP); //sigma public: void Moving (); public: void Revision (); //---------------------------------------------------------------------------- private: int coords; //coordinates number private: int popSize; //population size private: int parentsNumb; //number of parents private: double mutationPower; //mutation power private: double sigmaM; private: bool revision; private: S_Agent parents []; //parents private: int ind []; private: double val []; private: S_Agent pTemp []; private: double GaussDistribution (const double In, const double outMin, const double outMax, const double sigma); private: double SeInDiSp (double In, double InMin, double InMax, double Step); private: double RNDfromCI (double min, double max); private: double Scale (double In, double InMIN, double InMAX, double OutMIN, double OutMAX, bool revers); private: void Sorting (S_Agent &p [], int size); }; //——————————————————————————————————————————————————————————————————————————————
为了初始化优化算法,调用 C_AO_POES 类的 Init 函数。该函数接受几个参数:坐标数量、群落大小、亲本个体数量、突变强度、和西格玛值。
在函数内部,算法所用的变量和数组被初始化。该函数执行以下操作:
- 重置随机数生成器,并将 “fB” 变量设置为 “-DBL_MAX”。
- 设置 “coords”、“popSize”、“parentsNumb”、“mutationPower” 和 “sigmaM” 变量值。
- 调用 ArrayResize 函数更改 “ind”、“val”、“pTemp”、“a”、“parents”、“rangeMax”、“rangeMin”、“rangeStep” 和 “cB” 数组大小。
- “a” 和 “parents” 数组是调用 “S_Agent” 类的 Init 函数初始化的,该函数初始化个体的坐标,并将 “f” 变量值设置为 “-DBL_MAX”。
//—————————————————————————————————————————————————————————————————————————————— void C_AO_POES::Init (const int coordsP, //coordinates number const int popSizeP, //population size const int parentsP, //number of parents, < Population size const double mutationPowerP, //mutation power const double sigmaP) //sigma { MathSrand ((int)GetMicrosecondCount ()); // reset of the generator fB = -DBL_MAX; revision = false; coords = coordsP; popSize = popSizeP; parentsNumb = parentsP; mutationPower = mutationPowerP; sigmaM = sigmaP; ArrayResize (ind, popSize); ArrayResize (val, popSize); ArrayResize (pTemp, popSize); ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); ArrayResize (parents, parentsNumb); for (int i = 0; i < parentsNumb; i++) parents [i].Init (coords); ArrayResize (rangeMax, coords); ArrayResize (rangeMin, coords); ArrayResize (rangeStep, coords); ArrayResize (cB, coords); } //——————————————————————————————————————————————————————————————————————————————
Moving 方法在搜索空间中移动个体。
该函数包含两个代码模块,由 “if (!revision)” 条件分隔。
- 在第一个模块中,如果 “revision” 标志为 “false”,则为每位个体生成随机坐标。对于每个坐标,生成一个随机数,在 “rangeMin” 和 “rangeMax” 之间均匀分布,然后调用 SeInDiSp 函数对该数字进行常规化,该函数将坐标值设置为 “rangeStep” 的最接近的倍数。
- 在第二个模块中,如果 “revision” 标志等于 “true”,则会发生个体的移动。对于每个个体,从 “parents” 数组中随机选择一个亲本个体。然后,计算每位个体坐标的突变值 “dist”。该值取决于 “mutationPower” 突变强度,以及 “rangeMin” 和 “rangeMax” 搜索范围。调用 GaussDistribution 函数更改个体的坐标值,该函数使用 “sigmaM” 西格玛值,在父坐标值周围生成一个正态分布的随机数。然后,调用 SeInDiSp 函数对坐标值进行常规化。
//—————————————————————————————————————————————————————————————————————————————— void C_AO_POES::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; } //---------------------------------------------------------------------------- int indx = 0; double min = 0.0; double max = 0.0; double dist = 0.0; for (int i = 0; i < popSize; i++) { for (int c = 0; c < coords; c++) { indx = (int)RNDfromCI (0, parentsNumb); if (indx >= parentsNumb) indx = parentsNumb - 1; a [i].c [c] = parents [indx].c [c]; dist = (rangeMax [c] - rangeMin [c]) * mutationPower; min = a [i].c [c] - dist; if (min < rangeMin [c]) min = rangeMin [c]; max = a [i].c [c] + dist; if (max > rangeMax [c]) max = rangeMax [c]; a [i].c [c] = GaussDistribution (a [i].c [c], min, max, sigmaM); a [i].c [c] = SeInDiSp (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); } } } //——————————————————————————————————————————————————————————————————————————————
群落修订是通过 “Revision” 方法执行的,其修改优化算法中个体的当前状态。
该函数包含两个代码模块。
- 在第一个模块中,在 “for” 循环中遍历 “a” 数组中的最优个体。如果发现某个个体的适应度值高于当前最佳个体的 “fB”,则该个体的索引将存储在 “indx” 变量之中。然后,根据新的最佳个体更新当前最佳个体的 “fB” 值,和 “cB” 坐标。
- 在第二个模块中,调用 Sorting 函数对 “a” 数组按适应度降序排序,然后将 “a” 数组中的最佳个体的 “parentsNumb” 复制到 “parents” 数组当中。
因此,“Revision” 函数允许更新个体的当前状态,并将最佳个体保存在 “parents” 数组之中,其中最好的子代彻底替换所有亲本个体。
//—————————————————————————————————————————————————————————————————————————————— void C_AO_POES::Revision () { //---------------------------------------------------------------------------- int indx = -1; for (int i = 0; i < popSize; i++) { if (a [i].f > fB) indx = i; } if (indx != -1) { fB = a [indx].f; ArrayCopy (cB, a [indx].c, 0, 0, WHOLE_ARRAY); } //---------------------------------------------------------------------------- Sorting (a, popSize); for (int i = 0; i < parentsNumb; i++) { parents [i] = a [i]; } } //——————————————————————————————————————————————————————————————————————————————
(μ+λ)-ES 算法。
更改始自以 “yearsNumber” 参数的形式添加个体的预期生存期开始。这令控制群落的最高年龄成为可能,并避免其与非常老化的个体“堵塞”,从而阻止对无限生活空间新视野的探索,及新的发现。我希望,在该算法中这样做会很实用。
为什么 “(μ,λ)-ES” 算法中不包含此计数器?因为这就是它的意图。亲本完全被后代取代。这也是有道理的,就像动物王国中的传宗接代一样,有些物种一生中只繁殖一次。这类物种的例子包括鲑鱼、龙舌兰、竹子、椰子蟹、和苏铁。然而,在我们的算法中,我们将为个体提供多次繁殖的机会,无限期地活着或像竹子一样骄傲地死去。预期生存期可以是一个可调节的外部参数,作为我们测试的一部分,实验发现最优持续时间为 10 年。
此外,当人们开始“记住”并积累特定解,而不是在搜索空间的其它地方找到新的成功解时,生存期计数器可以帮助避免模型“过拟合”。限制个体的生存期令我们能够保持群落的多样性,并继续寻找更优解。
//—————————————————————————————————————————————————————————————————————————————— struct S_Agent { void Init (int coords) { ArrayResize (c, coords); f = -DBL_MAX; yearsNumber = 0; } double c []; //coordinates double f; //fitness int yearsNumber; }; //——————————————————————————————————————————————————————————————————————————————
在 “Init” 方法中,我们将通过子代数量来增加亲本群落的大小。这允许将亲本和子代一起排序,尽管就像在 (μ,λ)-ES 算法中一样,将来只有联合群落的 μ 部分将用于生成新的子代。虽然在以前的算法中,亲本的数量必须小于或等于后代的群落,但在该算法中,这无关紧要,亲本群落可以设置为任何大小,甚至非常大。这不会影响世代的数量。实验发现,在有 100 个后代的情况下,亲本群落 150 是最优值(随着世代数量的减少,不可能有更大的值)。亲本群落的进一步增加导致基因库的多样性过多,算法开始收敛得更糟(这本身就很有趣)。
ArrayResize (ind, popSize + parentsNumb); ArrayResize (val, popSize + parentsNumb); ArrayResize (pTemp, popSize + parentsNumb); ArrayResize (a, popSize); for (int i = 0; i < popSize; i++) a [i].Init (coords); ArrayResize (parents, popSize + parentsNumb); for (int i = 0; i < popSize + parentsNumb; i++) parents [i].Init (coords);
在 Moving 方法中,在创建新后代时将个体的年份计数器设置为 1。
a [i].yearsNumber = 1;
这些更改还影响了 Revision 方法,在该方法中,代码在考虑更改的情况下执行以下操作:
- 将每个亲本的 “yearsNumber” 值加 1。
- 如果 “yearsNumber” 的值超过规定的限制(寿命),则将对应亲本的适应度值 “f” 设置为 “-DBL_MAX”,这意味着将个体从群落中删除。
- 将新的子代数组从 “a” 数组复制到 “parents” 数组。
- 按 “f” 适应度值对 “parents” 数组进行排序。
//---------------------------------------------------------------------------- for (int i = 0; i < parentsNumb; i++) { parents [i].yearsNumber++; if (parents [i].yearsNumber > lifespan) { parents [i].f = - DBL_MAX; } } for (int i = parentsNumb; i < parentsNumb + popSize; i++) { parents [i] = a [i - parentsNumb]; } Sorting (parents, parentsNumb + popSize);
3. 替代测试函数
以前,我们调用 Rastrigin 函数作为测试函数来评估优化算法。然而,Rastrigin 函数并非此意图的完美选择。它具有严格的周期性,和平衡的最小值和最大值,某些算法可以相对容易地检测到。因此,Rastrigin 函数表现出的形态也许会影响算法判定函数极值的能力。
为了对优化算法进行更可靠和客观的测试,建议调用具有多样化和不可预测属性的函数。此类函数通常没有明显的形态,也没有最小值和最大值之间的平衡。此类函数的示例包括噪声函数、具有非线性依赖性的函数、或具有大量局部极值的函数。选择这种函数,令我们能够更准确地评估算法在各种条件下检测并收敛到全局最优的能力。
按照惯例,所有函数都可以分为“简单”和“复杂”。简单函数是指最大表面积位于 “max” 和 “min” 之间中线上方的函数,并且表面积越接近 “max”,优化算法就越简单。因此,如果我们简单地在函数域的整个表面上随机放置点,我们将得到“高”优化结果的错误印象,因为结果将接近绝对全局最大值。这种简单函数的一个例子是图例 1 中假设函数的示意图。
图例 1. 优化算法的“简单”函数示例
鉴于上述情况,Rastrigin 函数可以归类为一种简单函数,该函数可能会导致某些优化算法的结果夸大。这是由于这些算法的搜索策略的特殊性,它可以将其个体分散在整个函数表面。
对于具有大量变量(例如 1000)的 Rastrigin 函数,这种影响尤其明显。虽然一些算法“诚实地”试图找到全局极值,但其它算法也许只是简单地将个体均匀地放置在函数的整个表面。这种方法并不表示优化算法能够执行准确的搜索,而只是给人一种能够这样做的错觉。
Rastrigin 函数已进行了重大修改,为优化算法创建了更复杂、更具挑战性的环境。该函数的新版本增加了若干个“山丘”和“山谷”,同时保持了表面那部分的周期性,这无助于找到全球极值。这些变化会造成额外的障碍,分散注意力,并充当陷阱。
现在,我们不能只是跳到具有周期性的步骤,以求达到全局极值,就像在传统版本的 Rastrigin 中一样。此外,全局最优值已从边缘移开,因此在通常关注函数定义边界的算法中,如果出现伪影,则很难找到。
新函数称为 “Hilly”(图例 2)。与 “Forest” 和 “Megacity” 一样,它指的是复杂的测试函数。对于这三个函数,位于最大高度的 50% 以上的表面积大致相同,约占函数总面积的 20%。
Hilly、Forest 和 Megacity 函数提供了复杂且真实的优化场景,可以帮助评估算法在复杂和多样化条件下的性能。通过调用这些函数作为优化算法的综合测试,我们可以更深入地了解它们找到全局最优和克服局部陷阱的能力。
此外,还对测试方法进行了更改。现在,执行 10 轮测试而不是 5 轮(优化过程的重复运行次数),以减少结果中的随机“尖峰”。
图例 2. Hilly 测试函数
4. 测试结果
(μ,λ)-ES 算法测试台结果:
C_AO_(PO)ES:100:10:0.025:8.0
=============================
5 Hilly's; Func runs: 10000; result: 0.7902459324049909
25 Hilly's; Func runs: 10000; result: 0.6264667539839893
500 Hilly's; Func runs: 10000; result: 0.42934981087827656
=============================
5 Forest's; Func runs: 10000; result: 0.8761631782479373
25 Forest's; Func runs: 10000; result: 0.6094343681829253
500 Forest's; Func runs: 10000; result: 0.19591138782930953
=============================
5 Megacity's; Func runs: 10000; result: 0.5900000000000001
25 Megacity's; Func runs: 10000; result: 0.37933333333333336
500 Megacity's; Func runs: 10000; result: 0.11321666666666666
=============================
All score: 4.61012
(μ+λ)-ES 算法测试台结果:
C_AO_(P_O)ES:100:150:0.02:8.0:10
=============================
5 Hilly's; Func runs: 10000; result: 0.9993447297882565
25 Hilly's; Func runs: 10000; result: 0.9189524317647721
500 Hilly's; Func runs: 10000; result: 0.562968579605404
=============================
5 Forest's; Func runs: 10000; result: 1.0
25 Forest's; Func runs: 10000; result: 0.9352215748931851
500 Forest's; Func runs: 10000; result: 0.3917923122543615
=============================
5 Megacity's; Func runs: 10000; result: 0.8316666666666664
25 Megacity's; Func runs: 10000; result: 0.6443333333333332
500 Megacity's; Func runs: 10000; result: 0.21155000000000007
=============================
All score: 6.49583
(μ+λ)-ES 基于 Hilly 测试函数
(μ+λ)-ES 基于 Forest 测试函数
(μ+λ)-ES 基于 Megacity 测试函数
现在,当把新算法添加到表格中时,结果数字不会改变,因为它们是以绝对值表示的。
如此,我们转到所研究算法的结果,首先是 (μ+λ)-ES。该算法的惊人结果真的令我感到惊讶:它总共获得了理论上可能结果的 72.18%。为了确保这些令人印象深刻的结果,专门针对该算法进行了 20 轮测试。20 轮运行中的每一次都显示出 100% 收敛于复杂的 Forest 函数 — 这简直太巨大了!此外,其它函数的结果也令人瞩目。
现在关于 (μ,λ)-ES 的一些溢美之词。该算法表现出稳定和良好的结果。在彩色图形中,它是均匀的“绿色”,没有颜色突变。
# | AO | 说明 | Hilly | Hilly 最终 | Forest | Forest 最终 | Megacity (离散) | Megacity 最终 | 最终结果 | % of MAX | ||||||
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 | (P+O)ES | (P+O) 进化策略 | 0.99934 | 0.91895 | 0.56297 | 2.48127 | 1.00000 | 0.93522 | 0.39179 | 2.32701 | 0.83167 | 0.64433 | 0.21155 | 1.68755 | 6.496 | 72.18 |
2 | SDSm | 随机扩散搜索 M | 0.93066 | 0.85445 | 0.39476 | 2.17988 | 0.99983 | 0.89244 | 0.19619 | 2.08846 | 0.72333 | 0.61100 | 0.10670 | 1.44103 | 5.709 | 63.44 |
3 | SIA | 模拟各向同性退火 | 0.95784 | 0.84264 | 0.41465 | 2.21513 | 0.98239 | 0.79586 | 0.20507 | 1.98332 | 0.68667 | 0.49300 | 0.09053 | 1.27020 | 5.469 | 60.76 |
4 | DE | 差分进化 | 0.95044 | 0.61674 | 0.30308 | 1.87026 | 0.95317 | 0.78896 | 0.16652 | 1.90865 | 0.78667 | 0.36033 | 0.02953 | 1.17653 | 4.955 | 55.06 |
5 | HS | 谐声搜索 | 0.86509 | 0.68782 | 0.32527 | 1.87818 | 0.99999 | 0.68002 | 0.09590 | 1.77592 | 0.62000 | 0.42267 | 0.05458 | 1.09725 | 4.751 | 52.79 |
6 | SSG | 树苗播种和生长 | 0.77839 | 0.64925 | 0.39543 | 1.82308 | 0.85973 | 0.62467 | 0.17429 | 1.65869 | 0.64667 | 0.44133 | 0.10598 | 1.19398 | 4.676 | 51.95 |
7 | (PO)ES | (PO) 进化策略 | 0.79025 | 0.62647 | 0.42935 | 1.84606 | 0.87616 | 0.60943 | 0.19591 | 1.68151 | 0.59000 | 0.37933 | 0.11322 | 1.08255 | 4.610 | 51.22 |
8 | ACOm | 蚁群优化 M | 0.88190 | 0.66127 | 0.30377 | 1.84693 | 0.85873 | 0.58680 | 0.15051 | 1.59604 | 0.59667 | 0.37333 | 0.02472 | 0.99472 | 4.438 | 49.31 |
9 | MEC | 心智进化计算 | 0.69533 | 0.53376 | 0.32661 | 1.55569 | 0.72464 | 0.33036 | 0.07198 | 1.12698 | 0.52500 | 0.22000 | 0.04198 | 0.78698 | 3.470 | 38.55 |
10 | IWO | 入侵性杂草优化 | 0.72679 | 0.52256 | 0.33123 | 1.58058 | 0.70756 | 0.33955 | 0.07484 | 1.12196 | 0.42333 | 0.23067 | 0.04617 | 0.70017 | 3.403 | 37.81 |
11 | COAm | 布谷鸟优化算法 M | 0.75820 | 0.48652 | 0.31369 | 1.55841 | 0.74054 | 0.28051 | 0.05599 | 1.07704 | 0.50500 | 0.17467 | 0.03380 | 0.71347 | 3.349 | 37.21 |
12 | SDOm | 螺旋动力学优化 M | 0.74601 | 0.44623 | 0.29687 | 1.48912 | 0.70204 | 0.34678 | 0.10944 | 1.15826 | 0.42833 | 0.16767 | 0.03663 | 0.63263 | 3.280 | 36.44 |
13 | NMm | Nelder-Mead 方法 M | 0.73807 | 0.50598 | 0.31342 | 1.55747 | 0.63674 | 0.28302 | 0.08221 | 1.00197 | 0.44667 | 0.18667 | 0.04028 | 0.67362 | 3.233 | 35.92 |
14 | FAm | 萤火虫算法 M | 0.58634 | 0.47228 | 0.32276 | 1.38138 | 0.68467 | 0.37439 | 0.10908 | 1.16814 | 0.28667 | 0.16467 | 0.04722 | 0.49855 | 3.048 | 33.87 |
15 | GSA | 重力搜索算法 | 0.64757 | 0.49197 | 0.30062 | 1.44016 | 0.53962 | 0.36353 | 0.09945 | 1.00260 | 0.32667 | 0.12200 | 0.01917 | 0.46783 | 2.911 | 32.34 |
16 | ABC | 人工蜂群 | 0.63377 | 0.42402 | 0.30892 | 1.36671 | 0.55103 | 0.21874 | 0.05623 | 0.82600 | 0.34000 | 0.14200 | 0.03102 | 0.51302 | 2.706 | 30.06 |
17 | BFO | 细菌觅食优化 | 0.54626 | 0.43533 | 0.31907 | 1.30066 | 0.41626 | 0.23156 | 0.06266 | 0.71048 | 0.35500 | 0.15233 | 0.03627 | 0.54360 | 2.555 | 28.39 |
18 | BA | 蝙蝠算法 | 0.59761 | 0.45911 | 0.35242 | 1.40915 | 0.40321 | 0.19313 | 0.07175 | 0.66810 | 0.21000 | 0.10100 | 0.03517 | 0.34617 | 2.423 | 26.93 |
19 | SA | 模拟退火 | 0.55787 | 0.42177 | 0.31549 | 1.29513 | 0.34998 | 0.15259 | 0.05023 | 0.55280 | 0.31167 | 0.10033 | 0.02883 | 0.44083 | 2.289 | 25.43 |
20 | IWDm | 智能水滴 M | 0.54501 | 0.37897 | 0.30124 | 1.22522 | 0.46104 | 0.14704 | 0.04369 | 0.65177 | 0.25833 | 0.09700 | 0.02308 | 0.37842 | 2.255 | 25.06 |
21 | PSO | 粒子群优化 | 0.59726 | 0.36923 | 0.29928 | 1.26577 | 0.37237 | 0.16324 | 0.07010 | 0.60572 | 0.25667 | 0.08000 | 0.02157 | 0.35823 | 2.230 | 24.77 |
22 | MA | 猴子算法 | 0.59107 | 0.42681 | 0.31816 | 1.33604 | 0.31138 | 0.14069 | 0.06612 | 0.51819 | 0.22833 | 0.08567 | 0.02790 | 0.34190 | 2.196 | 24.40 |
23 | SFL | 蛙跳 | 0.53925 | 0.35816 | 0.29809 | 1.19551 | 0.37141 | 0.11427 | 0.04051 | 0.52618 | 0.27167 | 0.08667 | 0.02402 | 0.38235 | 2.104 | 23.38 |
24 | FSS | 鱼群搜索 | 0.55669 | 0.39992 | 0.31172 | 1.26833 | 0.31009 | 0.11889 | 0.04569 | 0.47467 | 0.21167 | 0.07633 | 0.02488 | 0.31288 | 2.056 | 22.84 |
25 | RND | 随机 | 0.52033 | 0.36068 | 0.30133 | 1.18234 | 0.31335 | 0.11787 | 0.04354 | 0.47476 | 0.25333 | 0.07933 | 0.02382 | 0.35648 | 2.014 | 22.37 |
26 | GWO | 灰狼优化器 | 0.59169 | 0.36561 | 0.29595 | 1.25326 | 0.24499 | 0.09047 | 0.03612 | 0.37158 | 0.27667 | 0.08567 | 0.02170 | 0.38403 | 2.009 | 22.32 |
27 | CSS | 收费系统搜索 | 0.44252 | 0.35454 | 0.35201 | 1.14907 | 0.24140 | 0.11345 | 0.06814 | 0.42299 | 0.18333 | 0.06300 | 0.02322 | 0.26955 | 1.842 | 20.46 |
28 | EM | 类电磁算法 | 0.46250 | 0.34594 | 0.32285 | 1.13129 | 0.21245 | 0.09783 | 0.10057 | 0.41085 | 0.15667 | 0.06033 | 0.02712 | 0.24412 | 1.786 | 19.85 |
图例 3. 算法的颜色渐变是根据相关测试
图例 4. 算法测试结果的直方图(标尺从 0 到 100,越多越好,
其中 100 是最大可能的理论结果(存档提供了一个用于计算评级表格的脚本)。
5. 总结
进化策略的运用为各个领域开辟了新的可能性,包括机器学习中的参数优化、机器人设计和复杂系统的控制。它们令我们能够基于进化的生物学原理获得更好的解决方案。
目前,我们在积分榜上有一位无可争议的新领导者,领先于其最接近的竞争对手 SDSm 近 10%。
(μ,λ)-ES 算法的优点和缺点:
- 少量外部参数。
- 高效解决各种问题。
- 易于实现。
- 抗粘连性。
- 在平滑和复杂的离散函数上都有可喜的结果。
- 高收敛性。
- 离散函数上的大量结果分散。
(μ+λ)-ES 算法的优点和缺点:
- 少量外部参数。
- 高效解决各种问题。
- 易于实现。
- 抗粘连性。
- 在平滑和复杂的离散函数上都有可喜的结果。
- 高收敛性。
- 离散函数上的结果大量分散(尽管这些是目前最好的结果)。
本文附有一个存档,其中包含前几篇文章中讲述的算法代码的当前更新版本。文章作者不对规范算法讲述的绝对准确性负责。对其中进行了多处修改,从而提升搜索能力。文章中表述的结论和论断是基于实验的结果。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/13923
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
This article was written by a user of the site and reflects their personal views. MetaQuotes Ltd is not responsible for the accuracy of the information presented, nor for any consequences resulting from the use of the solutions, strategies or recommendations described.




这是一个相当大的飞跃!
是的,出乎意料的飞跃。
我们可以把它归结为其中一个函数被替换了,但不,它仍然是 Rastrigin 的佼佼者。现在,测试的整体复杂度有所提高,一些算法的排名有所下降,而那些排名靠前的算法仍然保持在前列。