粒子群优化算法(Particle Swarm Optimization)是一种进化计算机技术(evolutionary computation),源于对鸟类捕食行为的研究,是一种基于迭代的优化工具。事实上,像PSO这种同属于元启发式优化算法有很多,例如同样比较常用过的遗传算法,灰狼算法,鲸鱼算法等等,这些算法放在现在看并不新颖,近年来国外的一些期刊上有时还会出现一些新的优化算法,对于学者而言更倾向于用新的东西,不过在工程上,各种优化算法的效力往往是具备一定的通用性和针对性的,只消能解决特定的问题即可。元启发式的搜索算法因其简单便捷,至今仍在工程中广为受用。
本文首先介绍最基本的PSO粒子群算法,其原理简单来说即是在初始时刻随机生成一系列无质量的粒子,在迭代中更新每个粒子的速度和位置,通过比较每次带入到目标函数中得到的适应值,逐渐向得到目标函数最优解的方向搜索。
实际使用中,往往希望所使用的方法以函数的形式实现,例如对于本文的优化算,我们希望将算法写成MATLAB函数的形式,输入目标函数的格式以及算法的一些基本参数(粒子个数、迭代数目、自变量个数等等),输出为优化后的最优解和最优解对应的最优值,即:
function [xm,fv] = PSO(fitness,N,c1,c2,w,M,D)
我在大量应用后,觉得这种形式的PSO算法用起来最为便捷,它源自《精通MATLAB最优计算》(龚纯),这本书是我很推荐的一本书,很适合学习使用MATLAB做优化问题的初学者,有兴趣的读者可以找来看看(如果需要电子版可以私信哦)。
其中除去fitness共有五个参数(fitness为目标函数的表达式):
N:粒子数。粒子数的多少根据问题的复杂程度自行决定;
D:粒子的维度。因优化的问题而定,也就是目标函数自变量的个数;
M:最大迭代次数。迭代次数越多,找到的解越精确,但运行时间也会更长;
c1、c2:学习因子。粒子自我学习的能力,在迭代中更新速度和位置,向群体中的最优点靠近;
w:惯性权重。决定粒子下一次迭代对当前速度的继承程度,合理的权重会大大提升优化的效果。
MATLAB代码如下:
function [xm,fv] = PSO(fitness,N,c1,c2,w,M,D) %调用算法
format long; %格式
for i=1:N %从第一个粒子到最后一个粒子
for j=1:D %每个粒子的各个维度
x(i,j)=randn; %随机初始化位置
v(i,j)=randn; %随机初始化速度
end
end
for i=1:N %从第一个粒子到最后一个粒子
p(i)=fitness(x(i,:)); %每个粒子最初的适应值
y(i,:)=x(i,:); %每个粒子最初的位置
end
pg = x(N,:); %pg为最后一个粒子的位置
for i=1:(N-1) %从第一个粒子到倒数第二个粒子
if fitness(x(i,:))<fitness(pg) %找到所有粒子中的最优解
pg=x(i,:); %全局最优解的位置给pg
end
end
for t=1:M %从第一次迭代到最后一次
for i=1:N %从第一个粒子到最后一个
v(i,:)=w*v(i,:)+c1*rand*(y(i,:)-x(i,:))+c2*rand*(pg-x(i,:)); %速度更新公式
x(i,:)=x(i,:)+v(i,:); %位置更新公式
if fitness(x(i,:))<p(i) %迭代过程中发现的更好的解
p(i)=fitness(x(i,:)); %p(i)为自身经历最好解
y(i,:)=x(i,:); %y(i)为自身经历最好位置
end
if p(i)<fitness(pg) %迭代过程中发现比当前全局最优解更好的解
pg=y(i,:); %更新全局最优解
end
end
end
xm = pg'; %xm即最优解的位置
fv = fitness(pg); %fv即所求最优解
下面举例展示该算法的使用方法。求下列函数的最小值:
可见其最小值显然为30个自变量xi都为0的情况,下面看看使用PSO算法随机搜索的结果。首先将目标函数也写成函数的形式以便调用算法:
function F = fitness(x)
F = 0;
for i=1:30
F = F +x(i)^2;
end
初始化PSO算法中的其余参数,显然维度为30,设置粒子个数为40,学习因子都为2,惯性权重取0.5,迭代步数取1000,可在命令行直接调用:
>> [xm,fv]=PSO(@fitness,40,2,2,0.5,1000,30)
运行结果:
xm =
0.015182618546981
0.056113959001443
-0.143126140712600
0.022860167253437
-0.127635563896624
0.195225136776349
0.102347870030786
0.352463218131993
0.118609397526905
-0.074127439939679
0.046658256089637
-0.000342509536136
0.098550521522268
-0.054312905711915
0.010692762431556
-0.072566163847757
-0.027799811427568
0.053671249569891
-0.203234994078039
-0.108330195389091
-0.147415725943573
0.038508698225266
0.032561038908752
-0.113458232978920
0.009816961245335
0.118488109121053
0.048798837278477
0.244461601731285
-0.044001734533730
-0.038658398115456
fv =
0.426828387505738
从求解结果可以看出,PSO算法并不能保证找到目标函数的最优情况,这也是随机搜索算法的通病,很多学者在各种优化算法上做了改进,以便增加其搜索的精度。事实上,在其他参数不变的情况下,加大迭代次数,求得的解的精度越高,对于本例若改成迭代次数为5000或10000,其搜索精度会大大提高。
读者对MATLAB解决优化问题感兴趣可以看看这本书《精通MATLAB最优计算》(龚纯),里边除了基本的PSO算法外还有介绍一些改进的PSO算法,以后有机会我也会学习后发文和大家分享。