粒子群优化(Particle Swarm Optimization, PSO)是一种基于群体智能的优化算法,最初由Jim Kennedy和Russ Eberhart于1995年提出。该算法最初用于模拟鸟群的飞行行为。其基本思想是让一组问题解决实体(粒子)在可能的解空间范围内移动(飞行)。粒子在解空间中的移动具有随机性,但主要由三个因素指导:粒子当前位置、粒子找到的最优位置(个人最优,pBest)以及群体中找到的最优位置(全局最优,gBest)。
以寻找方程(X*X)-(Y*Y)的最小值为例,其中X和Y是0到10之间的整数。算法的执行路径如下:
Rosenbrock函数常用作优化器的测试。由于它是多维的,并且有很多局部最小值,所以很难找到最小值。在选择适合的函数进行测试时,需要记住优化器具有内置的偏差。在解空间的中心或边缘找到解决方案更容易。
以C#语言为例,更新每个维度的速度,例如X和Y。速度是位置变化的量。
double[] vid = vid * W + C1 * Rand(pid - xid) + C2 * Rand(pgd - xid);
其中:
通过将新速度加到当前位置来更新当前位置。
double[] xid = xid + vid;
就是这样。没有变异或生成新粒子。它只是一个半随机的搜索过程,通过群体成员之间的信息交换来指导。
现代算法的变体使用局部最优位置而不是全局最优。这有助于更好地探索解空间,并防止过快地收敛到某个区域最小值。每个粒子都有一个固定的重叠信息集合,从中得出其局部最优位置。粒子以环状结构相互连接。例如,在6粒子群体中,A到F,信息数量设置为2,粒子A将由粒子F和B提供信息。粒子B将由粒子A和C提供信息,粒子F将由粒子E和A提供信息。另一种变体是将信息者分成不同的组,并在一定数量的迭代后没有改变全局最优值时重新组织它们。这种变体使得所有组可以同时在不同的线程上进行优化,并在一定数量的时期没有改进后重新分配。
粒子可能会飞出解空间,例如,X可能会获得大于10的值。处理这种情况有几种方法。最简单的就是让它们飞,但不允许逃逸的粒子更新pBest或lBest位置。粒子将在pBest和lBest的影响下被拉回到正确的范围内。
Particle类具有以下构造函数。
public Particle(int dimensions, Func errorFunc, ParticleManager particleManager)
{
this.Dimensions = dimensions;
this.particleManager = particleManager;
this.errorFunc = errorFunc;
this.Initialize();
}
要解决的问题作为Func
Optimize函数相当直接。连续静态时期的数量用于在没有改进时提供早期退出。优化器的属性在app.config文件中设置。
public double[] Optimize()
{
int epoch = 0;
int staticEpochs = 0;
while (epoch < this.psoAttributes.MaxEpochs && staticEpochs < psoAttributes.MaxStaticEpochs)
{
bool isErrorImproved = false;
foreach (IParticle particle in this.Swarm)
{
double error = particle.OptimizePosition();
if (error < this.BestGlobalError)
{
particle.Position.CopyTo(this.BestGlobalPosition, 0);
this.BestGlobalError = error;
isErrorImproved = true;
staticEpochs = 0;
}
}
if (!isErrorImproved)
{
staticEpochs++;
}
epoch++;
}
return this.BestGlobalPosition;
}