English Русский Español Deutsch 日本語 Português
preview
种群优化算法:社群进化(ESG)

种群优化算法:社群进化(ESG)

MetaTrader 5示例 | 1 十一月 2024, 09:54
507 0
Andrey Dik
Andrey Dik

内容

1. 概述
2. 算法
3. 测试结果


1. 概述

在优化领域,有范围广阔的种群算法,旨在寻找各种问题中的最优解。然而,尽管它们很重要,但多种群和多群体算法在我以前的文章中并未得到充分的涵盖。有鉴于此,我觉得有必要针对这个迷人而有前景的话题进行更详细的研究。

多种群算法基于多个独立种群来求解优化问题的思路。种群在逻辑上并行运作,可以交流有关最优解的信息,这样就令同时探索参数空间的不同区域并、并找到不同的最优值成为可能。另一方面,多群体算法使用许多互动份子的社群(群落),其也可以彼此合作,并交流达成最佳解的信息。

在本文中,我们将研究本文专门创建的多种群 ESG 算法。我们将研究该类算法的基本原理。此外,我们将研究比较研究的结果,这将令我们能够评估这些算法相比单种群优化方法的有效性。

2. 算法

多种群算法可以基于以下原理进行各种组合:

1. 社群。该算法并非针对单份子运作,而是那些通过合作和经验交流而联合的社群。每个群都有自己的决策中枢,以及当作优化个体的份子集合。群间互动、分享经验,并用相关最优解的信息来改善它们的结果。

2. 集体运动。社群内份子在参数空间中交互,并一起移动。这允许群体探索参数空间的不同区域,并分享有关寻找最优解的信息。

3. 局部和全局经验。每个社群都存储有关其中最优解(本地经验)的信息。在所有群(全局经验)中还有一个总体最佳分数。群体保留最佳解,分享经验,并用它们来改进结果。

4. 进化和经验交流。该算法会经历迭代,在此期间,社群会更新和分享经验。这是改进解的迭代,并寻求最优结果。

5. 自适性和多样性。通过互动和经验交流,群体可以自适应不断变化的条件,并寻找到各种最优解。该算法具有自适属性,令其能够有效地响应优化问题不断变化的条件和要求。群体可以自适新的条件,改变它们在参数空间中移动的策略,并基于经验更新它们的决策。这允许算法有效地搜索最优解,尤其是在问题条件随时间变化的情况下。

上面我们谈论了多种群算法的基本原理。现在我们来看看 ESG 搜索策略的特性。

假设我们有一个份子社会,我们称之为 “社群”。在这个群体中,某个行为模型(“中枢”)占主导地位,且该群体的份子追随这个模型,但有一定的偏差,其可用一定的分布律来描述。大多数份子略微偏离中枢,但在群体的影响区域内有些偏差很大,其边界由分布决定。当份子中出现更自适的行为形态时,它将成为群体的新中枢。因此,该群转向寻找份子行为的最稳定模型。

可以有若干个这样的群体,而且它们是独立的,所以可以称为多种群算法,在低层次上模拟社群中个体成员的行为,且在高层次上模拟群体的普遍行为。

鉴于这个概念,这样的状况很可能会出现在一些单独的群、甚或所有群同时停止它们的拓展,并陷入局部极值之时。为免遭此景,我们引入了“扩展社群的影响方圆”的概念。如果每次迭代毫无寸进,则扩展群边界,从而允许开拓新的搜索区域,并令种群及群体多样化。如果该群找到一个优于前值的解,则群边界半径将再次缩减到默认最小值。这有助于算法免于陷入局部陷阱,并在必要时强化对新区域的探索。增加半径也有助于社群的多样性。不同的群将探索参数空间的不同区域。

这种用于社群进化的多种群算法的概念看起来很有前途。然而,并非一切都像初看那么简单。该群中枢的当前位置也许在相应的坐标上处于不幸的位置,甚至扩大影响区域也未必有效。在这种情况下,我们可以说发生了 “对角线扩展” (就像在 ACO 算法中,蚂蚁只沿着它们的路径奔跑,不会跑偏),而实际上需要 “直角扩展”,或者确实也可能出现相反的状况。

若要克服上述问题,重点是确保在群之间转移成功的经验。为此目的,可以允许一些份子从“盟友”群的中枢借用一些思路。因此,中枢行为形态将影响其它群的单个份子。顺便说一句,影响不可能、也没必要是积极的。社群的行为模型如图例 1 所示制程。



ESG

图例 1. 算法操作。分离群,在缺乏进展的情况下扩展,在改善解的情况下收窄,

按 “p0” 份子(份子位于群索引 0 处)从相邻的 “Bt”(最佳团队)群中借用 “最佳思路”(坐/标)

ESG 算法的伪代码可以如下表示:

  1. 在搜索空间中随机放置群的中枢。
  2. 将群的份子围绕给定分布 * 的相应中心放置。
  3. 计算份子的适应度值。
  4. 更新全局解。
  5. 更新每个群的中枢。
  6. 如果中枢的位置并未改善,则扩大群边界,如果我们设法改善了位置,则减小群边界。
  7. 将群的份子围绕给定分布的相应中心放置。
  8. 将来自“盟友群”中枢的信息添加到每个群的一个份子中(份子从随机选择的盟友群中接收一组坐标)。
  9. 计算份子的适应度值。
  10. 从步骤 4 开始重复,直到满足停止准则。

* — 在 ESG 中,我使用分布幂律来表示群份子相对于中枢的分布。不过,也可用其它分布律,包括它们的策略独立部分逻辑的组合。该主题是开放的,可供试验。

我们转到代码回顾。为了描述一个社群,我们将编写 S_Group 结构,其中包含几个成员变量:

  • “cB” - 存储 “center” 坐标的值数组。
  • “fB” - 以 “-DBL_MAX” 初始化的中枢适应度函数。
  • “sSize” - 群大小。
  • “sRadius” - 群半径。

结构中的 Init 方法取两个参数:“coords” - 坐标的数量,和 “groupSize” - 群的大小。

//——————————————————————————————————————————————————————————————————————————————
struct S_Group
{
  void Init (int coords, int groupSize)
  {
    ArrayResize (cB, coords);
    fB          = -DBL_MAX;
    sSize       = groupSize;
  }

  double cB [];
  double fB;
  int    sSize;
  double sRadius;
};
//——————————————————————————————————————————————————————————————————————————————

所述搜索个体的简单结构也适用于 ESG 算法的逻辑。我决定在群描述字段中不包含个体份子的结构。每个群在访问其份子时都作为普通种群的一部分,这将允许保持从算法外部对个体的常规访问,同时避免不必要地复制群份子到个体。

S_Agent 结构的定义包含两个变量:

  • “c” - 个体坐标值的数组。
  • “f” - 以 “-DBL_MAX” 初始化的个体适应度值。

Init 方法取 “coords” 参数来调整 “c” 数组的大小。

//——————————————————————————————————————————————————————————————————————————————
struct S_Agent
{
  void Init (const int coords)
  {
    ArrayResize (c, coords);
    f = -DBL_MAX;
  }

  double c []; //coordinates
  double f;    //fitness
};
//——————————————————————————————————————————————————————————————————————————————

定义 C_AO_ESG 类,其中包含多个字段和方法:

1. 公开字段:

  • “cB” - 全局解的最佳坐标值数组。
  • “fB” — 最佳坐标的适应度值。
  • “a” - 表示个体的 S_Agent 类型对象数组。
  • “rangeMax” — 搜索数组范围的最大值。
  • "rangeMin" — 搜索数组范围的最小值。
  •  “rangeStep” - 搜索数组的步长值。

2. 方法:

  • “Init” - 初始化类成员变量的函数。接受参数:坐标数量、种群规模、群数量、初始群半径、群扩展因子、和分布度。
  • “Moving” - 该方法负责个体的移动。
  • “Revision” - 该方法负责个体的修订。
  • “SeInDiSp” - 按给定步长计算范围内数值的方法。
  • “RNDfromCI” - 按给定间生成随机数的方法。
  • “Scale” - 将数值从一个范围缩放到另一个范围的方法。
  • “PowerDistribution” - 根据幂律分布生成数值的方法。

3. 私密字段:

  • “coords” - 坐标的数量。
  • “popSize” - 种群规模。
  • “gr” - 表示群的 S_Group 类型对象数组。
  • “groups” - 群数量。
  • “groupRadius” - 群半径。
  • “expansionRatio” - 扩展比率。
  • “power” - 幂。
  •  “revision” - 指示需要修订的标志。
//——————————————————————————————————————————————————————————————————————————————
class C_AO_ESG
{
  //----------------------------------------------------------------------------
  public: double  cB [];       //best coordinates
  public: double  fB;          //FF of the best coordinates
  public: S_Agent a  [];       //agents

  public: double rangeMax  []; //maximum search range
  public: double rangeMin  []; //manimum search range
  public: double rangeStep []; //step search

  public: void Init (const int    coordinatesNumberP,   //coordinates number
                     const int    populationSizeP,      //population size
                     const int    groupsP,              //number of groups
                     const double groupRadiusP,         //group radius
                     const double expansionRatioP,      //expansion ratio
                     const double powerP);              //power

  public: void Moving   ();
  public: void Revision ();

  //----------------------------------------------------------------------------
  private: int     coords;
  private: int     popSize;          //population size
  private: S_Group gr [];            //group

  private: int    groups;            //number of groups
  private: double groupRadius;       //group radius
  private: double expansionRatio;    //expansion ratio
  private: double power;             //power

  private: bool   revision;

  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: double PowerDistribution (const double In, const double outMin, const double outMax, const double power);
};
//——————————————————————————————————————————————————————————————————————————————

类的 Init 方法基于所传递参数初始化类变量。除了变量的主要初始化和设置数组的大小之外,如果群数量不是种群规模的倍数,该方法还会计算每个群中的份子数量。

“partInSwarms” 数组的大小调整为 “groups”,其中 “groups” 是群的数量。然后,将变量 “particles” 设置为将 “popSize” 除以 “groups” 的结果,其中 “popSize” 是种群规模。“partInSwarms” 数组以数值 “particles” 填充,即没有余数的量。然后,通过从 “popSize” 中减去 “particles” 和 “groups” 的乘积来计算丢失元素的数量。如果有丢失的元素(“lost > 0”),那么在 'while' 循环中它们会在群中均匀分布。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ESG::Init (const int    coordinatesNumberP,   //coordinates number
                     const int    populationSizeP,      //population size
                     const int    groupsP,              //number of groups
                     const double groupRadiusP,         //group radius
                     const double expansionRatioP,      //expansion ratio
                     const double powerP)
{
  MathSrand ((int)GetMicrosecondCount ()); // reset of the generator
  fB       = -DBL_MAX;
  revision = false;

  coords         = coordinatesNumberP;
  popSize        = populationSizeP;
  groups         = groupsP;
  groupRadius    = groupRadiusP;
  expansionRatio = expansionRatioP;
  power          = powerP;

  //----------------------------------------------------------------------------
  int partInSwarms [];
  ArrayResize (partInSwarms, groups);

  int particles = popSize / groups;
  ArrayInitialize (partInSwarms, particles);

  int lost = popSize - particles * groups;

  if (lost > 0)
  {
    int pos = 0;

    while (true)
    {
      partInSwarms [pos]++;
      lost--;
      pos++;
      if (pos >= groups) pos = 0;
      if (lost == 0) break;
    }
  }

  //----------------------------------------------------------------------------
  ArrayResize (rangeMax,  coords);
  ArrayResize (rangeMin,  coords);
  ArrayResize (rangeStep, coords);
  ArrayResize (cB,        coords);

  ArrayResize (gr,        groups);
  for (int s = 0; s < groups; s++) gr [s].Init (coords, partInSwarms [s]);

  ArrayResize (a, popSize);
  for (int i = 0; i < popSize; i++) a [i].Init (coords);
}
//——————————————————————————————————————————————————————————————————————————————

Moving 方法用于在优化开始时生成群的中枢和个体。该方法执行以下操作:

  • 在外部 “for” 循环中为每个 “s” 群生成中枢。为此,嵌套的 “for” 循环为每个 “c” 坐标在给定范围内生成一个 “coordinate” 随机值。然后将 “coordinate” 值转换为所需的范围,并存储在 “gr[s].cB[c]” 数组之中。
  • 在外部 “for” 循环中为每个 “s” 群生成个体,以及逐个 “p” 个体。“radius” 的值是基于给定的参数,在嵌套的 “for” 循环中按群的当前状态计算得出。然后,通过调整相对于范围边界的 “radius” 来计算 “min” 和 “max” 值。然后调用 “PowerDistribution” 函数在给定范围内生成随机 “coordinate” 值。生成的 “coordinate” 值被转换并存储在 “a[cnt].c[c]” 数组之中。
  • 将 “revision” 标志设置为 “true”,从而指示正在生成中枢和个体。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_ESG::Moving ()
{
  if (!revision)
  {
    int    cnt        = 0;
    double coordinate = 0.0;
    double radius     = 0.0;
    double min        = 0.0;
    double max        = 0.0;

    //generate centers----------------------------------------------------------
    for (int s = 0; s < groups; s++)
    {
      gr [s].sRadius = groupRadius;

      for (int c = 0; c < coords; c++)
      {
        coordinate    = RNDfromCI (rangeMin [c], rangeMax [c]);
        gr [s].cB [c] = SeInDiSp (coordinate, rangeMin [c], rangeMax [c], rangeStep [c]);
      }
    }

    //generate individuals of groups--------------------------------------------
    for (int s = 0; s < groups; s++)
    {
      for (int p = 0; p < gr [s].sSize; p++)
      {
        for (int c = 0; c < coords; c++)
        {
          radius = (rangeMax [c] - rangeMin [c]) * gr [s].sRadius;
          min    = gr [s].cB [c] - radius;
          max    = gr [s].cB [c] + radius;

          if (min < rangeMin [c]) min = rangeMin [c];
          if (max > rangeMax [c]) max = rangeMax [c];

          coordinate    = PowerDistribution (gr [s].cB [c], min, max, power);
          a [cnt].c [c] = SeInDiSp (coordinate, rangeMin [c], rangeMax [c], rangeStep [c]);
        }

        cnt++;
      }
    }

    revision = true;
  }
}
//——————————————————————————————————————————————————————————————————————————————

生成新份子的主要动作发生在 “Revision” 方法中,其会更最佳全局解,生成新的群个体,并通过将信息从 “盟友 ”群的中枢转移到一个份子,完成在群之间交流经验。因此,一个群中只有一个份子被允许从其它群中借用经验。该方法执行以下操作:

  • 更新全局解。在 “for” 循环中,遍历所有个体,并检查当前个体的适应度函数的值是否超过了当前最佳值。然后更新最佳值,并将当前个体的坐标数组复制到最佳解的坐标数组当中。
  • 生成新的群个体。在 “for” 循环中,遍历所有群及其个体。半径以及每个群的最小和最大坐标值则在嵌套循环中计算。然后调用 “PowerDistribution” 函数生成随机坐标值,并将结果存储在个体坐标数组之中。
  • 群之间的经验交流。在 “for” 循环中,遍历所有群。在嵌套的 “for” 循环中,会生成一个随机值,用于判定与哪个群交流经验。然后,取所选群的坐标值更新当前群中个体的坐标值。
//——————————————————————————————————————————————————————————————————————————————
void C_AO_ESG::Revision ()
{
  //----------------------------------------------------------------------------
  //update the best global solution
  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > fB)
    {
      fB = a [i].f;
      ArrayCopy (cB, a [i].c, 0, 0, WHOLE_ARRAY);
    }
  }

  //----------------------------------------------------------------------------
  int cnt = 0;
  bool impr = false;

  for (int s = 0; s < groups; s++)
  {
    impr = false;

    for (int p = 0; p < gr [s].sSize; p++)
    {
      if (a [cnt].f > gr [s].fB)
      {
        gr [s].fB = a [cnt].f;
        ArrayCopy (gr [s].cB, a [cnt].c, 0, 0, WHOLE_ARRAY);
        impr = true;
      }

      cnt++;
    }

    if (!impr) gr [s].sRadius *= expansionRatio;
    else       gr [s].sRadius  = groupRadius;

    if (gr [s].sRadius > 0.5) gr [s].sRadius = 0.5;
  }

  //generate individuals of groups----------------------------------------------
  double coordinate = 0.0;
  double radius     = 0.0;
  double min        = 0.0;
  double max        = 0.0;
  cnt = 0;

  for (int s = 0; s < groups; s++)
  {
    for (int p = 0; p < gr [s].sSize; p++)
    {
      for (int c = 0; c < coords; c++)
      {
        if (RNDfromCI (0.0, 1.0) < 1.0)
        {
        radius = (rangeMax [c] - rangeMin [c]) * gr [s].sRadius;
        min    = gr [s].cB [c] - radius;
        max    = gr [s].cB [c] + radius;

        if (min < rangeMin [c]) min = rangeMin [c];
        if (max > rangeMax [c]) max = rangeMax [c];

        coordinate    = PowerDistribution (gr [s].cB [c], min, max, power);
        a [cnt].c [c] = SeInDiSp (coordinate, rangeMin [c], rangeMax [c], rangeStep [c]);
        }
      }

      cnt++;
    }
  }

  //exchange of experience----------------------------------------------------------------
  cnt = 0;

  for (int s = 0; s < groups; s++)
  {
    for (int c = 0; c < coords; c++)
    {
      int posSw = (int)RNDfromCI (0, groups);
      if (posSw >= groups) posSw = groups - 1;

      //if (sw [posSw].fB > sw [s].fB)
      {
        a [cnt].c [c] = gr [posSw].cB [c];
      }
    }

    cnt += gr [s].sSize;
  }
}
//——————————————————————————————————————————————————————————————————————————————

在编写了如上讲述的主要 ESG 算法之后,我决定进行更改,并允许不同群的份子交流信息,以便提高算法的组合品质。为此,我们必须对个体结构进行修改。我们需要额外的字段:“cMain” - 主坐标,和 “fMain” - 主经验。

//——————————————————————————————————————————————————————————————————————————————
struct S_Agent
{
  void Init (const int coords)
  {
    ArrayResize (c,     coords);
    ArrayResize (cMain, coords);
    f     = -DBL_MAX;
    fMain = -DBL_MAX;
  }

  double c     []; //coordinates
  double cMain []; //coordinates
  double f;        //fitness
  double fMain;    //fitness
};
//——————————————————————————————————————————————————————————————————————————————

两个选项之间的区别在于针对 “Revision” 方法所做的修改:

1. 在主版本中,个体之间的经验交流是在群层面运作的。在内部 “for” 循环中,选择一个随机群,并将当前个体的坐标值替换为所选群中的中枢坐标值。因此,群在交换经验时,把经验转移到相应群中的唯一份子。

2. 在第二种个选项中,个体之间的经验交流是在整个种群的层面上运作的,此即,在群的份子之间,如果所选份子具有更高的适应性,则才会交流。因此,在群之间,只有最佳份子才能将经验传递给最差的份子。在内部 “for” 循环中,选择一个随机个体,并以一定的概率(由 “copyProb” 值确定),将当前个体的坐标值替换为群中所选个体的坐标值。

此外,第二个选项还有一个额外的代码模块,用于更新个体。如果当前个体的适应度函数值大于其先前的最佳值(f > fMain),则当前个体的坐标值将更新为其当前最佳解(cMain)的值。这允许个体保存并在以后使用它们的最佳决策。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_ESG::Revision ()
{
  //----------------------------------------------------------------------------
  //Update the best global solution
  for (int i = 0; i < popSize; i++)
  {
    if (a [i].f > fB)
    {
      fB = a [i].f;
      ArrayCopy (cB, a [i].c, 0, 0, WHOLE_ARRAY);
    }
  }

  //----------------------------------------------------------------------------
  //update agents
  for (int p = 0; p < popSize; p++)
  {
    if (a [p].f > a [p].fMain)
    {
      a [p].fMain = a [p].f;
      ArrayCopy (a [p].cMain, a [p].c, 0, 0, WHOLE_ARRAY);
    }
  }

  //----------------------------------------------------------------------------
  int cnt = 0;
  bool impr = false;

  for (int s = 0; s < groups; s++)
  {
    impr = false;

    for (int p = 0; p < gr [s].sSize; p++)
    {
      if (a [cnt].f > gr [s].fB)
      {
        gr [s].fB = a [cnt].f;
        ArrayCopy (gr [s].cB, a [cnt].c, 0, 0, WHOLE_ARRAY);
        impr = true;
      }

      cnt++;
    }

    if (!impr) gr [s].sRadius *= expansionRatio;
    else       gr [s].sRadius  = groupRadius;

    if (gr [s].sRadius > 0.5) gr [s].sRadius = 0.5;
  }

  //generate individuals of groups----------------------------------------------
  double coordinate = 0.0;
  double radius     = 0.0;
  double min        = 0.0;
  double max        = 0.0;
  cnt = 0;

  for (int s = 0; s < groups; s++)
  {
    for (int p = 0; p < gr [s].sSize; p++)
    {
      for (int c = 0; c < coords; c++)
      {
        if (RNDfromCI (0.0, 1.0) < 0.6)
        {
        radius        = (rangeMax [c] - rangeMin [c]) * gr [s].sRadius;
        min           = gr [s].cB [c] - radius;
        max           = gr [s].cB [c] + radius;

        if (min < rangeMin [c]) min = rangeMin [c];
        if (max > rangeMax [c]) max = rangeMax [c];

        coordinate    = PowerDistribution (gr [s].cB [c], min, max, power);
        a [cnt].c [c] = SeInDiSp (coordinate, rangeMin [c], rangeMax [c], rangeStep [c]);
        }
      }

      cnt++;
    }
  }

  //exchange of experience----------------------------------------------------------------
  cnt = 0;

  for (int p = 0; p < popSize; p++)
  {
    for (int c = 0; c < coords; c++)
    {
      int pos = (int)RNDfromCI (0, popSize);
      if (pos >= popSize) pos = popSize - 1;

      if (RNDfromCI(0.0, 1.0) < copyProb)
      {
        if (a [pos].fMain > a [p].fMain)
        {
          a [p].c [c] = a [pos].cMain [c];
        }
      }
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

作为算法第二版的实验和测试结果,总体结果并没有带来预期的进展,并且略有恶化。这可以通过以下事实来解释:重点是将份子的经验保持在它们自己的群的边界内,且不允许群之间彻底混合思路。应保留每个群的独特经验,并且只应确保部分经验交流。

实验的失败不是最终的,并不意味着算法的改进是不可能的。这只是一次尝试,让我们了解哪些方面值得关注,以及哪些策略最适合应用。通过进一步的研究和开发,获得的知识可用于创建算法的新变体,从而显著改进搜索能力。重要的是,在实现既定目标时,保持乐观和坚定。测试结果如下所示。


3. 测试结果

ESG 主要版本测试台结果:

C_AO_ESG|200|100|0.1|2.0|10.0
=============================
5 Hilly's; Func runs: 10000; result: 0.9990564816911227
25 Hilly's; Func runs: 10000; result: 0.7965424362150277
500 Hilly's; Func runs: 10000; result: 0.35055904999599663
=============================
5 Forest's; Func runs: 10000; result: 1.0
25 Forest's; Func runs: 10000; result: 0.8286255415345216
500 Forest's; Func runs: 10000; result: 0.13102081222227177
=============================
5 Megacity's; Func runs: 10000; result: 0.8233333333333333
25 Megacity's; Func runs: 10000; result: 0.5529999999999999
500 Megacity's; Func runs: 10000; result: 0.04724999999999998
=============================
All score: 5.52939 (61.44%)

略微修改的 ESG 版本测试台结果:


C_AO_MPSO|200|100|0.1|1.1|10.0|1.0
=============================
5 Hilly's; Func runs: 10000; result: 0.9986983861349696
25 Hilly's; Func runs: 10000; result: 0.7971379560351051
500 Hilly's; Func runs: 10000; result: 0.3351159723676586
=============================
5 Forest's; Func runs: 10000; result: 1.0
25 Forest's; Func runs: 10000; result: 0.8288612676775615
500 Forest's; Func runs: 10000; result: 0.11374411604788078
=============================
5 Megacity's; Func runs: 10000; result: 0.8333333333333333
25 Megacity's; Func runs: 10000; result: 0.5116666666666667
500 Megacity's; Func runs: 10000; result: 0.049316666666666654
=============================
All score: 5.46787 (60.75%)

我们可以看到算法的主要版本具有良好的收敛性。在测试函数 Hilly 和 Forest 上,在收敛图上可以看到轨迹中的轻微散射。不过,在 Megacity 函数上,这种分散相当大,尽管据此测试函数的大多数算法也显示出广泛的收敛散射。与早前表述的大多数算法不同,该算法“首选”更大种群规模 - 200(一般只用 50),尽管实际上局次数量成比例减少。ESG 在局部极值下工作良好。此属性受多种群算法 “本性” 的影响。

Hilly

  ESG 依据 Hilly 测试函数

Forest

  ESG 依据 Forest 测试函数

Megacity

  ESG 依据 Megacity 测试函数


ESG 算法展现出不错的结果,在排位表中名列前茅。可以注意到,具有 10 个参数的 Forest 函数收敛为 100%,并且几乎完全收敛;具有 10 个参数的 Hilly 函数收敛为 99.9%。该表包含算法主版本的结果,而实验版本位于 “variant2” 文件夹当中。

# AO 说明 Hilly Hilly 最终 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 BGA 二进制遗传算法 0.99992 0.99484 0.50483 2.49959 1.00000 0.99975 0.32054 2.32029 0.90667 0.96400 0.23035 2.10102 6.921 76.90
2 (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
3 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
4 ESG 社群进化 0.99906 0.79654 0.35056 2.14616 1.00000 0.82863 0.13102 1.95965 0.82333 0.55300 0.04725 1.42358 5.529 61.44
5 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
6 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
7 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
8 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
9 (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
10 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
11 BFO-GA 细菌觅食优化 - ga 0.89150 0.55111 0.31529 1.75790 0.96982 0.39612 0.06305 1.42899 0.72667 0.27500 0.03525 1.03692 4.224 46.93
12 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
13 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
14 Micro-AIS 微人工免疫系统 0.79547 0.51922 0.30861 1.62330 0.72956 0.36879 0.09398 1.19233 0.37667 0.15867 0.02802 0.56335 3.379 37.54
15 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
16 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
17 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
18 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
19 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
20 BFO 细菌觅食优化 0.61171 0.43270 0.31318 1.35759 0.54410 0.21511 0.05676 0.81597 0.42167 0.13800 0.03195 0.59162 2.765 30.72
21 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
22 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
23 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
24 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
25 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
26 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
27 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
28 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
29 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
30 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
31 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
32 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


总结

综上所述,社群进化算法是一种基于群体间合作和经验分享的有效优化方法。它具有适应性强、多样性、等特性,能够在各种优化问题中找到最优解。

我可以推荐 ESG 算法用于需要优化参数的各个领域。例如,它可用于优化机器学习中的超参数、优化最优控制问题中的函数、解决组合优化问题、以及需要查找最优参数值的其它问题。

所表述的算法可以视作一种模板,可以辅以之前文章中讲述的各种独立技术和搜索策略。此外,每个群都可用单独的优化算法,例如 PSO、ABC、ACO、等等。因此,ESG 算法的架构令实现该类优化方法,以及配合使用变得容易,分别结合了每种算法的优点。

需要强调的是,ESG 是一个独立的解决方案,效果很好,是解决复杂问题的一种极其灵活的方式。它的全部潜力可以通过实验和发展核心思想来释放,而这种实验的机会向所有人开放。

排位表格

图例 2. 算法颜色渐变是根据相关测试,而大于或等于 0.99 的结果,会以白色高亮显示

图表

图例 3. 算法测试结果的直方图(标尺从 0 到 100,越多越好,

其中 100 是理论上的最大可能结果(存档提供了一个计算排位表格的脚本)。


ESG 的优点和缺点:

优势:

  1. 简单架构。
  2. 高收敛性。
  3. 对计算资源要求不高。

缺点:

  1. 在具有大量参数的函数上结果不佳。

本文附有一个存档,其中包含前几篇文章中讲述的算法代码的当前更新版本。文章作者不对规范算法讲述的绝对准确性负责。它们当中进行了多处修改,从而提升搜索能力。文章中表述的结论和论断是基于实验的结果。

本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/14136

附加的文件 |
开发多币种 EA 交易 (第 5 部分):可变仓位大小 开发多币种 EA 交易 (第 5 部分):可变仓位大小
在前面的部分中,我们正在开发的智能交易系统 (EA) 只能使用固定的仓位大小进行交易。这对于测试来说是可以接受的,但在真实账户交易时并不建议这样做。让我们能够使用可变的仓位大小进行交易。
克服集成ONNX(Open Neural Network Exchange )的挑战 克服集成ONNX(Open Neural Network Exchange )的挑战
ONNX是集成不同平台间复杂AI代码的强大工具,尽管它非常出色,但要想充分发挥其作用,就必须解决一些伴随而来的挑战。在本文中,我们将讨论您可能会遇到的一些常见问题,以及如何处理这些问题。
种群优化算法:鲸鱼优化算法(WOA) 种群优化算法:鲸鱼优化算法(WOA)
鲸鱼优化算法(WOA)是一种受座头鲸行为和捕食策略启发的元启发式算法。该算法的核心思想在于模仿所谓的“气泡网”捕食方法,即鲸鱼在猎物周围制造气泡,然后以螺旋运动的方式攻击猎物。
MQL5 中的高级变量和数据类型 MQL5 中的高级变量和数据类型
不仅在 MQL5 编程中,在任何编程语言中,变量和数据类型都是非常重要的主题。MQL5 变量和数据类型可分为简单类型和高级类型。在这篇文章中,我们将识别并学习高级类型,因为我们在前一篇文章中已经提到过简单类型。