簡介
定義
粒子群優化算法(Particle Swarm optimization,PSO)又翻譯為粒子群算法、微粒群算法、或微粒群優化算法。是通過模擬鳥群覓食行為而發展起來的一種基於群體協作的隨機搜索算法。通常認為它是群集智能 (Swarm intelligence, SI) 的一種。它可以被納入多主體優化系統(Multiagent Optimization System, MAOS).
模擬捕食
SO模擬鳥群的捕食行為。一群鳥在隨機搜索食物,在這個區域里只有一塊食物。所有的鳥都不知道食物在那里。但是他們知道當前的位置離食物還有多遠。那么找到食物的最優策略是什么呢。最簡單有效的就是搜尋離食物最近的鳥的周圍區域。
抽象成粒子
PSO中,每個優化問題的解都是搜索空間中的一只鳥。我們稱之為“粒子”。所有的粒子都有一個由被優化的函數決定的適應值(fitnessvalue),每個粒子還有一個速度決定他們飛翔的方向和距離。然后粒子們就追隨當前的最優粒子在解空間中搜索。
更新
PSO初始化為一群隨機粒子(隨機解),然后通過迭代找到最優解,在每一次疊代中,粒子通過跟蹤兩個“極值”來更新自己。第一個就是粒子本身所找到的最優解,這個解叫做個體極值pBest,另一個極值是整個種群找到的最優解,這個極值是全局極值gBest。另外也可以不用整個種群而只是用其中一部分最優粒子的鄰居,那么在所有鄰居中的極值就是局部極值。
在找到這兩個最優值時,粒子根據如下的公式來更新自己的速度和新的位置:
再來看一個公式:
公式二和公式三被視為標准PSO算法。
學習因子c1、c2分析
公式(2)和(3)中pbest和gbest分別表示微粒群的局部和全局最優位置。
1)當C1=0時,則粒子沒有了認知能力,變為只有社會的模型(social-only):
稱為全局PSO算法。粒子有擴展搜索空間的能力,具有較快的收斂速度,但由於缺少局部搜索,對於復雜問題比標准PSO 更易陷入局部最優。
2)當C2=0時,則粒子之間沒有社會信息,模型變為只有認知(cognition-only)模型
稱為局部PSO算法。由於個體之間沒有信息的交流,整個群體相當於多個粒子進行盲目的隨機搜索,收斂速度慢,因而得到最優解的可能性小。
標准PSO算法流程
1)初始化一群微粒(群體規模為N),包括隨機位置和速度;
2)評價每個微粒的適應度;
3)對每個微粒,將其適應值與其經過的最好位置pbest作比較,如果較好,則將其作為當前的最好位置pbest;
4)對每個微粒,將其適應值與其經過的最好位置gbest作比較,如果較好,則將其作為當前的最好位置gbest;
5)根據公式(2)、(3)調整微粒速度和位置;
6)未達到結束條件則轉第2步。
迭代終止條件根據具體問題一般選為最大迭代次數Gk或(和)微粒群迄今為止搜索到的最優位置滿足預定最小適應閾值。
應用舉例
這里用一個簡單的例子說明PSO訓練神經網絡的過程。這個例子使用分類問題的基准函數 (Benchmark function)IRIS數據集。(Iris 是一種鳶尾屬植物) 在數據記錄中,每組數據包含Iris花的四種屬性:萼片長度,萼片寬度,花瓣長度,和花瓣寬度,三種不同的花各有50組數據. 這樣總共有150組數據或模式。
我們用3層的神經網絡來做分類。有四個輸入和三個輸出。所以神經網絡的輸入層有4個節點,輸出層有3個節點我們也可以動態調節隱含層節點的數目,不過這里我們假定隱含層有6個節點。我們也可以訓練神經網絡中其他的參數。不過這里我們只是來確定網絡權重。粒子就表示神經網絡的一組權重,應該是4*6+6*3=42個參數。權重的范圍設定為[-100,100] (這只是一個例子,在實際情況中可能需要試驗調整).在完成編碼以后,我們需要確定適應函數。對於分類問題,我們把所有的數據送入神經網絡,網絡的權重有粒子的參數決定。然后記錄所有的錯誤分類的數目作為那個粒子的適應值。我們就利用PSO來訓練神經網絡來獲得盡可能低的錯誤分類數目。PSO本身並沒有很多的參數需要調整。所以在實驗中只需要調整隱含層的節點數目和權重的范圍以取得較好的分類效果。
參數設置
PSO中並沒有許多需要調節的參數,下面列出了這些參數以及經驗設置。
- 粒子數: 一般取 20–40. 其實對於大部分的問題10個粒子已經足夠可以取得好的結果, 不過對於比較難的問題或者特定類別的問題, 粒子數可以取到100 或 200
- 粒子的長度: 這是由優化問題決定, 就是問題解的長度
- 粒子的范圍: 由優化問題決定,每一維可是設定不同的范圍
- Vmax: 最大速度,決定粒子在一個循環中最大的移動距離,通常設定為粒子的范圍寬度,例如上面的例子里,粒子 (x1, x2, x3) x1 屬於 [-10, 10], 那么 Vmax 的大小就是 20
- 學習因子: c1 和 c2 通常等於 2. 不過在文獻中也有其他的取值. 但是一般 c1 等於 c2 並且范圍在0和4之間
- 中止條件: 最大循環數以及最小錯誤要求. 例如, 在上面的神經網絡訓練例子中, 最小錯誤可以設定為1個錯誤分類, 最大循環設定為2000, 這個中止條件由具體的問題確定.
- 全局PSO和局部PSO: 我們介紹了兩種版本的粒子群優化算法: 全局版和局部版. 前者速度快不過有時會陷入局部最優. 后者收斂速度慢一點不過很難陷入局部最優. 在實際應用中, 可以先用全局PSO找到大致的結果,再用局部PSO進行搜索.
- 另外的一個參數是慣性權重, 由Shi 和Eberhart提出, 有興趣的可以參考他們1998年的論文(題目: A modified particle swarm optimizer)。
編碼實現
為了簡便,這里直接使用scikit-opt庫中的PSO算法。
def demo_func(x): x1, x2, x3 = x return x1 ** 2 + (x2 - 0.05) ** 2 + x3 ** 2 # %% Do PSO from sko.PSO import PSO pso = PSO(func=demo_func, dim=3, pop=40, max_iter=150, lb=[0, -1, 0.5], ub=[1, 1, 1], w=0.8, c1=0.5, c2=0.5) pso.run() print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y) # %% Plot the result import matplotlib.pyplot as plt plt.plot(pso.gbest_y_hist) plt.show()
在演示一個更直觀的例子:
# Plot particle history as animation import numpy as np from sko.PSO import PSO def demo_func(x): x1, x2 = x return x1 ** 2 + (x2 - 0.5) ** 2 pso = PSO(func=demo_func, dim=2, pop=20, max_iter=40, lb=[-1, -1], ub=[1, 1]) pso.record_mode = True pso.run() print('best_x is ', pso.gbest_x, 'best_y is', pso.gbest_y) # %% Now Plot the animation import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation record_value = pso.record_value X_list, V_list = record_value['X'], record_value['V'] fig, ax = plt.subplots(1, 1) ax.set_title('title', loc='center') line = ax.plot([], [], 'b.') X_grid, Y_grid = np.meshgrid(np.linspace(-1.0, 1.0, 40), np.linspace(-1.0, 1.0, 40)) Z_grid = demo_func((X_grid, Y_grid)) ax.contour(X_grid, Y_grid, Z_grid, 20) ax.set_xlim(-1, 1) ax.set_ylim(-1, 1) plt.ion() p = plt.show() def update_scatter(frame): i, j = frame // 10, frame % 10 ax.set_title('iter = ' + str(i)) X_tmp = X_list[i] + V_list[i] * j / 10.0 plt.setp(line, 'xdata', X_tmp[:, 0], 'ydata', X_tmp[:, 1]) return line ani = FuncAnimation(fig, update_scatter, blit=True, interval=25, frames=300) plt.show() ani.save('pso.gif', writer='pillow')
可見,粒子最后聚集在(0.00,0.50)。
參考鏈接:
1. 百度百科-粒子群優化算法