同進化算法(見博客《[Evolutionary Algorithm] 進化算法簡介》,進化算法是受生物進化機制啟發而產生的一系列算法)和人工神經網絡算法(Neural Networks,簡稱NN,神經網絡是從信息處理角度對人腦的神經元網絡系統進行了模擬的相關算法)一樣,群體智能優化算法也屬於一種生物啟發式方法,它們三者可以稱為是人工智能領域的三駕馬車(PS:實際上除了上述三種算法還有一些智能算法應用也很廣泛,比如模擬金屬物質熱力學退火過程的模擬退火算法(Simulated Algorithm,簡稱SA),模擬人體免疫系統在抗原刺激下產生抗體過程的人工免疫系統算法(Artificial Immune System,簡稱AIS)等,但是相對三者而言,模擬退火和人工免疫系統算法已逐漸處於低潮期)。群體智能優化算法主要模擬了昆蟲、獸群、鳥群和魚群的群集行為,這些群體按照一種合作的方式尋找食物,群體中的每個成員通過學習它自身的經驗和其他成員的經驗來不斷地改變搜索的方向。群體智能優化算法的突出特點就是利用了種群的群體智慧進行協同搜索,從而在解空間內找到最優解。
1. 常見的群體智能優化算法分類
常見的群體智能優化算法主要有如下幾類:
(1)蟻群算法(Ant Colony Optimization,簡稱ACO)[1992年提出];
(2)粒子群優化算法(Particle Swarm Optimization,簡稱PSO)[1995年提出](簡單易於實現,也是目前應用最為廣泛的群體智能優化算法);
(3)菌群優化算法(Bacterial Foraging Optimization,簡稱BFO)[2002年提出];
(4)蛙跳算法(Shuffled Frog Leading Algorithm,簡稱SFLA)[2003年提出];
(5)人工蜂群算法(Artificial Bee Colony Algorithm,簡稱ABC)[2005年提出];
除了上述幾種常見的群體智能算法以外,還有一些並不是廣泛應用的群體智能算法,比如螢火蟲算法、布谷鳥算法、蝙蝠算法以及磷蝦群算法等等。
2. 粒子群優化算法思想
由於博主對粒子群優化算法比較熟悉,在碩士期間也進行了比較系統的學習,所以利用本博文系統的介紹一下應用最為廣泛的PSO算法。
粒子群優化算法是在1995年由Eberhart博士和Kennedy博士一起提出的,它源於對鳥群捕食行為的研究。它的基本核心是利用群體中的個體對信息的共享從而使得整個群體的運動在問題求解空間中產生從無序到有序的演化過程,從而獲得問題的最優解。我們可以利用一個有關PSO的經典描述來對PSO算法進行一個直觀的描述。設想這么一個場景:一群鳥進行覓食,而遠處有一片玉米地,所有的鳥都不知道玉米地到底在哪里,但是它們知道自己當前的位置距離玉米地有多遠。那么找到玉米地的最佳策略,也是最簡單有效的策略就是是搜尋目前距離玉米地最近的鳥群的周圍區域。PSO就是從這種群體覓食的行為中得到了啟示,從而構建的一種優化模型。
在PSO中,每個優化問題的解都是搜索空間中的一只鳥,稱之為“粒子”,而問題的最優解就對應為鳥群要尋找的“玉米地”。所有的粒子都具有一個位置向量(粒子在解空間的位置)和速度向量(決定下次飛行的方向和速度),並可以根據目標函數來計算當前的所在位置的適應值(fitness value),可以將其理解為距離“玉米地”的距離。在每次的迭代中,種群中的粒子除了根據自身的“經驗”(歷史位置)進行學習以外,還可以根據種群中最優粒子的“經驗”來學習,從而確定下一次迭代時需要如何調整和改變飛行的方向和速度。就這樣逐步迭代,最終整個種群的粒子就會逐步趨於最優解。
3. 粒子群優化算法的基本框架
在介紹PSO的算法流程之前,我們寫給出PSO中常用的迭代算子的形式。令$X_{i}=(x_{i1}, x_{i2}, ... , x_{in})$代表粒子$i$的位置向量,$V_{i}=(v_{i1}, v_{i2}, ... , v_{in})$代表粒子$i$的速度向量(其中$n$為優化問題的維度大小),最早版本的粒子群優化算法的迭代算子形式如下:
速度向量迭代公式:
$V_{i}=V_{i}+c_{1}r_{1}(Pbest_{i}-X_{i})+c_{2}r_{2}(Gbest-X_{i})$ (1)
位置向量迭代公式:
$X_{i}=X_{i}+V_{i}$ (2)
其中在公式(1)中,$Pbest_{i}$和$Gbest$分別代表粒子$i$的歷史最佳位置向量和種群歷史最佳位置向量。根據公式(1)(2)可以看出,種群中的粒子通過不斷地向自身和種群的歷史信息進行學習,從而可以找出問題的最優解。
但是,在后續的研究中表明,上述原始的公式中存在一個問題:公式(1)中$V_{i}$的更新太具有隨機性,從而使得整個PSO算法的全局優化能力很強,但是局部搜索能力較差。而實際上,我們需要在算法迭代初期PSO有着較強的全局優化能力,而在算法的后期,整個種群應該具有更強的局部搜索能力。所以根據上述的弊端,Shi和Eberhart通過引入慣性權重修改了公式(1),從而提出了PSO的慣性權重模型:
速度向量迭代公式:
$V_{i}=wV_{i}+c_{1}r_{1}(Pbest_{i}-X_{i})+c_{2}r_{2}(Gbest-X_{i})$ (3)
其中參數$w$稱為是PSO的慣性權重(inertia weight),它的取值介於[0,1]區間,一般應用中均采取自適應的取值方法,即一開始令$w=0.9$,使得PSO全局優化能力較強,隨着迭代的深入,參數$w$進行遞減,從而使得PSO具有較強的局部優化能力,當迭代結束時,$w=0.1$。參數$c_{1}$和$c_{2}$稱為是學習因子(learn factor),一般設置為1.4961;而$r_{1}$和$r_{2}$為介於[0,1]之間的隨機概率值。
整個粒子群優化算法的算法框架如下:
Step 1 種群初始化:可以進行隨機初始化或者根據被優化的問題設計特定的初始化方法,然后計算個體的適應值,從而選擇出個體的局部最優位置向量$Pbest_{i}$和種群的全局最優位置向量$Gbest$。
Step 2 迭代設置:設置迭代次數$g_{max}$,並令當前迭代次數$g=1$;
Step 3 速度更新:根據公式(3)更新每個個體的速度向量;
Step 4 位置更新:根據公式(2)更新每個個體的位置向量;
Step 5 局部位置向量和全局位置向量更新:更新每個個體的$Pbest_{i}$和種群的$Gbest$;
Step 6 終止條件判斷:判斷迭代次數時都達到$g_{max}$,如果滿足,輸出$Gbest$;否則繼續進行迭代,跳轉至Step 3。
對於粒子群優化算法的運用,主要是對速度和位置向量迭代算子的設計。迭代算子是否有效將決定整個PSO算法性能的優劣,所以如何設計PSO的迭代算子是PSO算法應用的研究重點和難點。
4. 對粒子群優化算法中慣性權重的認識
參數$w$被稱之為是慣性權重,顧名思義$w$實際反映了粒子過去的運動狀態對當前行為的影響,就像是我們物理中提到的慣性。如果$w<<1$,從前的運動狀態很少能影響當前的行為,粒子的速度會很快的改變;相反,$w$較大,雖然會有很大的搜索空間,但是粒子很難改變其運動方向,很難向較優位置收斂,由於算法速度的因素,在實際運用中很少這樣設置。也就是說,較高的$w$設置促進全局搜索,較低的$w$設置促進快速的局部搜索。
5. 粒子群優化算法舉例——求解旅行商問題
旅行商問題(Traveling Salesman Problem,TSP)又譯為旅行推銷員問題、貨郎擔問題,簡稱為TSP問題,是最基本的路線問題和最典型的NP難問題,該問題是在尋求單一旅行者由起點出發,通過所有給定的需求點之后,最后再回到原點的最小路徑成本。最早的旅行商問題的數學規划是由Dantzig等人於1959年提出的。
下面為一個TSP問題的數據集,城市個數為50:
1 37 52 2 49 49 3 52 64 4 20 26 5 40 30 6 21 47 7 17 63 8 31 62 9 52 33 10 51 21 11 42 41 12 31 32 13 5 25 14 12 42 15 36 16 16 52 41 17 27 23 18 17 33 19 13 13 20 57 58 21 62 42 22 42 57 23 16 57 24 8 52 25 7 38 26 27 68 27 30 48 28 43 67 29 58 48 30 58 27 31 37 69 32 38 46 33 46 10 34 61 33 35 62 63 36 63 69 37 32 22 38 45 35 39 59 15 40 5 6 41 10 17 42 21 10 43 5 64 44 30 15 45 39 10 46 32 39 47 25 32 48 25 55 49 48 28 50 56 37 51 30 40
50個城市分布圖:
下面為PSO求解旅行商問題的matlab代碼:
主函數main.m:
%% 該文件演示基於TSP-PSO算法 clc;clear %% 載入數據 data=load('eil51.txt') cityCoor=[data(:,2) data(:,3)];%城市坐標矩陣 figure plot(cityCoor(:,1),cityCoor(:,2),'ms','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g') legend('城市位置') ylim([4 78]) title('城市分布圖','fontsize',12) xlabel('km','fontsize',12) ylabel('km','fontsize',12) %ylim([min(cityCoor(:,2))-1 max(cityCoor(:,2))+1]) grid on %% 計算城市間距離 n=size(cityCoor,1); %城市數目 cityDist=zeros(n,n); %城市距離矩陣 for i=1:n for j=1:n if i~=j cityDist(i,j)=((cityCoor(i,1)-cityCoor(j,1))^2+... (cityCoor(i,2)-cityCoor(j,2))^2)^0.5; end cityDist(j,i)=cityDist(i,j); end end nMax=1000; %進化次數 indiNumber=50; %個體數目 individual=zeros(indiNumber,n); %^初始化粒子位置 for i=1:indiNumber individual(i,:)=randperm(n); end %% 計算種群適應度 indiFit=fitness(individual,cityCoor,cityDist); [value,index]=min(indiFit); tourPbest=individual; %當前個體最優 tourGbest=individual(index,:) ; %當前全局最優 recordPbest=inf*ones(1,indiNumber); %個體最優記錄 recordGbest=indiFit(index); %群體最優記錄 xnew1=individual; %% 循環尋找最優路徑 L_best=zeros(1,nMax); for N=1:nMax N %計算適應度值 indiFit=fitness(individual,cityCoor,cityDist); %更新當前最優和歷史最優 for i=1:indiNumber if indiFit(i)<recordPbest(i) recordPbest(i)=indiFit(i); tourPbest(i,:)=individual(i,:); end if indiFit(i)<recordGbest recordGbest=indiFit(i); tourGbest=individual(i,:); end end [value,index]=min(recordPbest); recordGbest(N)=recordPbest(index); %% 交叉操作 for i=1:indiNumber % 與個體最優進行交叉 c1=unidrnd(n-1); %產生交叉位 c2=unidrnd(n-1); %產生交叉位 while c1==c2 c1=round(rand*(n-2))+1; c2=round(rand*(n-2))+1; end chb1=min(c1,c2); chb2=max(c1,c2); cros=tourPbest(i,chb1:chb2); ncros=size(cros,2); %刪除與交叉區域相同元素 for j=1:ncros for k=1:n if xnew1(i,k)==cros(j) xnew1(i,k)=0; for t=1:n-k temp=xnew1(i,k+t-1); xnew1(i,k+t-1)=xnew1(i,k+t); xnew1(i,k+t)=temp; end end end end %插入交叉區域 xnew1(i,n-ncros+1:n)=cros; %新路徑長度變短則接受 dist=0; for j=1:n-1 dist=dist+cityDist(xnew1(i,j),xnew1(i,j+1)); end dist=dist+cityDist(xnew1(i,1),xnew1(i,n)); if indiFit(i)>dist individual(i,:)=xnew1(i,:); end % 與全體最優進行交叉 c1=round(rand*(n-2))+1; %產生交叉位 c2=round(rand*(n-2))+1; %產生交叉位 while c1==c2 c1=round(rand*(n-2))+1; c2=round(rand*(n-2))+1; end chb1=min(c1,c2); chb2=max(c1,c2); cros=tourGbest(chb1:chb2); ncros=size(cros,2); %刪除與交叉區域相同元素 for j=1:ncros for k=1:n if xnew1(i,k)==cros(j) xnew1(i,k)=0; for t=1:n-k temp=xnew1(i,k+t-1); xnew1(i,k+t-1)=xnew1(i,k+t); xnew1(i,k+t)=temp; end end end end %插入交叉區域 xnew1(i,n-ncros+1:n)=cros; %新路徑長度變短則接受 dist=0; for j=1:n-1 dist=dist+cityDist(xnew1(i,j),xnew1(i,j+1)); end dist=dist+cityDist(xnew1(i,1),xnew1(i,n)); if indiFit(i)>dist individual(i,:)=xnew1(i,:); end %% 變異操作 c1=round(rand*(n-1))+1; %產生變異位 c2=round(rand*(n-1))+1; %產生變異位 while c1==c2 c1=round(rand*(n-2))+1; c2=round(rand*(n-2))+1; end temp=xnew1(i,c1); xnew1(i,c1)=xnew1(i,c2); xnew1(i,c2)=temp; %新路徑長度變短則接受 dist=0; for j=1:n-1 dist=dist+cityDist(xnew1(i,j),xnew1(i,j+1)); end dist=dist+cityDist(xnew1(i,1),xnew1(i,n)); if indiFit(i)>dist individual(i,:)=xnew1(i,:); end end [value,index]=min(indiFit); L_best(N)=indiFit(index); tourGbest=individual(index,:); end tourGbest minbest=min(L_best) %% 結果作圖 figure plot(L_best) title('算法訓練過程') xlabel('迭代次數') ylabel('適應度值') grid on figure hold on plot([cityCoor(tourGbest(1),1),cityCoor(tourGbest(n),1)],[cityCoor(tourGbest(1),2),... cityCoor(tourGbest(n),2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g') hold on for i=2:n plot([cityCoor(tourGbest(i-1),1),cityCoor(tourGbest(i),1)],[cityCoor(tourGbest(i-1),2),... cityCoor(tourGbest(i),2)],'ms-','LineWidth',2,'MarkerEdgeColor','k','MarkerFaceColor','g') hold on end legend('規划路徑') scatter(cityCoor(:,1),cityCoor(:,2)); title('規划路徑','fontsize',10) xlabel('km','fontsize',10) ylabel('km','fontsize',10) grid on ylim([4 80])
目標函數:fitness.m
function indiFit=fitness(x,cityCoor,cityDist) %% 該函數用於計算個體適應度值 %x input 個體 %cityCoor input 城市坐標 %cityDist input 城市距離 %indiFit output 個體適應度值 m=size(x,1); n=size(cityCoor,1); indiFit=zeros(m,1); for i=1:m for j=1:n-1 indiFit(i)=indiFit(i)+cityDist(x(i,j),x(i,j+1)); end indiFit(i)=indiFit(i)+cityDist(x(i,1),x(i,n)); end
PSO迭代收斂曲線圖:
PSO求解50個城市的TSP問題最小距離為473.1536,TSP求解規划路徑圖如下:
6. 參考文獻
[1] Eberhart R C and Kennedy J. A new optimizer using particle swarm theory. 1995.
[2] Shi Y and Eberhart R C. A modified particle optimizer. 1998.
[3] Kennedy J. Particle swarm optimization. 2010.