【初學者必看】粒子羣算法(PSO)詳細介紹:附加matlab代碼可直接運行

一 算法原理

粒子羣算法(PSO)是由Kennedy 和Eberhart等於1995 年開發的一種演化計算技術, 來源於Millonas 對一個簡化社會模型的模擬。其中“羣( swarm )”來源於粒子羣符合在開發應用於人工生命(artificiallife) 的模型時所提出的羣體智能的5個基本原則。而“粒子(particle)”則是一個折衷的選擇,因爲既需要將羣體中的成員描述爲沒有質量、沒有體積的,同時也需要描述它的速度和加速狀態。由於PSO 算法概念簡單,實現容易,短短几年時間,
PSO 算法便獲得了很大的發展,並在一些領域得到應用。 PSO 模擬鳥羣的捕食行爲。一羣鳥在隨機搜索食物,在這個區域裏只有一塊食物。所有的鳥都不知道食物在那裏。但是他們知道當前的位置離食物還有多遠。那麼找到食物的最優策略是什麼呢。最簡單有效的就是搜尋目前離食物最近的鳥的周圍區域。 PSO 從這種模型中得到啓示並用於解決優化問題。PSO 中,每個優化問題的解都是搜索空間中的一隻鳥。我們稱之爲“粒子”。所有的粒子都有一個由被優化的函數決定的適應值(fitness value),每個粒子還有一個速度決定他們飛翔的方向和距離。然後粒子們就追隨當前的最優粒子在解空間中搜索。 PSO 初始化爲一羣隨機粒子(隨機解),然後通過迭代找到最優解,在每一次迭代中,粒子通過跟蹤兩個“極值”來更新自己。第一個就是粒子本身所找到的最優解,這個解叫做個體極值 p Best,另一個極值是整個種羣目前找到的最優解,這個極值是全局極值 g Best。另外也可以不用整個種羣而只是用其中一部分最優粒子的鄰居,那麼在所有鄰居中的極值就是局部極值。 PSO 算法與其他演化算法相似, 也是基於羣體的, 根據對環境的適應度將羣體中的個體移動到好的區域,然而它不像其他演化算法那樣對個體使用演化算子, 而是將每個個體看作n維搜索空間中的一個沒有體積的微粒(點),在搜索空間中以一定的速度飛行。這個速度根據它本身的飛行經驗以及同伴的飛行經驗進行動態調整。

二 PSO算法過程

1 種羣隨機初始化。
2 對種羣內每一個個體計算適應值(fitness value)。適應值與最優解距離有關。
3 種羣根據適應值進行復制
4 如果終止條件滿足的話,就停止,否則轉步驟2
在這裏插入圖片描述

從以上步驟,我們可以看到 PSO 和進化算法有很多共同之處。兩者都隨機初始化種羣,而且都使用適應值來評價系統,而且都根據適應值來進行一定的隨機搜索。兩個系統都不是保證一定找到最優解。但是,PSO 沒有遺傳操作如交叉(crossover)和變異(mutation),而是根據自己的速度來決定搜索。粒子還有一個重要的特點,就是有記憶。 與進化算法比較,
PSO 的信息共享機制是很不同的。在進化算法中,染色體(chromosomes) 互相共享信息,所以整個種羣的移動是比較均勻的向最優區域移動。在 PSO 中, 只有 gBest (or pBest) 給出信息給其他的粒子,這是單向的信息流動。整個搜索更新過程是跟隨當前最優解的過程。與進化算法比較, 在大多數的情況下,所有的粒子可能更快的收斂於最優解。研究表明 PSO 是一種很有潛力的神經網絡算法,同時 PSO 速度比較快而且可以得到比較好的結果。

三 參數設定

種羣數量:粒子羣算法的最大特點就是速度快,因此初始種羣取50-1000都是可以的,雖然初始種羣越大收斂性會更好,不過太大了也會影響速度;
迭代次數:一般取100~4000,太少解不穩定,太多浪費時間。對於複雜問題,進化代數可以相應地提高;
慣性權重:該參數反映了個體歷史成績對現在的影響,一般取0.5~1;
學習因子:一般取0~4,此處要根據自變量的取值範圍來定,並且學習因子分爲個體和羣體兩種;
空間維數:粒子搜索的空間維數即爲自變量的個數。
位置限制:限制粒子搜索的空間,即自變量的取值範圍,對於無約束問題此處可以省略。
速度限制:如果粒子飛行速度過快,很可能直接飛過最優解位置,但是如果飛行速度過慢,會使得收斂速度變慢,因此設置合理的速度限制就很有必要了。

四 算法評價

粒子羣算法是一門新興算法,此算法與遺傳算法有很多相似之處,其收斂於全局最優解的概率很大。
①相較於傳統算法計算速度非常快,全局搜索能力也很強;
②PSO對於種羣大小不十分敏感,所以初始種羣設爲500-1000,速度影響也不大;
③粒子羣算法適用於連續函數極值問題,對於非線性、多峯問題均有較強的全局搜索能力。

五 算法驗證

下面我們用一個例子來幫助理解,對於函數 f=xsin(x)cos(2x)-2xsin(3x) ,求其在區間[0,20]上該函數的最大值。首先我們需要畫出函數的圖像,如下圖:
在這裏插入圖片描述
多峯問題對於算法的檢驗效果最佳,而上圖顯然是一個簡單的非等距、非等高的多峯一元函數。

初始化種羣

已知位置限制[0,20],由於一維問題較爲簡單,因此可以取初始種羣N 爲50,迭代次數爲100,當然空間維數d 也就是1。
位置和速度的初始化即在位置和速度限制內隨機生成一個N x d 的矩陣,對於此題,位置初始化也就是在020內隨機生成一個50x1的數據矩陣,而對於速度則不用考慮約束,一般直接在01內隨機生成一個50x1的數據矩陣。
此處的位置約束也可以理解爲位置限制,而速度限制是保證粒子步長不超限制的,一般設置速度限制爲[-1,1]。
粒子羣的另一個特點就是記錄每個個體的歷史最優和種羣的歷史最優,因此而二者對應的最優位置和最優值也需要初始化。其中每個個體的歷史最優位置可以先初始化爲當前位置,而種羣的歷史最優位置則可初始化爲原點。對於最優值,如果求最大值則初始化爲負無窮,相反地初始化爲正無窮。
每次搜尋都需要將當前的適應度和最優解同歷史的記錄值進行對比,如果超過歷史最優值,則更新個體和種羣的歷史最優位置和最優解。
通過之前的參數設定可以得到如下的初始分佈圖:
在這裏插入圖片描述

速度與位置的更新

    速度和位置更新是粒子羣算法的核心,其原理表達式和更新方式如下:

在這裏插入圖片描述

在這裏插入圖片描述
每次更新完速度和位置都需要考慮速度和位置的限制,需要將其限制在規定範圍內,此處僅舉出一個常規方法,即將超約束的數據約束到邊界(當位置或者速度超出初始化限制時,將其拉回靠近的邊界處)。當然,你不用擔心他會停住不動,因爲每個粒子還有慣性和其他兩個參數的影響。

matlab代碼如下

clc;clear;close all;
%% 初始化種羣
f= @(x)x .* sin(x) .* cos(2 * x) - 2 * x .* sin(3 * x); % 函數表達式
figure(1);ezplot(f,[0,0.01,20]);
N = 50;                         % 初始種羣個數
d = 1;                          % 空間維數
ger = 100;                      % 最大迭代次數     
limit = [0, 20];                % 設置位置參數限制
vlimit = [-1, 1];               % 設置速度限制
w = 0.8;                        % 慣性權重
c1 = 0.5;                       % 自我學習因子
c2 = 0.5;                       % 羣體學習因子 
for i = 1:d
    x = limit(i, 1) + (limit(i, 2) - limit(i, 1)) * rand(N, d);%初始種羣的位置
end
v = rand(N, d);                  % 初始種羣的速度
xm = x;                          % 每個個體的歷史最佳位置
ym = zeros(1, d);                % 種羣的歷史最佳位置
fxm = zeros(N, 1);               % 每個個體的歷史最佳適應度
fym = -inf;                      % 種羣歷史最佳適應度
hold on
plot(xm, f(xm), 'ro');title('初始狀態圖');
figure(2)
%% 羣體更新
iter = 1;
record = zeros(ger, 1);          % 記錄器
while iter <= ger
     fx = f(x) ; % 個體當前適應度   
     for i = 1:N      
        if fxm(i) < fx(i)
            fxm(i) = fx(i);     % 更新個體歷史最佳適應度
            xm(i,:) = x(i,:);   % 更新個體歷史最佳位置
        end 
     end
if fym < max(fxm)
        [fym, nmax] = max(fxm);   % 更新羣體歷史最佳適應度
        ym = xm(nmax, :);      % 更新羣體歷史最佳位置
 end
    v = v * w + c1 * rand * (xm - x) + c2 * rand * (repmat(ym, N, 1) - x);% 速度更新
    % 邊界速度處理
    v(v > vlimit(2)) = vlimit(2);
    v(v < vlimit(1)) = vlimit(1);
    x = x + v;% 位置更新
    % 邊界位置處理
    x(x > limit(2)) = limit(2);
    x(x < limit(1)) = limit(1);
    record(iter) = fym;%最大值記錄
     x0 = 0 : 0.01 : 20;
     plot(x0, f(x0), 'b-', x, f(x), 'ro');title('狀態位置變化')
     pause(0.1)
    iter = iter+1;
end
figure(3);plot(record);title('收斂過程')
x0 = 0 : 0.01 : 20;
figure(4);plot(x0, f(x0), 'b-', x, f(x), 'ro');title('最終狀態位置')
disp(['最大值:',num2str(fym)]);
disp(['變量取值:',num2str(ym)]);

在這裏插入圖片描述

由上圖可以看出算法已成功找出了最優解,其最優解爲18.3014,而其最大值爲32.1462。
如果想看粒子羣算法中粒子的搜索過程的可以將代碼中註釋掉的三行代碼放上去。效果是這樣的

在這裏插入圖片描述

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