日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

粒子群优化算法(PSO)python实践

發(fā)布時(shí)間:2023/12/10 python 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 粒子群优化算法(PSO)python实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1 算法介紹和原理

1.1 算法原理

強(qiáng)烈推薦知乎大佬的這篇文章:粒子群優(yōu)化算法(Particle Swarm Optimization, PSO)的詳細(xì)解讀 - 知乎 (zhihu.com)。該文章詳細(xì)介紹了算法的原理、算法流程、參數(shù)解釋和一些Tips,這里就不過(guò)多贅述了。

粒子群優(yōu)化算法(PSO, Particle Swarm Optimization),屬于啟發(fā)式算法中的一種,常用于多目標(biāo)優(yōu)化,尋找全局最優(yōu)解,具有收斂速度快、參數(shù)少、算法簡(jiǎn)單的優(yōu)點(diǎn)。

算法流程圖如下(圖片來(lái)自這篇文章):

1.2 更新公式

1.2.1 速度更新公式

vidk+1=ωvidk+c1r1(pid,pbest?k?xidk)+c2r2(pd,gbest?k?xidk)v_{i d}^{k+1}=\omega v_{i d}^k+c_1 r_1\left(p_{i d, \text { pbest }}^k-x_{i d}^k\right)+c_2 r_2\left(p_{d, \text { gbest }}^k-x_{i d}^k\right) vidk+1?=ωvidk?+c1?r1?(pid,?pbest?k??xidk?)+c2?r2?(pd,?gbest?k??xidk?)

vidk+1v_{i d}^{k+1}vidk+1? —— 粒子 iii 在第 kkk 次迭代中第 ddd 維的速度向量。

pid,pbest?kp_{i d, \text { pbest }}^kpid,?pbest?k? —— 粒子 iii 在第 kkk 次迭代中第 ddd 維的歷史最優(yōu)位置。

速度可以看作一個(gè)向量,具有大小和方向。即是粒子下一輪迭代移動(dòng)的距離和方向。公式分為三部分,第一部分為慣性項(xiàng),由該粒子的當(dāng)前速度和慣性權(quán)重 ω\omegaω 組成。第二部分為認(rèn)知項(xiàng),即是粒子當(dāng)前位置和自身歷史最優(yōu)位置間的距離和方向。 第三部分為社會(huì)項(xiàng),即是粒子當(dāng)前位置和群體歷史最優(yōu)位置間的距離和方向。

對(duì)于更新速度的方向,等于三部分向量和向量的方向。

1.2.2 位置更新公式

xidk+1=xidk+vidk+1x_{i d}^{k+1}=x_{i d}^{k}+v_{i d}^{k+1} xidk+1?=xidk?+vidk+1?

點(diǎn)加向量等于點(diǎn)

大致掌握算法原理后,直接上手代碼。

2 代碼實(shí)現(xiàn)

示例問(wèn)題:

求解如下函數(shù)的極小值
y=x1ex2+x3sinx2+x4x5y=x_1e^{x_2}+x_3sinx_2+x_4x_5 y=x1?ex2?+x3?sinx2?+x4?x5?
每個(gè)變量的取值都在(1,25)。

首先是定義一個(gè)求解類(lèi)及其初始化方法。

class PSO:def __init__(self, D, N, M, p_low, p_up, v_low, v_high, w = 1., c1 = 2., c2 = 2.):self.w = w # 慣性權(quán)值self.c1 = c1 # 個(gè)體學(xué)習(xí)因子self.c2 = c2 # 群體學(xué)習(xí)因子self.D = D # 粒子維度self.N = N # 粒子群規(guī)模,初始化種群個(gè)數(shù)self.M = M # 最大迭代次數(shù)self.p_range = [p_low, p_up] # 粒子位置的約束范圍self.v_range = [v_low, v_high] # 粒子速度的約束范圍self.x = np.zeros((self.N, self.D)) # 所有粒子的位置self.v = np.zeros((self.N, self.D)) # 所有粒子的速度self.p_best = np.zeros((self.N, self.D)) # 每個(gè)粒子的最優(yōu)位置self.g_best = np.zeros((1, self.D))[0] # 種群(全局)的最優(yōu)位置self.p_bestFit = np.zeros(self.N) # 每個(gè)粒子的最優(yōu)適應(yīng)值self.g_bestFit = float('Inf') # float('-Inf'),始化種群(全局)的最優(yōu)適應(yīng)值,由于求極小值,故初始值給大,向下收斂,這里默認(rèn)優(yōu)化問(wèn)題中只有一個(gè)全局最優(yōu)解# 初始化所有個(gè)體和全局信息for i in range(self.N):for j in range(self.D):self.x[i][j] = random.uniform(self.p_range[0][j], self.p_range[1][j])self.v[i][j] = random.uniform(self.v_range[0], self.v_range[1])self.p_best[i] = self.x[i] # 保存?zhèn)€體歷史最優(yōu)位置,初始默認(rèn)第0代為最優(yōu)fit = self.fitness(self.p_best[i])self.p_bestFit[i] = fit # 保存?zhèn)€體歷史最優(yōu)適應(yīng)值if fit < self.g_bestFit: # 尋找并保存全局最優(yōu)位置和適應(yīng)值self.g_best = self.p_best[i]self.g_bestFit = fit

然后定義適應(yīng)度計(jì)算函數(shù),也就是我們要尋優(yōu)的對(duì)象。

def fitness(x):"""根據(jù)粒子位置計(jì)算適應(yīng)值,可根據(jù)問(wèn)題情況自定義"""return x[0] * np.exp(x[1]) + x[2] * np.sin(x[1]) + x[3] * x[4]

定義每次迭代的更新函數(shù)。

def update(self):for i in range(self.N):# 更新速度(核心公式)self.v[i] = self.w * self.v[i] + self.c1 * random.uniform(0, 1) * (self.p_best[i] - self.x[i]) + self.c2 * random.uniform(0, 1) * (self.g_best - self.x[i])# 速度限制for j in range(self.D):if self.v[i][j] < self.v_range[0]:self.v[i][j] = self.v_range[0]if self.v[i][j] > self.v_range[1]:self.v[i][j] = self.v_range[1]# 更新位置self.x[i] = self.x[i] + self.v[i]# 位置限制for j in range(self.D):if self.x[i][j] < self.p_range[0][j]:self.x[i][j] = self.p_range[0][j]if self.x[i][j] > self.p_range[1][j]:self.x[i][j] = self.p_range[1][j]# 更新個(gè)體和全局歷史最優(yōu)位置及適應(yīng)值_fit = self.fitness(self.x[i])if _fit < self.p_bestFit[i]:self.p_best[i] = self.x[i]self.p_bestFit[i] = _fitif _fit < self.g_bestFit:self.g_best = self.x[i]self.g_bestFit = _fit

其中主要完成每輪迭代中單個(gè)粒子位置和速度,歷史最優(yōu)位置和最優(yōu)適應(yīng)度的更新,以及群體(全局)的最優(yōu)位置和最優(yōu)適應(yīng)度的更新。

最后,便是主要函數(shù)的實(shí)現(xiàn)。

def pso(self, draw = 1):best_fit = [] # 記錄每輪迭代的最佳適應(yīng)度,用于繪圖w_range = Noneif isinstance(self.w, tuple):w_range = self.w[1] - self.w[0]self.w = self.w[1]time_start = time.time() # 記錄迭代尋優(yōu)開(kāi)始時(shí)間for i in range(self.M):self.update() # 更新主要參數(shù)和信息if w_range:self.w -= w_range / self.M # 慣性權(quán)重線性遞減print("\rIter: {:d}/{:d} fitness: {:.4f} ".format(i, self.M, self.g_bestFit, end = '\n'))best_fit.append(self.g_bestFit.copy())time_end = time.time() # 記錄迭代尋優(yōu)結(jié)束時(shí)間print(f'Algorithm takes {time_end - time_start} seconds') # 打印算法總運(yùn)行時(shí)間,單位為秒/sif draw:plt.figure()plt.plot([i for i in range(self.M)], best_fit)plt.xlabel("iter")plt.ylabel("fitness")plt.title("Iter process")plt.show()

測(cè)試代碼如下。

if __name__ == '__main__':low = [1, 1, 1, 1, 1]up = [25, 25, 25, 25, 25]pso = PSO(5, 100, 50, low, up, -1, 1, w = 0.9)pso.pso()

測(cè)試結(jié)果如下圖所示。

... Iter: 47/50 fitness: 4.5598 Iter: 48/50 fitness: 4.5598 Iter: 49/50 fitness: 4.5598 Algorithm takes 0.1444549560546875 seconds

可以看到在第30輪就已經(jīng)完全收斂了,且函數(shù)在求解空間中的極小值為4.5598。

3 總結(jié)

  • 動(dòng)態(tài)的慣性權(quán)重[1]^{[1]}[1]

    w_range = self.w[1] - self.w[0] self.w = self.w[1] self.w -= w_range / self.M # 慣性權(quán)重線性遞減
  • fitness變化邏輯

    fitness是適應(yīng)度函數(shù)值,通常問(wèn)題是尋找解空間內(nèi)的粒子,使得該粒子所代表的解的fitness向下或向上收斂于某一定值。對(duì)于不同收斂方向,個(gè)體和全局最優(yōu)fitness一般初始化賦值無(wú)窮大或者無(wú)窮小float('Inf')/float('-Inf')。并且在判斷更新最優(yōu)適應(yīng)值時(shí)也應(yīng)當(dāng)注意大小于符號(hào)。

  • 程序復(fù)用

    對(duì)于上面的PSO類(lèi)代碼,不同多元尋優(yōu)問(wèn)題均可通過(guò)重寫(xiě)類(lèi)中的fitness函數(shù)實(shí)現(xiàn)。或者定義self.fitness_function屬性進(jìn)行外部函數(shù)名傳參賦值。

參考

[1] 粒子群優(yōu)化算法(Particle Swarm Optimization, PSO)的詳細(xì)解讀 - 知乎 (zhihu.com)

[2] 粒子群算法(PSO)的Python實(shí)現(xiàn)(求解多元函數(shù)的極值)_Cyril_KI的博客-CSDN博客_pso算法python

總結(jié)

以上是生活随笔為你收集整理的粒子群优化算法(PSO)python实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。