目錄
一、算法基本流程
1.1算法概述
粒子羣優化(PSO, particle swarm optimization)算法是計算智能領域,除了蟻羣算法,魚羣算法之外的一種羣體智能的優化算法,該算法最早由Kennedy和Eberhart在1995年提出的,該算法源自對鳥類捕食問題的研究。
算法步驟:
(1)初始化所有的微粒,包括它們的位置和速度,把個體的歷史最優pBest設爲當前位置,羣體的最優個體作爲當前的gBest;
(2)每一代的進化中,計算每個粒子的適應度函數值;
(3)對每個微粒,將它的適應值和它經歷過的最好位置pbest的作比較,如果較好,則將其作爲當前的最好位置pBest;
(4)對每個微粒,將它的適應值和全局所經歷最好位置gbest的作比較,如果較好,則重新設置gBest的索引號;
(5)變化微粒的速度和位置;
(6)如未達到結束條件(通常爲足夠好的適應值或達到一個預設最大代數Gmax) ,回到(2),否則輸出gBest並結束。
在每一次迭代過程中,粒子通過個體極值和羣體極值更新自身的速度和位置,更新公式 如下:
1.2 算法流程圖
二、代碼實現
PSO.m
%% 清空環境
clc
clear
%% 參數初始化
%粒子羣算法中的三個參數
c1 = 1.49445;%加速因子
c2 = 1.49445;
w=0.8 %慣性權重
maxgen=1000; % 進化次s數
sizepop=200; %種羣規模
Vmax=1; %限制速度圍
Vmin=-1;
popmax=5; %變量取值範圍
popmin=-5;
dim=10; %適應度函數維數
func=1; %選擇待優化的函數,1爲Rastrigin,2爲Schaffer,3爲Griewank
Drawfunc(func);%畫出待優化的函數,只畫出二維情況作爲可視化輸出
%% 產生初始粒子和速度
for i=1:sizepop
%隨機產生一個種羣
pop(i,:)=popmax*rands(1,dim); %初始種羣
V(i,:)=Vmax*rands(1,dim); %初始化速度
%計算適應度
fitness(i)=fun(pop(i,:),func); %粒子的適應度
end
%% 個體極值和羣體極值
[bestfitness bestindex]=min(fitness);
gbest=pop(bestindex,:); %全局最佳
pbest=pop; %個體最佳
fitnesspbest=fitness; %個體最佳適應度值
fitnessgbest=bestfitness; %全局最佳適應度值
%% 迭代尋優
for i=1:maxgen
fprintf('第%d代,',i);
fprintf('最優適應度%f\n',fitnessgbest);
for j=1:sizepop
%速度更新
V(j,:) = w*V(j,:) + c1*rand*(pbest(j,:) - pop(j,:)) + c2*rand*(gbest - pop(j,:)); %根據個體最優pbest和羣體最優gbest計算下一時刻速度
V(j,find(V(j,:)>Vmax))=Vmax; %限制速度不能太大
V(j,find(V(j,:)<Vmin))=Vmin;
%種羣更新
pop(j,:)=pop(j,:)+0.5*V(j,:); %位置更新
pop(j,find(pop(j,:)>popmax))=popmax;%座標不能超出範圍
pop(j,find(pop(j,:)<popmin))=popmin;
if rand>0.98 %加入變異種子,用於跳出局部最優值
pop(j,:)=rands(1,dim);
end
%更新第j個粒子的適應度值
fitness(j)=fun(pop(j,:),func);
end
for j=1:sizepop
%個體最優更新
if fitness(j) < fitnesspbest(j)
pbest(j,:) = pop(j,:);
fitnesspbest(j) = fitness(j);
end
%羣體最優更新
if fitness(j) < fitnessgbest
gbest = pop(j,:);
fitnessgbest = fitness(j);
end
end
yy(i)=fitnessgbest;
end
%% 結果分析
figure;
plot(yy)
title('最優個體適應度','fontsize',12);
xlabel('進化代數','fontsize',12);ylabel('適應度','fontsize',12);
Rastrigin.m
圖像爲:
function y = Rastrigin(x)
% Rastrigin函數
% 輸入x,給出相應的y值,在x = ( 0 , 0 ,…, 0 )處有全局極小點0.
% 編制人:
% 編制日期:
[row,col] = size(x);
if row > 1
error( ' 輸入的參數錯誤 ' );
end
y =sum(x.^2-10*cos(2*pi*x)+10);
%y =-y;
Schaffer.m
函數寫法:
此函數在(0,...,0)處有最大值1,因此不需要取相反數。
圖像爲:
function y=Schaffer(x)
[row,col]=size(x);
if row>1
error('輸入的參數錯誤');
end
y1=x(1,1);
y2=x(1,2);
temp=y1^2+y2^2;
y=0.5-(sin(sqrt(temp))^2-0.5)/(1+0.001*temp)^2;
%y=-y;
Griewank.m
圖像爲:
function y=Griewank(x)
%Griewan函數
%輸入x,給出相應的y值,在x=(0,0,…,0)處有全局極小點0.
%編制人:
%編制日期:
[row,col]=size(x);
if row>1
error('輸入的參數錯誤');
end
y1=1/4000*sum(x.^2);
y2=1;
for h=1:col
y2=y2*cos(x(h)/sqrt(h));
end
y=y1-y2+1;
%y=-y;
fun.m
函數用於計算粒子適應度值,選擇待優化的函數,1爲Rastrigin,2爲Schaffer,3爲Griewank
function y = fun(x,label)
%x input 輸入粒子
%y output 粒子適應度值
if label==1
y=Rastrigin(x);
elseif label==2
y=Schaffer(x);
else
y= Griewank(x);
end
fun1.m
function y = fun1(x)
%函數用於計算粒子適應度值
%x input 輸入粒子
%y output 粒子適應度值
y=-20*exp(-0.2*sqrt((x(1)^2+x(2)^2)/2))-exp((cos(2*pi*x(1))+cos(2*pi*x(2)))/2)+20+exp(1);
%y=x(1)^2-10*cos(2*pi*x(1))+10+x(2)^2-10*cos(2*pi*x(2))+10;
Drawfunc.m
畫出待優化的函數,只畫出二維情況作爲可視化輸出
function Drawfunc(label)
x=-5:0.05:5;%41列的向量
if label==1
y = x;
[X,Y] = meshgrid(x,y);
[row,col] = size(X);
for l = 1 :col
for h = 1 :row
z(h,l) = Rastrigin([X(h,l),Y(h,l)]);
end
end
surf(X,Y,z);
shading interp
xlabel('x1-axis'),ylabel('x2-axis'),zlabel('f-axis');
title('mesh');
end
if label==2
y = x;
[X,Y] = meshgrid(x,y);
[row,col] = size(X);
for l = 1 :col
for h = 1 :row
z(h,l) = Schaffer([X(h,l),Y(h,l)]);
end
end
surf(X,Y,z);
shading interp
xlabel('x1-axis'),ylabel('x2-axis'),zlabel('f-axis');
title('mesh');
end
if label==3
y = x;
[X,Y] = meshgrid(x,y);
[row,col] = size(X);
for l = 1 :col
for h = 1 :row
z(h,l) = Griewank([X(h,l),Y(h,l)]);
end
end
surf(X,Y,z);
shading interp
xlabel('x1-axis'),ylabel('x2-axis'),zlabel('f-axis');
title('mesh');
end
PSOMutation.m
%% 清空環境
clc
clear
%% 參數初始化
%粒子羣算法中的兩個參數
c1 = 1.49445;
c2 = 1.49445;
maxgen=500; % 進化次數
sizepop=100; %種羣規模
Vmax=1;
Vmin=-1;
popmax=5;
popmin=-5;
%% 產生初始粒子和速度
for i=1:sizepop
%隨機產生一個種羣
pop(i,:)=5*rands(1,2); %初始種羣
V(i,:)=rands(1,2); %初始化速度
%計算適應度
fitness(i)=fun(pop(i,:)); %染色體的適應度
end
%% 個體極值和羣體極值
[bestfitness bestindex]=min(fitness);
zbest=pop(bestindex,:); %全局最佳
gbest=pop; %個體最佳
fitnessgbest=fitness; %個體最佳適應度值
fitnesszbest=bestfitness; %全局最佳適應度值
%% 迭代尋優
for i=1:maxgen
for j=1:sizepop
%速度更新
V(j,:) = V(j,:) + c1*rand*(gbest(j,:) - pop(j,:)) + c2*rand*(zbest - pop(j,:));
V(j,find(V(j,:)>Vmax))=Vmax;
V(j,find(V(j,:)<Vmin))=Vmin;
%種羣更新
pop(j,:)=pop(j,:)+0.5*V(j,:);
pop(j,find(pop(j,:)>popmax))=popmax;
pop(j,find(pop(j,:)<popmin))=popmin;
if rand>0.98
pop(j,:)=rands(1,2);
end
%適應度值
fitness(j)=fun(pop(j,:));
end
for j=1:sizepop
%個體最優更新
if fitness(j) < fitnessgbest(j)
gbest(j,:) = pop(j,:);
fitnessgbest(j) = fitness(j);
end
%羣體最優更新
if fitness(j) < fitnesszbest
zbest = pop(j,:);
fitnesszbest = fitness(j);
end
end
yy(i)=fitnesszbest;
end
%% 結果分析
plot(yy)
title('最優個體適應度','fontsize',12);
xlabel('進化代數','fontsize',12);ylabel('適應度','fontsize',12);
三、結果分析
POS.m運行結果
最優個體適應度最接近於零時算法達到很好
算法中的參數:
%粒子羣算法中的三個參數
加速因子
c1 向自身推進的加速權值
c2 向全局推進的加速權值
w 慣性權重
sizepop 種羣規模
dim 適應度函數維數
初始時設置:c1 = 1.49445,c2 = 1.49445,w = 0.8,sizepop=200,dim=10
(1)c1 = 1.49445,c2 = 1.49445,sizepop=200,dim=10,改變慣性權重的值 w
w | 適應度平均值 |
0.8 | 3.581852 |
0.7 | 2.586893 |
0.6 | 2.967745 |
0.4 | 1.893848 |
w關係到前一速度對當前速度的影響,一般取值在0.9~0.4。因初始種羣是隨機產生的,當權重w固定爲某一個值的時候,我們可以用多次結果取平均值的方法來處理數據。
(2)利用線性遞減的函數設置w從0.9到0.4變化,觀察記錄這時多個結果不同
典型線性遞減策略的w計算公式如下:
其中 wmax是慣性權重最大值,wmin是慣性權重最小值,t 是當前迭代次數,是個變量,
maxgen是總共迭代次數,是常量,實驗中取 1000。
當初始迭代時,慣性權重w比較大,反應在速度v的計算公式上(V(j,:) = w*V(j,:) + c1*rand*(pbest(j,:) - pop(j,:)) + c2*rand*(gbest - pop(j,:)))可以看出初始迭代的時候粒子的速度比較大,具有很好的全局搜索能力,而局部搜索能力較弱。隨着迭代次數的累加,w的值越來越小,粒子的速度也越來越小,此時粒子具有很好的局部搜索能力,而全局搜索能力較弱。但是由於斜率恆定,所以速度的改變總是保持同一水平。
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 平均適應度 | |
1 | 3.979836 | 3.979836 | 0 | 1.989918 | 2.538381 | 4.974795 | 6.964713 | 0 | 5.969754 | 4.974795 | 3.537203 |
2 | 0 | 0.000009 | 0.994962 | 5.969754 | 3.979836 | 0 | 0 | 4.974795 | 4.977137 | 0.995012 | 2.189151 |
3 | 0.994959 | 6.964713 | 4.974795 | 1.048167 | 4.974795 | 5.969754 | 0.994959 | 3.991431 | 2.984877 | 2.984877 | 3.588333 |
在迭代尋找最優的代碼循環裏利用公式來取慣性權重w:
%% 迭代尋優
for i=1:maxgen
fprintf('第%d代,',i);
fprintf('最優適應度%f\n',fitnessgbest);
for j=1:sizepop
%速度更新
V(j,:) = w*V(j,:) + c1*rand*(pbest(j,:) - pop(j,:)) + c2*rand*(gbest - pop(j,:)); %根據個體最優pbest和羣體最優gbest計算下一時刻速度
V(j,find(V(j,:)>Vmax))=Vmax; %限制速度不能太大
V(j,find(V(j,:)<Vmin))=Vmin;
%種羣更新
pop(j,:)=pop(j,:)+0.5*V(j,:); %位置更新
pop(j,find(pop(j,:)>popmax))=popmax;%座標不能超出範圍
pop(j,find(pop(j,:)<popmin))=popmin;
if rand>0.98 %加入變異種子,用於跳出局部最優值
pop(j,:)=rands(1,dim);
end
%更新第j個粒子的適應度值
fitness(j)=fun(pop(j,:),func);
end
for j=1:sizepop
%個體最優更新
if fitness(j) < fitnesspbest(j)
pbest(j,:) = pop(j,:);
fitnesspbest(j) = fitness(j);
end
%羣體最優更新
if fitness(j) < fitnessgbest
gbest = pop(j,:);
fitnessgbest = fitness(j);
end
end
yy(i)=fitnessgbest;
w=wmax-(wmax-wmin)*i/1000;
end
線性微分遞減策略的w的計算公式如下:
初始迭代的時候,w變化緩慢,有利於在初始迭代時尋找滿足條件的局部最優值,在接近最大迭代次數時,w變化較快,在尋找到局部最優值之後能夠快速地收斂逼近於全局最優值,提高運算效率。
(3)其他參數不變,只改變適應度函數維度dim:
dim | 最優適應度 | 收斂(次) |
5 | 0 | 469 |
6 | 0 | 697 |
8 | 0 | 752 |
10 | 0 | 483 |
pop(i,:)=popmax*rands(1,dim); %初始種羣
V(i,:)=Vmax*rands(1,dim); %初始化速度
適應度函數維度用於初始化種羣和速度,以及後面若是算法陷入局部最優時加入的變異因子。當dim越大,初始種羣和速度比較大的機率高。實驗取dim=5或者dim=10時迭代收斂得比較快。
(4)其他參數不變,只c1、c2改變
適應度 | c2=1.08324 | c2=1.49445 | c2=1.99857 |
c1=1.08324 | 3.979836 | 0.994959 | 3.979836 |
c1=1.49445 | 3.979836 | 1.989918 | 4.974795 |
c1=1.99857 | 5.969763 | 2.984877 | 1.989918 |
可以看出在此目標函數中,相對三個取值中,c1取1.08324,c2取1.49445,適應度的值更接近於0。
(5)其他參數不變,改變種羣規模sizepop
sizepop | 最優適應度 | 達到最優適應度時收斂次數 | 總用時 |
100 | 0 | 375 | 6.041 s |
200 | 0 | 530 | 8.334 s |
300 | 0 | 115 | 12.173 s |
400 | 0 | 87 | 14.392 s |
500 | 0 | 523 | 18.376 s |
600 | 0 | 239 | 20.882 s |
種羣規模sizepop影響算法的搜索能力和計算量。當種羣規模越大時,達到最優適應度所用的時間越長,此目標函數中種羣規模設置在300或400時達到最優適應度時收斂次數比較小,算法效果較好。