粒子羣優化算法(PSO)

目錄

一、算法基本流程

1.1算法概述

1.2 算法流程圖

二、代碼實現

三、結果分析


一、算法基本流程

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計算公式如下:

w=wmax-(wmax-wmin)\times t\div maxgen

其中 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=wmax-(wmax-wmin)\times t^{2}\div maxgen^{2}

初始迭代的時候,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時達到最優適應度時收斂次數比較小,算法效果較好。

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章