English Русский Português
preview
算术优化算法(AOA):从AOA到SOA(简单优化算法)

算术优化算法(AOA):从AOA到SOA(简单优化算法)

MetaTrader 5测试者 |
45 0
Andrey Dik
Andrey Dik

内容

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


概述

算术优化算法(AOA)是一种基于简单算术运算(如加法、减法、乘法和除法)的原创方法。其核心在于利用这些基本的数学原理来为各种问题寻找最优解。AOA由包括Laith Abualigah在内的一组研究人员开发,并于2021年首次提出。该算法属于元启发式方法(高级算法)类别,旨在针对复杂优化问题(在这些问题上,基于准确性的方法可能无效或不可行)在合理时间内找到、生成并概率性地从多个启发式方法中选择出能提供高质量解的方法。

这种方法因其简单性且同时巧妙地运用了基础的算术运算符,从而引起了我的兴趣。这些基本数学运算与元启发式方法的结合产生了协同效应,使得能够解决复杂的优化问题。AOA中使用的元启发式方法包括几个关键原则:

1. 种群方法。AOA使用一个解种群,这使其能够覆盖更广泛的潜在解空间。这样有助于避免陷入局部最优解,并扩大了搜索范围。

2. 无序性和随机性。在搜索中引入随机性元素有助于算法避免陷入局部最优解,并提供对解空间的更全面探索,从而增加了找到全局最优解的概率。

3. 探索与利用之间的平衡。与许多其他元启发式算法一样,AOA力求在探索解空间的新区域和利用已知的有效解之间取得平衡。这是通过使用算术运算来更新解的位置来实现的。

因此,AOA是元启发式算法的一个典型的例子,它有效地利用了种群方法、随机性以及探索与利用之间的平衡原则来解决优化问题。然而,我们将在实现并测试该算法后,具体讨论其在复杂和多维空间中寻找最优解的效率。


算法实现

AOA的基本思想是利用算术运算符的分配行为来寻找最优解。该算法的特点是原理简单、参数数量不多且易于实现。该算法利用了数学中四种基本算术运算符的分布特性,即:乘法(Mε × ε)、除法(Dε ÷ ε)、减法(Sε − ε)和加法(Aε + ε)。在AOA中,初始种群在[U; L]范围内随机生成,其中目标函数的搜索空间的上限和下限分别用U和L表示,使用以下方程:

x = L + (U − L) × δ, 其中x表示种群解,δ是一个取值范围在[0, 1]内的随机变量。

在每次迭代中,探索与利用策略的选择,即选择两组运算符中的一组(除法;乘法)或(减法;加法),取决于MoA(数学优化器加速)函数的结果,该函数本质上是一个计算出的概率值,并随每次迭代而变化,其计算方程为:

MoA(t) = Min + t × (Max − Min) ÷ Maxt,其中MoA(t)是第t次迭代时的函数结果,t表示当前迭代次数,范围在1到最大迭代次数(Maxt)之间。MoA的最小可能值用Min表示,最大值用Max表示。这些是算法的外部参数。

所有四个算术运算符方程都使用MoP(数学优化器)因子,其计算如下:

MoP(t) = 1 − (t ÷ Maxt)^(1 ÷ θ),其中MoP(t)表示第t次迭代时MoP函数的值。θ是一个控制迭代过程中利用性能的关键参数。在原始工作中,算法的作者将其设置为5。

下图1显示了MoA和MoP随当前迭代变化的图形。这些图形表明,随着每次迭代,MoA线性增加,这意味着选择(减法;加法)运算符组的概率增加,而选择(除法;乘法)运算符组的概率相应降低。反过来,MoP比率非线性降低,从而减少了种群中智能体当前位置的下一个增量,这意味着在优化过程中决策的细化程度增加。

MoA与MoP

图例1. 紫色表示MoA概率图形,绿色表示MoP比率图形。

如果满足MoA概率,AOA中的研究或全局搜索 将使用基于除法(D)和乘法(M)运算符的搜索策略进行,该策略表述如下,其中以下运算符以相等的概率执行:

xi,j(t+1) = best(xj) ÷ (MoPr + 𝜖) × ((Uj − Lj) × 𝜇 + Lj),如果rand2 < 0.5; 

否则:

xi,j(t+1) = best(xj) × (MoPr) × ((Uj − Lj) × 𝜇 + Lj),其中xi(t+1)表示第(t+1)次迭代时的第i个解,x(i,j)(t)表示当前代中第i个个体的第j个位置,best(xj)表示当前最佳解的第j个位置,ε是一个小的正数,第j个位置值的上限和下限分别用Uj和Lj表示。控制参数μ设置为0.5。 

如果不满足MoA概率,则在AOA中执行利用策略(解细化)。该策略是使用减法(S)或加法(A)运算符开发的。在这里,μ也是一个常数,根据作者的意图固定为0.5。 

xi,j(t+1) = best(xj) − (MoPr) × ((Uj − Lj) × 𝜇 + Lj),如果rand3 < 0.5 

否则,xi,j(t+1) = best(xj) + (MoPr) × ((Uj − Lj) × 𝜇 + Lj)。

在AOA中,参数𝜇和θ非常重要,因为它们参与了探索与利用之间的权衡平衡。保持探索与利用的良好平衡通常是一项极具挑战性的任务。在原始AOA中,𝜇的值在探索和利用时均固定为0.5。然而,影响迭代过程中操作效率的θ参数设置为5。作者对𝜇和θ的不同值进行了实验,发现对于不同维度的单峰和多峰测试函数,𝜇 = 0.5和θ = 5通常能产生最佳结果。 

现在,让我们来实现AOA算法的伪代码:

将迭代次数(epoch数量)增加1

// 开始初始化
如果是首次启动
对于种群中的每个个体:
        对于每个坐标:
在允许范围内设置一个随机位置
将位置调整为离散值
标记初始化已完成
结束函数
结束条件判断

// 主优化过程
计算MoA = minMoA + EpochNumber * ((maxMoA - minMoА) / totalEpochs)
计算MoP = 1 - (EpochNumber / totalEpochs)^(1/θ)

// 解决方案空间探索阶段
对于种群中的每个个体:
    对于每个坐标:
生成三个随机值(rand1、rand2、rand3)
获取该坐标的已知最佳值
        
如果rand1 < MoAc
如果rand2 > 0.5
使用除法更新位置
否则:
使用乘法更新位置

结束条件判断
除此之外:
  如果rand3 > 0.5
使用减法更新位置
否则:
使用加法更新位置

结束条件判断
结束条件判断
        
将新位置调整为可接受的离散值
        
更新最优解

现在,我们继续编写代码。C_AO_AOA类是AOA算法的一种实现,旨在使用基于算术运算的方法解决优化问题。公有方法:

1. SetParams ()方法:从params数组中设置参数值。该方法允许在算法初始化后更改算法参数。

2. Init ()方法:

  • 通过获取最小和最大搜索范围、搜索步长和迭代次数来初始化算法。 
  • 如果初始化成功,返回true,否则返回false

3. Moving ()方法:在解决方案空间中移动个体。该方法根据给定参数和当前状态实现更新个体位置的逻辑。

4. Revision()方法:修改个体的当前位置,更新找到的函数最佳值以及对应个体的坐标。

私有字段,类参数:

  • minT — MoA概率的最小值。
  • maxT — MoA概率的最大值。
  • θ — 影响平衡探索与利用的参数。
  • μ — 用于控制个体位置变化(移动范围)的参数。
  • ϵ — 用于防止除零的小数。

算法状态信息:

  • epochs — 算法将经历的总迭代次数。
  • epochNow — 当前迭代次数,用于跟踪算法进度,影响MoA概率和MoP比率。

C_AO_AOA类实现了AOA算法的主要组件,包括初始化、粒子移动和修改。

//——————————————————————————————————————————————————————————————————————————————
class C_AO_AOA : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_AOA () { }
  C_AO_AOA ()
  {
    ao_name = "AOA";
    ao_desc = "Arithmetic Optimization Algorithm";
    ao_link = "https://www.mql5.com/en/articles/16364";

    popSize = 50;   // Population size
    minT    = 0.1;  // Minimum T value
    maxT    = 0.9;  // Maximum T value
    θ       = 10;   // θ parameter
    μ       = 0.01; // μ parameter

    ArrayResize (params, 5); // Resize the parameter array

    // Initialize parameters
    params [0].name = "popSize"; params [0].val = popSize;
    params [1].name = "minT";    params [1].val = minT;
    params [2].name = "maxT";    params [2].val = maxT;
    params [3].name = "θ";       params [3].val = θ;
    params [4].name = "μ";       params [4].val = μ;
  }

  void SetParams () // Method for setting parameters
  {
    popSize = (int)params [0].val; // Set population size
    minT    = params      [1].val; // Set minimum T
    maxT    = params      [2].val; // Set maximum T
    θ       = params      [3].val; // Set θ
    μ       = params      [4].val; // Set μ
  }

  bool Init (const double &rangeMinP  [], // Minimum search range
             const double &rangeMaxP  [], // Maximum search range
             const double &rangeStepP [], // Search step
             const int     epochsP = 0);  // Number of epochs

  void Moving   (); // Method of moving particles
  void Revision (); // Revision method

  //----------------------------------------------------------------------------
  double minT; // Minimum T value
  double maxT; // Maximum T value
  double θ;    // θ parameter
  double μ;    // μ parameter
  double ϵ;    // Parameter to prevent division by zero

  private: //-------------------------------------------------------------------
  int epochs;    // Total number of epochs
  int epochNow;  // Current epoch
};
//——————————————————————————————————————————————————————————————————————————————

C_AO_AOA类的Init方法负责通过设置搜索范围、步长以及将执行优化的迭代次数(epoch数)等参数,来初始化优化算法。方法逻辑:

1. 该方法首先调用StandardInit,对算法的标准参数进行初始化。如果此次初始化失败,Init方法将立即终止执行并返回false

2. 参数设置界面

  • 根据传入的epochsP参数设置总epochs(迭代次数)。
  • 将当前epochNow(当前迭代次数)初始化为0
  • ϵ(用于防止除0的小数值)设置为DBL_EPSILON,这是双精度浮点类型所能表示的最小正数的标准值。

3. 如果所有步骤均成功完成,该方法将返回true,表示算法已成功初始化。

Init方法是准备算法执行的重要环节,因为它设置了优化过程中将使用的基本参数。调用此方法会将所有参数和变量重置为初始状态。

//——————————————————————————————————————————————————————————————————————————————
bool C_AO_AOA::Init (const double &rangeMinP  [], // Minimum search range
                     const double &rangeMaxP  [], // Maximum search range
                     const double &rangeStepP [], // Search step
                     const int     epochsP = 0)   // Number of epochs
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; // Initialization of standard parameters

  //----------------------------------------------------------------------------
  epochs   = epochsP;     // Set the total number of epochs
  epochNow = 0;           // Initialize the current epoch
  ϵ        = DBL_EPSILON; // Set ϵ

  return true;            // Return 'true' if initialization was successful
}
//——————————————————————————————————————————————————————————————————————————————

Moving方法负责在AOA(算术优化算法)中实现个体在解空间内的移动。基于当前状态和算法参数,实现了更新个体位置的基本逻辑。方法逻辑:

1. 将epochNow(当前迭代次数)加1,以表明已进入新的优化阶段。

2. 初始随机定位:如果尚未进行任何更新(修订),则为每个粒子在给定的rangeMin(最小范围)和rangeMax(最大范围)内生成的随机位置。然后,使用指定的步长,通过SeInDiSp方法对每个位置进行离散化处理。

3. 根据当前迭代次数和指定参数计算MoAc (算术优化控制参数)和MoPr (算术优化概率参数)。这些值决定了用于更新个体位置的概率。

4. 探索阶段。对于每个个体和每个坐标,根据随机值和计算出的参数更新位置。位置可以使用各种运算符(除法和乘法)以及概率条件进行更新。

5. 更新后,同样使用SeInDiSp方法将位置转换为离散值。

//——————————————————————————————————————————————————————————————————————————————
// Particle displacement method
void C_AO_AOA::Moving ()
{
  epochNow++; // Increase the current epoch number

  // Initial random positioning
  if (!revision) // If there has not been a revision yet 
  {
    for (int i = 0; i < popSize; i++) // For each particle
    {
      for (int c = 0; c < coords; c++) // For each coordinate
      {
        a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);                             // Generate random position
        a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); // Convert to discrete values
      }
    }

    revision = true; // Set revision flag
    return;          // Exit the method
  }

  //----------------------------------------------------------------------------
  double MoAc = minT + epochNow * ((maxT - minT) / epochs); // Calculate the MoAc value
  double MoPr = 1.0 - pow (epochNow / epochs, (1.0 / θ));   // Calculate the MoPr value
  double best = 0.0;                                        // Variable to store the best value

  // Research phase using Division (D) and Multiplication (M) operators
  for (int i = 0; i < popSize; i++) // For each particle
  {
    for (int c = 0; c < coords; c++) // For each coordinate
    {
      double rand1 = u.RNDprobab (); // Generate a random value
      double rand2 = u.RNDprobab (); // Generate a random value
      double rand3 = u.RNDprobab (); // Generate a random value

      best = cB [c];                 // Save the current best value

      if (rand1 < MoAc)              // If random value is less than MoAc
      {
        if (rand2 > 0.5)             // If random value is greater than 0.5
        {
          a [i].c [c] = best / (MoPr + ϵ) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]); // Update particle position
        }
        else
        {
          a [i].c [c] = best * (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
      }
      else // If random value is greater than or equal to MoAc
      {
        if (rand3 > 0.5) // If random value is greater than 0.5
        {
          a [i].c [c] = best - (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
        else
        {
          a [i].c [c] = best + (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
      }

      a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);       // Convert to discrete values
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

C_AO_AOA类中,Revision方法用于更新种群中最优个体的相关信息。该方法遍历所有个体,将它们的函数值与当前最优值进行比较,若发现更优的值,则更新该最优值并保存对应个体的索引。随后,将最优个体的坐标复制到cB数组中。

//——————————————————————————————————————————————————————————————————————————————
void C_AO_AOA::Revision ()
{
  int ind = -1;                     // Index to store the best particle

  for (int i = 0; i < popSize; i++) // For each particle
  {
    if (a [i].f > fB)               // If the function value is better than the current best one
    {
      fB = a [i].f;                 // Update the best value of the function
      ind = i;                      // Save the index of the best particle
    }
  }

  if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY); // Copy the coordinates of the best particle
}
//——————————————————————————————————————————————————————————————————————————————

C_AO_Utilities类的SeInDiSp方法用于将输入值In限制在指定步长Step的[InMin, InMax]范围内。

1. 若In小于或等于 InMin,则返回InMin
2. 若In大于或等于InMax,则返回InMax
3. 若Step等于0,则返回In的原始值。
4. 否则,将值四舍五入到(In - InMin) / Step,并返回考虑步长后调整至该范围内的值。

double C_AO_Utilities :: SeInDiSp (double In, double InMin, double InMax, double Step)
{
  if (In <= InMin) return (InMin);
  if (In >= InMax) return (InMax);
  if (Step == 0.0) return (In);
  else return (InMin + Step * (double)MathRound ((In - InMin) / Step));
}


测试结果

AOA算法相当简单,让我们来看一下它在测试任务上的表现。

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|0.01|
=============================
5 Hilly's; Func runs: 10000; result: 0.3914957505847635
25 Hilly's; Func runs: 10000; result: 0.27733670012505607
500 Hilly's; Func runs: 10000; result: 0.2514517003089684
=============================
5 Forest's; Func runs: 10000; result: 0.23495704012464264
25 Forest's; Func runs: 10000; result: 0.1853447250852242
500 Forest's; Func runs: 10000; result: 0.15382470751079919
=============================
5 Megacity's; Func runs: 10000; result: 0.19846153846153847
25 Megacity's; Func runs: 10000; result: 0.11815384615384619
500 Megacity's; Func runs: 10000; result: 0.09475384615384692
=============================
总分:1.90578 (21.18%)

根据测试结果,该算法在满分100分的情况下仅获得21.18分。这一成绩非常不理想。遗憾的是,它在当前排名表中位列末尾。让我们尝试修改算法逻辑,以取得更好的结果。我们将逐步进行修改,并监测结果。

原始AOA算法的逻辑涉及随机搜索,其仅依赖于从四种数学运算符中做出概率性选择的随机性本质。让我们在μ位移比例中加入一个随机性元素,将其乘以一个0到1之间的随机数。

// Research phase using Division (D) and Multiplication (M) operators
  for (int i = 0; i < popSize; i++) // For each particle
  {
    for (int c = 0; c < coords; c++) // For each coordinate
    {
      double rand1 = u.RNDprobab (); // Generate a random value
      double rand2 = u.RNDprobab (); // Generate a random value
      double rand3 = u.RNDprobab (); // Generate a random value

      best = cB [c];                 // Save the current best value

      μ *= u.RNDfromCI (0, 1);       // Random change of μ

      if (rand1 < MoAc)              // If random value is less than MoAc
      {
        if (rand2 > 0.5)             // If random value is greater than 0.5
        {
          a [i].c [c] = best / (MoPr + ϵ) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]); // Update particle position
        }
        else
        {
          a [i].c [c] = best * (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
      }
      else // If random value is greater than or equal to MoAc
      {
        if (rand3 > 0.5) // If random value is greater than 0.5
        {
          a [i].c [c] = best - (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
        else
        {
          a [i].c [c] = best + (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ + rangeMin [c]);     // Update particle position
        }
      }

      a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);       // Convert to discrete values
    }
  }

让我们使用相同的参数测试算法:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|0.01|
=============================
5 Hilly's; Func runs: 10000; result: 0.3595591180258857
25 Hilly's; Func runs: 10000; result: 0.2804913285516192
500 Hilly's; Func runs: 10000; result: 0.25204298245610646
=============================
5 Forest's; Func runs: 10000; result: 0.24115834887873383
25 Forest's; Func runs: 10000; result: 0.18034196700384764
500 Forest's; Func runs: 10000; result: 0.15441446106797124
=============================
5 Megacity's; Func runs: 10000; result: 0.18307692307692305
25 Megacity's; Func runs: 10000; result: 0.12400000000000003
500 Megacity's; Func runs: 10000; result: 0.09470769230769309
=============================
总分:1.86979 (20.78%)

遗憾的是,结果变得更糟了。需要采取更多措施。不过,在确定性表达式中加入随机性这一做法本身,理应能提升搜索策略的多样性。让我们仔细审视数学运算符的公式——每个公式都包含rangeMin [c]这一项。本质上,这些运算符所得出的表达式总是以待优化参数的最小边界为中心。这并无明显逻辑依据,因此,让我们将这一元素从所有公式中移除

// Research phase using Division (D) and Multiplication (M) operators
for (int i = 0; i < popSize; i++) // For each particle
{
  for (int c = 0; c < coords; c++) // For each coordinate
  {
    double rand1 = u.RNDprobab (); // Generate a random value
    double rand2 = u.RNDprobab (); // Generate a random value
    double rand3 = u.RNDprobab (); // Generate a random value

    best = cB [c];                 // Save the current best value

    μ *= u.RNDfromCI (0, 1);       // Change μ

    if (rand1 < MoAc)              // If random value is less than MoAc
    {
      if (rand2 > 0.5)             // If random value is greater than 0.5
      {
        a [i].c [c] = best / (MoPr + ϵ) * ((rangeMax [c] - rangeMin [c]) * μ);// + rangeMin [c]); // Update particle position
      }
      else
      {
        a [i].c [c] = best * (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);// + rangeMin [c]);     // Update particle position
      }
    }
    else // If random value is greater than or equal to MoAc
    {
      if (rand3 > 0.5) // If random value is greater than 0.5
      {
        a [i].c [c] = best - (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);// + rangeMin [c]);     // Update particle position
      }
      else
      {
        a [i].c [c] = best + (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);// + rangeMin [c]);     // Update particle position
      }
    }

    a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);       // Convert to discrete values
  }
}

让我们来进行测试。以下是所得结果:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|0.01|
=============================
5 Hilly's; Func runs: 10000; result: 0.36094646986361645
25 Hilly's; Func runs: 10000; result: 0.28294095623218063
500 Hilly's; Func runs: 10000; result: 0.2524581968477915
=============================
5 Forest's; Func runs: 10000; result: 0.2463208325927641
25 Forest's; Func runs: 10000; result: 0.1772140022690996
500 Forest's; Func runs: 10000; result: 0.15367993432040622
=============================
5 Megacity's; Func runs: 10000; result: 0.1923076923076923
25 Megacity's; Func runs: 10000; result: 0.11938461538461542
500 Megacity's; Func runs: 10000; result: 0.09433846153846229
=============================
总分:1.87959 (20.88%)

我们所做的改动并未带来任何性能提升,考虑到我们已对搜索策略实施了重大调整,这一结果着实令人诧异。这或许表明,策略本身存在缺陷,而仅移除个别组件并不会对结果产生显著影响。

搜索策略中包含一个随每次迭代线性增加的MoA组件(见图1)。让我们尝试将该组件用于从最优解的坐标中做出概率性选择,并将其复制到当前工作解中。通过利用种群中最优解的信息交换(在原始版本中,智能体之间不存在信息交换),应该为搜索策略增添组合特性。

// Research phase using Division (D) and Multiplication (M) operators
for (int i = 0; i < popSize; i++) // For each particle
{
  for (int c = 0; c < coords; c++) // For each coordinate
  {
    double rand1 = u.RNDprobab (); // Generate a random value
    double rand2 = u.RNDprobab (); // Generate a random value
    double rand3 = u.RNDprobab (); // Generate a random value

    best = cB [c];                 // Save the current best value

    μ *= u.RNDfromCI (0, 1);       // Change μ

    if (rand1 < MoAc)              // If random value is less than MoAc
    {
      if (rand2 > 0.5)             // If random value is greater than 0.5
      {
        a [i].c [c] = best / (MoPr + ϵ) * ((rangeMax [c] - rangeMin [c]) * μ); // Update particle position
      }
      else
      {
        a [i].c [c] = best * (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);     // Update particle position
      }
    }
    else // If random value is greater than or equal to MoAc
    {
      if (rand3 > 0.5) // If random value is greater than 0.5
      {
        a [i].c [c] = best - (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);     // Update particle position
      }
      else
      {
        a [i].c [c] = best + (MoPr) * ((rangeMax [c] - rangeMin [c]) * μ);     // Update particle position
      }
    }

    if (u.RNDbool () < MoAc) a [i].c [c] = cB [c];                                            // Set to the best value

    a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);       // Convert to discrete values
  }
}

在引入通过最优解进行信息交换的逻辑后,取得的结果如下:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|0.01|
=============================
5 Hilly's; Func runs: 10000; result: 0.360814744695913
25 Hilly's; Func runs: 10000; result: 0.28724958448168375
500 Hilly's; Func runs: 10000; result: 0.2523432997811412
=============================
5 Forest's; Func runs: 10000; result: 0.26319762212870146
25 Forest's; Func runs: 10000; result: 0.1796822846691542
500 Forest's; Func runs: 10000; result: 0.1546335398592898
=============================
5 Megacity's; Func runs: 10000; result: 0.18
25 Megacity's; Func runs: 10000; result: 0.12153846153846157
500 Megacity's; Func runs: 10000; result: 0.09373846153846228
=============================
总分:1.89320 (21.04%)

我们观察到性能有所提升,但目前这种提升仍局限于解本身的范围内。现在,让我们在代码的同一部分添加一项功能:在优化参数的整个可接受范围内,为坐标生成随机值的概率(同时,该坐标会根据MoP方程以非线性方式递减)。

// Probabilistic update of particle position
if (u.RNDbool () < MoAc) a [i].c [c] = cB [c];                                        // Set to the best value
else
  if (u.RNDbool () < MoPr) a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);    // Generate new random position

让我们看看以下结果:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|0.01|
=============================
5 Hilly's; Func runs: 10000; result: 0.8354927331645667
25 Hilly's; Func runs: 10000; result: 0.3963221867834875
500 Hilly's; Func runs: 10000; result: 0.2526544322311671
=============================
5 Forest's; Func runs: 10000; result: 0.7689954585427405
25 Forest's; Func runs: 10000; result: 0.3144560745800252
500 Forest's; Func runs: 10000; result: 0.15495875390289315
=============================
5 Megacity's; Func runs: 10000; result: 0.6076923076923076
25 Megacity's; Func runs: 10000; result: 0.24646153846153843
500 Megacity's; Func runs: 10000; result: 0.09816923076923163
=============================
总分:3.67520 (40.84%)

令人惊叹的是,效率得到了大幅提升!这意味着我们的改进方向是正确的。值得注意的是,我们究竟为AOA算法逻辑添加了什么:在优化初期,即第一个迭代周期(epoch)时,将全局最优解的坐标复制到当前解的概率极低。这十分合理,因为在优化初始阶段,策略才刚刚开始探索搜索空间。与此同时,在第一次迭代时,在整个搜索空间内生成随机解的概率达到最大。在所有迭代周期中,这些概率会发生变化:复制全局解坐标的概率逐渐增加,而生成随机解的概率则相反,逐渐降低(见图1)。

鉴于我所做的改动已使性能得到提升,且此前已指出对原始逻辑的改动并未带来显著改善,因此,完全摒弃所有算术运算符是合理的。让我们基于测试问题检验修改后的算法:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.9|2.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.8751771961221438
25 Hilly's; Func runs: 10000; result: 0.4645369071659114
500 Hilly's; Func runs: 10000; result: 0.27170038319811357
=============================
5 Forest's; Func runs: 10000; result: 0.8369443889312367
25 Forest's; Func runs: 10000; result: 0.36483865328371257
500 Forest's; Func runs: 10000; result: 0.17097532914778202
=============================
5 Megacity's; Func runs: 10000; result: 0.7046153846153846
25 Megacity's; Func runs: 10000; result: 0.28892307692307695
500 Megacity's; Func runs: 10000; result: 0.10847692307692398
=============================
总分:4.08619 (45.40%)   

正如我们所见,效率又提升了近5%,这再次验证了我的推理是正确的。使用默认参数时,我们获得了有趣的结果,然而,逻辑改动如此之大,以至于现在有必要为算法选择最优的外部参数。效率提升带来的额外好处包括:

  • 工作速度显著提升,因为我们摆脱了不必要的随机数生成过程
  • 外部参数数量减少了一个

让我们来看看最终得到的算法结果:

AOA|Arithmetic Optimization Algorithm|50.0|0.1|0.5|10.0|
=============================
5 Hilly's; Func runs: 10000; result: 0.9152036654779877
25 Hilly's; Func runs: 10000; result: 0.46975580956945456
500 Hilly's; Func runs: 10000; result: 0.27088799720164297
=============================
5 Forest's; Func runs: 10000; result: 0.8967497776673259
25 Forest's; Func runs: 10000; result: 0.3740125122006007
500 Forest's; Func runs: 10000; result: 0.16983896751516864
=============================
5 Megacity's; Func runs: 10000; result: 0.6953846153846155
25 Megacity's; Func runs: 10000; result: 0.2803076923076923
500 Megacity's; Func runs: 10000; result: 0.10852307692307792
=============================
总分:4.18066 (46.45%) 

所得结果已足以在排名表中占据一席之地,而最终版本的搜索策略已完全摒弃了原始逻辑的元素。因此,我决定为这个新算法赋予一个新名称——简单优化算法(Simple Optimization Algorithm,SOA)。让我们来看看完整的SOA算法最终代码。

#include "#C_AO.mqh"

//——————————————————————————————————————————————————————————————————————————————
class C_AO_SOA : public C_AO
{
  public: //--------------------------------------------------------------------
  ~C_AO_SOA () { }
  C_AO_SOA ()
  {
    ao_name = "SOA";
    ao_desc = "Simple Optimization Algorithm";
    ao_link = "https://www.mql5.com/en/articles/16364";

    popSize = 50;   // Population size
    minT    = 0.1;  // Minimum T value
    maxT    = 0.9;  // Maximum T value
    θ       = 10;   // θ parameter

    ArrayResize (params, 4); // Resize the parameter array

    // Initialize parameters
    params [0].name = "popSize"; params [0].val = popSize;
    params [1].name = "minT";    params [1].val = minT;
    params [2].name = "maxT";    params [2].val = maxT;
    params [3].name = "θ";       params [3].val = θ;
  }

  void SetParams () // Method for setting parameters
  {
    popSize = (int)params [0].val; // Set population size
    minT    = params      [1].val; // Set minimum T
    maxT    = params      [2].val; // Set maximum T
    θ       = params      [3].val; // Set θ
  }

  bool Init (const double &rangeMinP  [], // Minimum search range
             const double &rangeMaxP  [], // Maximum search range
             const double &rangeStepP [], // Search step
             const int     epochsP = 0);  // Number of epochs

  void Moving   (); // Method of moving particles
  void Revision (); // Revision method

  //----------------------------------------------------------------------------
  double minT; // Minimum T value
  double maxT; // Maximum T value
  double θ;    // θ parameter

  private: //-------------------------------------------------------------------
  int epochs;    // Total number of epochs
  int epochNow;  // Current epoch
  double ϵ;      // Parameter to prevent division by zero
};
//——————————————————————————————————————————————————————————————————————————————

//——————————————————————————————————————————————————————————————————————————————
bool C_AO_SOA::Init (const double &rangeMinP  [], // Minimum search range
                     const double &rangeMaxP  [], // Maximum search range
                     const double &rangeStepP [], // Search step
                     const int     epochsP = 0)   // Number of epochs
{
  if (!StandardInit (rangeMinP, rangeMaxP, rangeStepP)) return false; // Initialization of standard parameters

  //----------------------------------------------------------------------------
  epochs   = epochsP;     // Set the total number of epochs
  epochNow = 0;           // Initialize the current epoch
  ϵ        = DBL_EPSILON; // Set ϵ

  return true;            // Return 'true' if initialization was successful
}
//——————————————————————————————————————————————————————————————————————————————

//——————————————————————————————————————————————————————————————————————————————
// Particle displacement method
void C_AO_SOA::Moving ()
{
  epochNow++; // Increase the current epoch number

  // Initial random positioning
  if (!revision) // If there has not been a revision yet 
  {
    for (int i = 0; i < popSize; i++) // For each particle
    {
      for (int c = 0; c < coords; c++) // For each coordinate
      {
        a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);                             // Generate random position
        a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]); // Convert to discrete values
      }
    }

    revision = true; // Set revision flag
    return;          // Exit the method
  }

  //----------------------------------------------------------------------------
  double MoAc = minT + epochNow * ((maxT - minT) / epochs); // Calculate the MoAc value
  double MoPr = 1.0 - pow (epochNow / epochs, (1.0 / θ));   // Calculate the MoPr value
  double best = 0.0;                                        // Variable to store the best value

  // Research phase using Division (D) and Multiplication (M) operators
  for (int i = 0; i < popSize; i++) // For each particle
  {
    for (int c = 0; c < coords; c++) // For each coordinate
    {
      // Probabilistic update of particle position
      if (u.RNDbool () < MoAc) a [i].c [c] = cB [c];                                        // Set to the best value
      else
        if (u.RNDbool () < MoPr) a [i].c [c] = u.RNDfromCI (rangeMin [c], rangeMax [c]);    // Generate new random position

      a [i].c [c] = u.SeInDiSp  (a [i].c [c], rangeMin [c], rangeMax [c], rangeStep [c]);   // Convert to discrete values
    }
  }
}
//——————————————————————————————————————————————————————————————————————————————

//——————————————————————————————————————————————————————————————————————————————
void C_AO_SOA::Revision ()
{
  int ind = -1;                     // Index to store the best particle

  for (int i = 0; i < popSize; i++) // For each particle
  {
    if (a [i].f > fB)               // If the function value is better than the current best one
    {
      fB = a [i].f;                 // Update the best value of the function
      ind = i;                      // Save the index of the best particle
    }
  }

  if (ind != -1) ArrayCopy (cB, a [ind].c, 0, 0, WHOLE_ARRAY); // Copy the coordinates of the best particle
}
//——————————————————————————————————————————————————————————————————————————————

就代码而言,这是我们之前探讨过的最为简洁的优化算法之一。唯一比它更简短的代码是随机游走(Random Walk,RW)算法的代码,该算法将在后续的一篇文章中详细讨论。

在解空间中可视化搜索策略的性能,能直观展现诸多信息。我将AOA算法在三种函数上测试,将其在丘陵(Hilly)、森林(Forest)和超级城市(Megacity)中的表现整合成了一部动画,因为该算法在不同类型任务上的性能表现几乎毫无差异。以下是SOA算法在三个测试函数上分别运行的可视化效果。

值得注意的是,新的SOA算法在处理低维问题时表现突出——结果分布范围较小,这是一种相当罕见的优良特性。 

AOA在Hilly, Forest, Megacity测试函数上

AOA在Hilly, Forest, Megacity 测试函数上

Hilly值

SOA在Hilly测试函数上

Forest值

  SOA在Forest测试函数上

Megacity值

SOA在Megacity测试函数上


根据测试结果,原始的AOA算法未能跻身排名表,其成绩位列45名之后。而新的简单优化算法(SOA)则成功入榜,最终排名第29位。

# 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 ANS 跨邻域搜索 0.94948 0.84776 0.43857 2.23581 1.00000 0.92334 0.39988 2.32323 0.70923 0.63477 0.23091 1.57491 6.134 68.15
2 CLA 密码锁算法(joo) 0.95345 0.87107 0.37590 2.20042 0.98942 0.91709 0.31642 2.22294 0.79692 0.69385 0.19303 1.68380 6.107 67.86
3 AMOm 动物迁徙优化M 0.90358 0.84317 0.46284 2.20959 0.99001 0.92436 0.46598 2.38034 0.56769 0.59132 0.23773 1.39675 5.987 66.52
4 (P+O)ES (P+O) 进化策略 0.92256 0.88101 0.40021 2.20379 0.97750 0.87490 0.31945 2.17185 0.67385 0.62985 0.18634 1.49003 5.866 65.17
5 CTA 彗星尾算法(joo) 0.95346 0.86319 0.27770 2.09435 0.99794 0.85740 0.33949 2.19484 0.88769 0.56431 0.10512 1.55712 5.846 64.96
6 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
7 AAm 射箭算法M 0.91744 0.70876 0.42160 2.04780 0.92527 0.75802 0.35328 2.03657 0.67385 0.55200 0.23738 1.46323 5.548 61.64
8 ESG 社会群体的进化(joo) 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
9 SIA 模拟各向同性退火(joo) 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
10 ACS 人工协同搜索 0.75547 0.74744 0.30407 1.80698 1.00000 0.88861 0.22413 2.11274 0.69077 0.48185 0.13322 1.30583 5.226 58.06
11 ASO 无序社会优化 0.84872 0.74646 0.31465 1.90983 0.96148 0.79150 0.23803 1.99101 0.57077 0.54062 0.16614 1.27752 5.178 57.54
12 AOSm 原子轨道搜索M 0.80232 0.70449 0.31021 1.81702 0.85660 0.69451 0.21996 1.77107 0.74615 0.52862 0.14358 1.41835 5.006 55.63
13 TSEA 龟壳演化算法(joo) 0.96798 0.64480 0.29672 1.90949 0.99449 0.61981 0.22708 1.84139 0.69077 0.42646 0.13598 1.25322 5.004 55.60
14 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
15 CRO 化学反应优化 0.94629 0.66112 0.29853 1.90593 0.87906 0.58422 0.21146 1.67473 0.75846 0.42646 0.12686 1.31178 4.892 54.36
16 BSA 鸟群算法 0.89306 0.64900 0.26250 1.80455 0.92420 0.71121 0.24939 1.88479 0.69385 0.32615 0.10012 1.12012 4.809 53.44
17 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
18 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
19 BCOm 细菌趋化性优化算法M 0.75953 0.62268 0.31483 1.69704 0.89378 0.61339 0.22542 1.73259 0.65385 0.42092 0.14435 1.21912 4.649 51.65
20 ABO 非洲水牛优化 0.83337 0.62247 0.29964 1.75548 0.92170 0.58618 0.19723 1.70511 0.61000 0.43154 0.13225 1.17378 4.634 51.49
21 (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
22 TSm 禁忌搜索M 0.87795 0.61431 0.29104 1.78330 0.92885 0.51844 0.19054 1.63783 0.61077 0.38215 0.12157 1.11449 4.536 50.40
23 BSO 头脑风暴优化 0.93736 0.57616 0.29688 1.81041 0.93131 0.55866 0.23537 1.72534 0.55231 0.29077 0.11914 0.96222 4.498 49.98
24 WOAm 鲸鱼优化算法M 0.84521 0.56298 0.26263 1.67081 0.93100 0.52278 0.16365 1.61743 0.66308 0.41138 0.11357 1.18803 4.476 49.74
25 AEFA 人工电场算法 0.87700 0.61753 0.25235 1.74688 0.92729 0.72698 0.18064 1.83490 0.66615 0.11631 0.09508 0.87754 4.459 49.55
26 AEO 基于人工生态系统的优化算法 0.91380 0.46713 0.26470 1.64563 0.90223 0.43705 0.21400 1.55327 0.66154 0.30800 0.28563 1.25517 4.454 49.49
27 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
28 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
29 SOA 简单优化算法 0.91520 0.46976 0.27089 1.65585 0.89675 0.37401 0.16984 1.44060 0.69538 0.28031 0.10852 1.08422 4.181 46.45
30 ABHA 人工蜂巢算法 0.84131 0.54227 0.26304 1.64663 0.87858 0.47779 0.17181 1.52818 0.50923 0.33877 0.10397 0.95197 4.127 45.85
31 ACMO 大气云模型优化 0.90321 0.48546 0.30403 1.69270 0.80268 0.37857 0.19178 1.37303 0.62308 0.24400 0.10795 0.97503 4.041 44.90
32 ASHA 人工淋浴算法 0.89686 0.40433 0.25617 1.55737 0.80360 0.35526 0.19160 1.35046 0.47692 0.18123 0.09774 0.75589 3.664 40.71
33 ASBO 适应性社会行为优化 0.76331 0.49253 0.32619 1.58202 0.79546 0.40035 0.26097 1.45677 0.26462 0.17169 0.18200 0.61831 3.657 40.63
34 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
35 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
36 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
37 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
38 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
39 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
40 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
41 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
42 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
43 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
44 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
45 AAA 人工藻类算法 0.50007 0.32040 0.25525 1.07572 0.37021 0.22284 0.16785 0.76089 0.27846 0.14800 0.09755 0.52402 2.361 26.23


总结

我们已经详细地探讨了算术优化算法,其实现过程确实极为简便。然而,正如有时会出现的情况那样,简单性并不总能保证取得优异成果。成功的真正秘诀在于极致的简单!当然,我这是在开玩笑。AOA算法的主要问题在于种群成员之间缺乏互动与信息交流,这进而导致该搜索策略完全缺乏组合特性。

该算法的另一缺点在于其搜索算子缺乏可变性。尽管每个坐标的算子选择是随机的,但这无法使算法有效地“捕捉”到搜索空间的多维特征。不过,AOA算法也包含了一些合理且逻辑清晰的方法,比如MoA和MoP元素会随每个迭代周期(epoch)而变化。这些方法成为重新构建算法的基础,推动其演变为一种基于概率方法的新型、有趣且极其简单的搜索策略,该策略通过从种群中的最优解复制信息,并在搜索空间中生成随机解来实现。

随着每个迭代周期的推进,种群决策中的随机性逐渐减少,而成功方向的集中度则逐渐增加。可以将其比作在河上建造一座优雅的桥梁:在工作的初始阶段,会使用各种可能并不适合最终结果的材料和设计。然而,随着项目逐渐接近完成,最优解决方案变得更加显而易见,不必要的材料也被摒弃。最终,这座桥梁变得愈发平衡稳固,以优雅而坚固的方式连接着两岸。

标签

图例2. 根据相关测试,将算法的颜色等级大于或等于0.99的结果以白色突出显示。

图表

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

其中 100 是理论上的最大可能结果,将计算评级表格的脚本存档)


SOA pros and cons:

优点:

  1. 少量外部参数。
  2. 在低维问题上,尤其是离散型问题上表现优异。
  3. 快速。
  4. 在低维问题上,结果分布范围(或离散程度)较小。
  5. 实现简单。

缺点:

  1. 可扩展性低。

文章附有一个包含当前版本算法代码的归档文件。本文作者对标准算法描述的绝对准确性不承担责任。为提升搜索能力,已经对其中的许多算法进行了修改。文章中表述的结论和论断都是基于实验的结果。

文中所用的程序

# 名称 类型 描述
1 #C_AO.mqh

种群优化算法的基类
2 #C_AO_enum.mqh

种群优化算法的枚举说明
3 TestFunctions.mqh

测试函数库
4
TestStandFunctions.mqh

测试台函数库
5
Utilities.mqh

辅助函数库
6
CalculationTestResults.mqh

用于计算比较表结果的脚本
7
Testing AOs.mq5
脚本 面向所有种群优化算法的统一测试平台
8
Simple use of population optimization algorithms.mq5
脚本
种群优化算法非可视化简易使用案例
9
AO_AOA_ArithmeticOptimizationAlgorithm.mqh
AOA算法类
10
AO_SOA_SimpleOptimizationAlgorithm.mqh

SOA算法类
11
Test_AO_AOA.mq5
脚本 AOA测试
12
Test_AO_SOA.mq5
脚本
SOA测试

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

附加的文件 |
AOA_SOA.zip (141.9 KB)
市场轮廓指标 市场轮廓指标
在本文中,我们将探讨市场轮廓指标。我们将探究这个名称背后隐藏的内容,尝试理解其运行原理,并分析其程序代码(MarketProfile)。
交易中的神经网络:受控分段 交易中的神经网络:受控分段
在本文中。我们将讨论一种复杂的多模态交互分析和特征理解的方法。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
使用莱文贝格-马夸尔特(Levenberg-Marquardt,LM)算法训练多层感知器 使用莱文贝格-马夸尔特(Levenberg-Marquardt,LM)算法训练多层感知器
本文介绍了一种用于训练前馈神经网络的莱文贝格-马夸尔特(Levenberg-Marquardt,LM)算法的实现。与Python的scikit-learn库中的算法进行性能比较分析。初步探讨更简便的学习方法,如梯度下降、带动量的梯度下降和随机梯度下降。