起源:1995年,受到鸟群觅食行为的规律性启发,James Kennedy和Russell Eberhart建立了一个简化算法模型,经过多年改进最终形成了粒子群优化算法(Particle Swarm Optimization, PSO) ,也可称为粒子群算法
特点:粒子群算法具有收敛速度快、参数少、算法简单易实现的优点(对高维度优化问题,比遗传算法更快收敛于最优解)。
基本思想:粒子群算法的思想源于对鸟群觅食行为的研究,鸟群通过集体的信息共享使群体找到最优的目的地。
如下图,设想这样一个场景:鸟群在森林中随机搜索食物,它们想要找到食物量最多的位置。但是所有的鸟都不知道食物具体在哪个位置,只能感受到食物大概在哪个方向。每只鸟沿着自己判定的方向进行搜索,并在搜索的过程中记录自己曾经找到过食物且量最多的位置,同时所有的鸟都共享自己每一次发现食物的位置以及食物的量,这样鸟群就知道当前在哪个位置食物的量最多。在搜索的过程中每只鸟都会根据自己记忆中食物量最多的位置和当前鸟群记录的食物量最多的位置调整自己接下来搜索的方向。鸟群经过一段时间的搜索后就可以找到森林中哪个位置的食物量最多(全局最优解)。
下面的动图很形象地展示了PSO算法的过程:
将鸟群觅食行为和算法原理对应,如下图:
**(1)PSO的基础:**信息的社会共享
(2)粒子的两个属性:速度
和位置
(算法的两个核心要素)
速度表示粒子下一步迭代时移动的方向和距离,位置是所求解问题的一个解。
(3)算法的6个重要参数
假设在 D D D维搜索空间中,有 N N N个粒子,每个粒子代表一个解,则:
第 i i i个粒子的位置为
X i d = ( x i 1 , x x 2 , ⋯ , x i D ) X_{id}=(x_{i1},x_{x2},\cdots,x_{iD}) Xid=(xi1,xx2,⋯,xiD)
第 i i i个粒子的速度(粒子移动的方向和大小)为:
V i d = v i 1 , v i 2 , ⋯ , v i D V_{id}=v_{i1},v_{i2},\cdots,v_{iD} Vid=vi1,vi2,⋯,viD
第 i i i个粒子搜索到的最优诶之(个体最优解)为:
P i d , p b e s t = ( p i 1 , p i 2 , … , p i D ) P_{id,pbest}=(p_{i1},p_{i2},\dots,p_{iD}) Pid,pbest=(pi1,pi2,…,piD)
群体搜索到最优位置(群体最优解)为:
P d , g b e s t = ( p 1 , g b e s t , p 2 , g b e s t , ⋯ , p D , g b e s t ) P_{d,gbest}=(p_{1,gbest},p_{2,gbest},\cdots,p_{D,gbest}) Pd,gbest=(p1,gbest,p2,gbest,⋯,pD,gbest)
第 i i i个粒子搜索到的最优位置的适应值(优化目标函数的值)为:
f p f_p fp–个体历史最优适应值
群体搜索到的最优位置的适应值为:
f g f_g fg-群体历史最优适应值
粒子群规模 N N N
一个正整数,推荐取值范围:[20,1000],简单问题一般取 20 ∼ 40 20\sim40 20∼40,较难或特定类别的问题可以取 100 ∼ 200 100\sim200 100∼200。较小的种群规模容易陷入局部最优;较大的种群规模可以提高收敛性,更快找到全局最优解,但是相应地每次迭代的计算量也会增大;当种群规模增大至一定水平时,再增大将不再有显著的作用。
粒子维度 D D D
粒子搜索的空间维数即为自变量的个数
迭代次数 K K K
推荐取值范围:[50,100],典型取值:60、70、100;这需要在优化的过程中根据实际情况进行调整,迭代次数太小的话解不稳定,太大的话非常耗时,没有必要。
惯性权重 w w w
1998年,Yuhui Shi和Russell Eberhart对基本粒子群算法引入了惯性权重(inertia weight) w w w,并提出动态调整惯性权重以平衡收敛的全局性和收敛速度,该算法被称为标准PSO算法(本文所介绍)
参数 w w w:0.5-0.8, c 1 , c 2 c_1,c_2 c1,c2:0.1-2, v m a x , x m a x v_{max},x_{max} vmax,xmax取决于优化函数
PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解。在每一次的迭代中,粒子通过跟踪两个“极值”(pbest,gbest)来更新自己。在找到这两个最优值后,粒子通过下面的公式来更新自己的速度和位置。
最大速度 v m a x v_{max} vmax:粒子下一步迭代可以移动的最大距离,通常设为粒子(解)的范围宽度。
v i d k + 1 = w v i d k + c 1 r 1 ( p i d , p b e s t k − x i d k ) + c 2 r 2 ( p d , b e s t k − x i d k ) v_{id^{k+1}}=wv_{id}^k+c_1r_1(p_{id,pbest}^k-x_{id}^k)+c_2r_2(p_{d,best}^k-x_{id}^k) vidk+1=wvidk+c1r1(pid,pbestk−xidk)+c2r2(pd,bestk−xidk)
(1)速度更新公式的解释
① 第一项:惯性部分
由惯性权重和粒子自身速度构成,表示粒子对先前自身运动状态的信任。
② 第二项:认知部分
表示粒子本身的思考,即粒子自己经验的部分,可理解为粒子当前位置与自身历史最优位置之间的距离和方向。
③ 第三项:社会部分
表示粒子之间的信息共享与合作,即来源于群体中其他优秀粒子的经验,可理解为粒子当前位置与群体历史最优位置之间的距离和方向。
速度更新公式的参数定义
N N N–粒子群规模, i i i–粒子序号, i = 1 , 2 , ⋯ , N i=1,2,\cdots,N i=1,2,⋯,N
D D D–粒子维度, d d d–粒子维度序号, d = 1 , 2 , ⋯ , D d=1,2,\cdots,D d=1,2,⋯,D
k k k–迭代次数; w w w–惯性权重, c 1 c_1 c1–个体学习因子, c 2 c_2 c2–群体学习因子
r 1 , r 2 r_1,r_2 r1,r2–区间 [ 0 , 1 ] [0,1] [0,1]内的随机数,增加搜索的随机性
v i d k v_{id}^k vidk–粒子 i i i在第 k k k次迭代中第 d d d维的速度向量
x i d k x_{id}^k xidk–粒子 i i i在第 k k k次迭代中第 d d d维的位置向量
p i d , p b e s t k p_{id,pbest}^k pid,pbestk–粒子 i i i在第 k k k次迭代中第 d d d维的历史最优位置,即在第 k k k次迭代后,第 i i i个粒子(个体)搜索得到的最优解
p d , b e s t k p_{d,best}^k pd,bestk–群体在第 k k k次迭代中第 d d d维的历史最优解,即在第 k k k次迭代后,整个粒子群众的最优解
速度的方向
粒子下一步迭代的移动方向 = 惯性方向 + 个体最优方向 + 群体最优方向
x i d k + 1 = x i d k + v i d k + 1 x_{id}^{k+1}=x_{id}^k+v_{id}^{k+1} xidk+1=xidk+vidk+1
题目
求解 f ( x ) = − ( x − 10 ) 2 + x sin ( x ) cos ( 2 x ) − 5 x sin ( 3 x ) f(x)=-(x-10)^2+x\sin(x)\cos(2x)-5x\sin(3x) f(x)=−(x−10)2+xsin(x)cos(2x)−5xsin(3x)的最优解
clc;
clear;
close all;
f= @(x) - (x - 10) .^ 2 + x .* sin(x) .* cos(2 * x) - 5 * x .* sin(3 * x) ; % 适应度函数表达式(求这个函数的最大值)
figure(1);
fplot(f, [0 20], 'b-'); % 画出初始图像
d = 1; % 空间维数(该例子是1维)
N = 15; % 初始种群个数
x_limit = [0, 20]; % 设置位置限制
v_limit = [-1, 1]; % 设置速度限制
x = x_limit(1) + (x_limit(2) - x_limit(1)) * rand(N, d); %初始每个粒子的位置
v = rand(N, d); % 初始每个粒子的速度
pbest = x; % 初始化每个个体的历史最佳位置
gbest = zeros(1, d); % 初始化种群的历史最佳位置 ,创建全0数组
fp_best = zeros(N, 1); % 初始化每个个体的历史最佳适应度 为 0
fg_best = -inf; % 初始化种群历史最佳适应度 为 负无穷
iter = 50; % 最大迭代次数
c1 = 1.6; % 自我学习因子
c2 = 1.8; % 群体学习因子
w=0.4; % 惯性学习因子
hold on;
plot(x, f(x), 'ro');
title('初始状态图');
record = zeros(iter, 1); % 记录器(用于记录 fg_best 的变化过程)
figure(2);
i = 1;
while i <= iter
fx = f(x) ; % 计算个体当前适应度
% 个体寻优
for j = 1:N
if fp_best(j) < fx(j) % 第j个个体的历史(最优)适应度小于当前的适应度则更新
fp_best(j) = fx(j); % 更新个体历史最佳适应度
pbest(j) = x(j); % 更新个体历史最佳位置
end
end
% 群体寻优
if fg_best < max(fp_best) % 第i次迭代,种群历史最优适应值,小于当前迭代次数的群体最优适应值则更新
[fg_best,ind_max] = max(fp_best); % 更新群体历史最佳适应度
gbest = pbest(ind_max); % 更新群体历史最佳位置,其中 ind_max 是最大值所在的下标
% 注:将上面的两个式子换成下面两个是不可以的
% [gbest, ind_max] = max(pbest); % 更新群体历史最佳位置,其中 ind_max 是最大值所在的下标
% fg_best = fp_best(ind_max); % 更新群体历史最佳适应度
end
v = v * w + c1 * rand() * (pbest - x) + c2 * rand() * (repmat(gbest, N, 1) - x); % 速度更新
% 注: repmat(A,r1,r2):可将矩阵 扩充 为每个单位为A的r1*r2的矩阵
% 边界速度处理
v(v > v_limit(2)) = v_limit(2);
v(v < v_limit(1)) = v_limit(1);
x = x + v;% 位置更新
% 边界位置处理
x(x > x_limit(2)) = x_limit(2);
x(x < x_limit(1)) = x_limit(1);
record(i) = fg_best;%最大值记录
% 画动态展示图
zuo_x = 0 : 0.01 : 20;
plot(zuo_x, f(zuo_x), 'b-', x, f(x), 'ro');
title('状态位置变化')
pause(0.1)
i = i + 1;
% if mod(i,10) == 0 % 显示进度
% i
% end
end
figure(3);
plot(record);
title('收敛过程');
zuo_x = 0 : 0.01 : 20;
figure(4);
plot(zuo_x, f(zuo_x), 'b-', x, f(x), 'ro');
title('最终状态图')
disp(['最佳适应度:',num2str(fg_best)]);
disp(['最佳粒子的位置x:',num2str(gbest)]);
% 主调用函数,以下新建一个文件,命名为f_xy
% function z = f_xy(x, y)
% % 适应度函数
% z = - x.^2 - y.^2 + 10*cos(2*pi*x) + 10*cos(2*pi*y) + 100;
% end
clc;
clear;
close all;
[ZuoBiao_x, ZuoBiao_y] = meshgrid(-10:0.1:10,-5:0.1:5); % 产生二维坐标
ZuoBiao_z = f_xy(ZuoBiao_x, ZuoBiao_y);
figure(1);
s = mesh(ZuoBiao_x, ZuoBiao_y, ZuoBiao_z); % 画网格曲面图
s.FaceColor = 'flat'; % 修改网格图的属性
% 初始化种群
N = 100; % 初始种群个数
D = 2; % 空间维数
iter = 50; % 迭代次数
x_limit = [-10, 10; -5, 5]; % 位置限制
v_limit = [ -2, 2; -1, 1]; % 速度限制
x = zeros(N, D);
for i = 1:D
x(:,i) = x_limit(i, 1) + (x_limit(i, 2) - x_limit(i, 1)) * rand(N, 1);%初始种群的位置
end
v(:,1) = rands(N, 1) * 1; % 初始种群x方向的速度
v(:,2) = rands(N, 1) * 2; % 初始种群y方向的速度
p_best = x; % (初始化)每个个体的历史最佳位置
f_best = zeros(1, D); % (初始化)种群的历史最佳位置
fp_best = zeros(N, 1) - inf; % (初始化)每个个体的历史最佳适应度为负无穷
fg_best = -inf; % (初始化)种群历史最佳适应度为负无穷
w = 0.8; % 惯性权重
c1 = 0.5; % 自我学习因子
c2 = 0.5; % 群体学习因子
figure(2);
s = mesh(ZuoBiao_x, ZuoBiao_y, ZuoBiao_z); % 画网格曲面图
s.FaceColor = 'flat'; % 修改网格图的属性
hold on;
plot3(x(:,1), x(:,2),f_xy(x(:,1), x(:,2)), 'ro');
title('初始状态图');
figure(3);
i = 1;
record = zeros(iter, 1); % 记录器
while i <= iter
fx = f_xy(x(:,1), x(:,2)); % 个体当前适应度
for j = 1:N
if fp_best(j) < fx(j) % 记录最大值
fp_best(j) = fx(j); % 更新个体历史最佳适应度
p_best(j,:) = x(j,:); % 更新个体历史最佳位置
end
end
if fg_best < max(fp_best)
[fg_best, ind_max] = max(fp_best); % 更新群体历史最佳适应度
f_best = p_best(ind_max, :); % 更新群体历史最佳位置
end
v = v * w + c1 * rand() * (p_best - x) + c2 * rand() * (repmat(f_best, N, 1) - x); % 速度更新
% 速度处理
for t=1:N
for k=1:D
if v(t,k) > v_limit(k,2) % 超速处理
v(t,k) = v_limit(k,2);
elseif v(t,k) < v_limit(k,1) % 慢速处理
v(t,k) = v_limit(k,1);
end
end
end
x = x + v; % 位置更新
% 边界处理
for t=1:N
for k=1:D
if x(t,k) > x_limit(k,2) % 超过边界上限
x(t,k) = x_limit(k,2);
elseif x(t,k) < x_limit(k,1) % 超过边界下限
x(t,k) = x_limit(k,1);
end
end
end
record(i) = fg_best; % 最大值记录
i = i + 1;
if mod(i,10) == 0
i % 收敛进度输出
end
pause(0.1)
end
figure(4)
plot(record);
title('收敛过程');
% 画最终状态图
figure(5);
[ZuoBiao_x, ZuoBiao_y] = meshgrid(-10:0.1:10,-5:0.1:5); % 产生二维坐标
s = mesh(ZuoBiao_x, ZuoBiao_y, ZuoBiao_z); % 画网格曲面图
s.FaceColor = 'flat'; % 修改网格图的属性
hold on;
scatter3(x(:,1), x(:,2), f_xy(x(:,1), x(:,2)), 'ro');
title('最终状态图')
disp(['最大值:',num2str(fg_best)]);
disp(['变量取值:',num2str(f_best)]);
% 下面一段用来输出 粒子群最佳适应度的排行榜
[socre,ind] = sort(fp_best, 'descend') % 降序排序
DaAn = zeros(3,2);
for i=1:N
row = ind(i);
DaAn(i,:) = p_best(row,:);
end
参考资料
粒子群优化算法(Particle Swarm Optimization, PSO)的详细解读 - 知乎 (zhihu.com)
粒子群优化算法(PSO)_Mxxxx12的博客-CSDN博客_粒子群优化
粒子群优化算法(PSO)_Handsome_Zpp的博客-CSDN博客_粒子群优化