粒子群算法
原始粒子群算法
粒子群算法(Particle Swarm Optimization, PSO)的基本思想是随机初始化一群没有体积没有质量的粒子,将每个粒子视为优化问题的一个可行解,粒子的好坏由一个事先设定的适应度函数来确定。每个粒子将在可行解空间中运行,并由一个速度变量决定其方向和距离。通常粒子将追随当前的最优粒子,并经逐代搜索后得到最优解。在每一代中,粒子将跟踪两个极值:一个是粒子本身迄今为止找到的最优解,另一个则是整个群体迄今为止找到的最优解。
假设一个由 \(M\) 个粒子组成的群体在 \(D\) 维的搜索空间以一定的速度飞行。粒子 \(i\) 在 \(t\) 时刻的状态属性设置如下:
- 位置:\(x_i^t = {\left( {x_{i1}^t,x_{i2}^t, \cdots ,x_{id}^t} \right)^T}\),其中 \(x_{id}^t \in \left[ {{L_d},{U_d}} \right]\),\(L_d\),\(U_d\) 分别为搜索空间的下限和上限;
- 速度:\(v_i^t = {\left( {v_{i1}^t,v_{i2}^t, \cdots ,v_{id}^t} \right)^T}\),其中 \(v_{id}^t \in \left[ {{v_{min,d}},{v_{max,d}}} \right]\),\(v_{min,d}\),\(v_{max,d}\) 分别为最小和最大速度;
- 个体最优位置:\(p_i^t = {\left( {p_{i1}^t,p_{i2}^t, \cdots ,p_{iD}^t} \right)^T}\) ;
- 全局最优位置:\(p_g^t = {\left( {p_{g1}^t,p_{g2}^t, \cdots ,p_{gD}^t} \right)^T}\) ;
其中,\(1 \le d \le D\) ,\(1 \le i \le M\) 。
则粒子在 \(t+1\) 时刻的位置通过下式更新获得:
式中,\(r_1\),\(r_2\) 为均匀分布在 \((0,1)\) 区间上的随机数;\(c_1\),\(c_2\) 称为学习因子,通常取 \(c_1=c_2=2\) 。
式(1)主要由三部分线组成:
- 第一部分为粒子先前速度的继承,表示粒子对当前自身运动状态的信任,依据自身的速度进行惯性运动;
- 第二部分为 “认知” 部分,表示粒子本身的思考,即根据综合考虑自身以往的经历从而实现对下一步行为决策,这种行为决策便是 “认知” ;
- 第三部分为 “社会” 部分,表示粒子间的信息共享与相互合作。在搜索过程中粒子一方面记住它们自己的经验,同时考虑其他同伴的经验。当单个粒子觉察同伴经验较好的时候,它将进行适应性的调整,寻求一致认知过程。
基本 PSO 算法的实现步骤如下:
(1)初始化。设定 PSO 算法中涉及的各类参数:搜索空间的上限和下限 \(L_D\) 和 \(U_d\) ,学习因子 \(c_1\),\(c_2\) ,算法最大迭代次数 \(T_{max}\) 或收敛精度 $\xi $,粒子速度范围 \(\left[ {{v_{min}},{v_{max}}} \right]\);随机初始化搜索点的位置 \(x_i\) 及其速度 \(v_i\) ,设置当前位置即为每个粒子的 \(p_i\) ,从个体极值找出全局极值,记录该最好值的粒子序号 \(g\) 机器位置 \(p_g\) 。
(2)评价每一个粒子。计算粒子的适应值,如果好于该粒子当前的个体极值,则将 \(p_i\) 设置为该粒子的位置,且更新个体极值。如果所有粒子的个体极值中最好的好于当前的全局值,则将 \(p_g\) 设置为该粒子的位置,更新全局值及其序号 \(g\) 。
(3)粒子的状态更新。用式(1)和式(2)对每一个粒子的速度和位置进行更新。如果 \(v_i \gt v_{max}\) 将其置为 \(v_{max}\) ,如果 \(v_i \lt v_{min}\) 将其置为 \(v_{min}\) 。
(4)检验是否符合结束条件。如果当前的迭代次数达到了预先设定的最大次数 \(T_{max}\) ,或最终结果小于预定收敛精度 \(\xi\) 要求,则停止迭代,输出最优解,否则转到步骤(2)。
标准粒子群算法
标准 PSO(Stand PSO,SPSO)模型与原始 PSO 模型的不同之处在于,通过一个惯性权重 \(\omega\) (Y.Shi et al,1998)来协调 PSO 算法的全局和局部寻优能力。具体做法是将基本 PSO 的速度方程修改为如式(3)所示,而位置方程保持不变:
这里 \(\omega\) 称为惯性权重,其大小决定了粒子对当前速度继承的多少,选择一个合适的 \(\omega\) 有助于 PSO 均衡它的探索能力与开发能力。
Y.Shi 等(2000)指出了惯性权重的作用,较大的惯性权重有利于展开全局寻优,而较小的惯性权重则有利于局部寻优。因此,如果在迭代计算过程中呈线性递减惯性权重,则 PSO 算法在开始时具有良好的全局搜索性能,能够迅速定位到接近全局最优点的区域,而在后期具有良好的局部搜索性能,能够精确地得到全局最优解。Y.Shi 等(2000)经过多组反复实验后,建议采用从 0.9 线性递减到 0.4 的策略,通常会取得比较好的算法性能。线性递减公式如下:
式中,\(t_{max}\) 为最大迭代次数, \(t\) 为当前迭代次数,\(\omega _{start}\) ,\(\omega _{end}\) 分别为初始惯性权重和终止惯性权重。
标准测试函数
使用标准测试函数对基本 PSO 算法及其改进算法进行试验研究,这些标准测试函数都是经过精心设计和严格测试的,如果某一优化算法能较为满意地解决一个标准测试问题,则可以认为它在大量的问题上会取得良好的表现。
(1) Sphere 函数:
又称 DeJong 函数,这是一个简单的单峰函数,各类优化算法性能都能较为容易地发现全局最优解,它的简单性有助于研究优化算法在问题维度上的效果。该函数的全局最优点位于 \(x = \left\{ {0, \cdots ,0} \right\}\) ,全局最优点的函数值 \(f_1(x) = 0\) 。
(2)Schwefel 函数:
该函数的全局最优点位于 \(x = \left\{ {0, \cdots ,0} \right\}\) ,全局最优点的函数值 \(f_2(x) = 0\) 。由于该函数是单峰函数,但是该函数由于 \(\prod\) 的存在使得各变量相互影响,比 Sphere 函数较难求解。
(3)Rosenbrock 函数:
这是一个单峰函数,但并不易于求解。该函数在远离最优点区域的适应值地形很简单,但靠近最优点的区域为香蕉状。变量之间具有很强的相关性,且梯度信息经常舞蹈算法的搜索方向。该函数在最优点 \(x = \left\{ {1, \cdots ,1} \right\}\),具有最小函数值 \(f_3(x) = 0\) 。
(4)Rastrigin 函数:
这是 Sphere 类函数的多峰版本,具有大量按正弦拐点排列的、很深的局部最优点。全局最优值为 \(f_4(x) = 0\) ,在点 \(x = \left\{ {0, \cdots ,0} \right\}\) 处获取。优化算法很容易在通往全局最优点的路径上陷入一个局部最优点。
(5)Griewank 函数:
该函数是一个复杂的多峰函数,粗在大量的局部最小点和高大障碍物,由于各变量之间显著相关,优化算法很容易陷入局部最优,该函数全局最优值为 \(f_5(x) = 0\) ,在点 \(x = \left\{ {0, \cdots ,0} \right\}\) 处获取。
(6)Ackley 函数:
Ackley 函数,一个多峰的,存在许多局部最小的,自变量之间相互独立的函数,当\(x = \left\{ {0, \cdots ,0} \right\}\) 时,全局最优值为 \(f_6(x) = 0\) 。
(7)Quarticfunction (Nosie)函数:
这是一个含有高斯噪声的 4 次函数,当不考虑噪声影响时,它具有一个全局极小值 \(f_7 ( 0, \cdots ,0 ) = 0\) 。
(8)Shaffer 函数:
这是一个多峰函数,有无数个极小值点,一般算法都很难找到全局最优点,其中只有一个最小值点即当 \(x=\{0,0\}\) 时,全局最优值为 \(f_8(x) = -1\) 。
粒子群算法的基本实现
下面使用 Matlab 语言,以 Griewank 函数为测试对象,根据上述的标准 PSO 实现给出了应用 PSO 算法优化求解的具体过程。
% 相关参数的设置
UB = 600; % 函数的上界
lb = 300; % 函数的下界
PopSize = 40; % 种群大小
Dim = 10; % 微粒的维数
c1 = 2; % 学习因子
c2 = 2; % 学习因子
w_start = 0.9; % 惯性权重的初始值
w_end = 0.4; % 惯性权重的终止值
Vmax = 100; % 微粒的最大速度
MaxIter = 1500; % 最大迭代次数
Iter = 0; % 初始迭代次数
% Initialize Swarm and Velocity
X = rand(PopSize,Dim) * (UB-LB) + LB; % 为例位置随机初始化
V = rand(PopSize,Dim); % 微粒速度随机初始化
% 测试函数:Griewank 函数
ind = repmat(1:Dim, PopSize,1);
FX = sum(((X.^2)/4000)')' - prod(cos(X./ sqrt(ind))')' + 1;
% 设定当前位置为粒子的最好位置,并记录其最好值
PBest = X;
FPBest = FX;
% 找到初始微粒群体的最好微粒
[Fgbest,r] = min(FX);
CF = Fgbest; % 记录当前全局最优值
Best = X(r,:); % 用于保存最优粒子的位置
FBest = Fgbest;
% 循环
while(iter <= MaxIter)
iter = iter + 1;
% 更新惯性权重的值
w_now = ((w_start - w_end) * (Maxiter - iter)/MaxIter) + w_end;
A = repmat(X(r,:), PopSize,1);
% 生成随机数
R1 = rand(PopSize,Dim);
R2 = rand(PopSize,Dim);
% 速度更新
V = w_now * V + c1*R1.*(PBest-X) + c2*R2.*(A-X);
% 对进化后速度大于最大速度的微粒进行处理
changeRows = V > Vmax;
V(find(changeRows)) = Vmax;
% 对进化后速度小于最小速度的微粒进行处理
changeRows = V < -Vmax;
V(find(changeRows)) = -Vmax;
% 微粒位置进行更新
X = X + 1.0*V;
% 重新计算新位置的适应度值
ind = repmat(1:Dim, PopSize, 1);
FX = sum(((X.^2)/4000)')' - prod(cos(X./ sqrt(ind))')' + 1;
% 更新每个微粒的最好位置
P = FX < FPBest;
FPBest(find(P)) = FX(find(P)); % 适应值更换
PBest(find(P),:) = X(find(P),:); % 粒子位置更换
[Fgbest, g] = min(FPBest); % 保存最好适应值
if Fgbest < CF % 如果本次适应值好于上次则保存
[fBest, b] = min(FPBest); % 最好适应值为 fBest
Best = PBest(n,:); % 最好位置为 Best
end
CF = Fgbest; % 保留本次适应值,准备与下一次比较
end
参考来源
《粒子群优化算法》 李丽,牛奔著