什么是粒子群算法

  粒子群算法,也稱粒子群優(yōu)化算法或鳥(niǎo)群覓食算法(Particle Swarm Optimization,PSO)。由J. Kennedy和R. C. Eberhart等人于1995年提出。其屬于進(jìn)化算法的一種,也是從隨機(jī)解出發(fā),通過(guò)迭代尋找最優(yōu)解,其通過(guò)適應(yīng)度來(lái)評(píng)價(jià)解的品質(zhì)。

  這種算法以其實(shí)現(xiàn)容易、精度高、收斂快等優(yōu)點(diǎn)引起了學(xué)術(shù)界的重視,并且在解決實(shí)際問(wèn)題中展示了其優(yōu)越性。

  求解過(guò)程

  PSO通過(guò)模擬鳥(niǎo)群的捕食行為完成最優(yōu)解的求取。

  假設(shè)一群鳥(niǎo)在一個(gè)空間捕捉食物。在這個(gè)區(qū)域里只有一塊食物(對(duì)應(yīng)著最優(yōu)解)。所有的鳥(niǎo)都不知道食物在那里。但是它們可以判斷自身與食物的大致距離(通過(guò)fit值判斷與最優(yōu)解的距離)。最簡(jiǎn)單有效的方法就是搜尋目前離食物最近的鳥(niǎo)的周圍區(qū)域。

  PSO中,問(wèn)題的每個(gè)解都是搜索空間中的一只“鳥(niǎo)”。我們稱之為“粒子”。所有的粒子都有一個(gè)由被優(yōu)化的函數(shù)決定的適應(yīng)值(fitness value),可以通過(guò)種群中適應(yīng)度最高的粒子的位置和自身與自身最優(yōu)情況的判斷完成位置的更新。

  即,PSO 會(huì)初始化一群隨機(jī)粒子。利用迭代尋找最優(yōu)解。在每一次迭代中,粒子通過(guò)跟蹤兩個(gè)"極值"來(lái)實(shí)現(xiàn)位置的更新。

  1、粒子本身所找到的最優(yōu)解,個(gè)體極值pbest。

  2、整個(gè)種群目前找到的最優(yōu)解,全局極值gBest。

  每個(gè)粒子有一個(gè)重要的屬性,名為速度,該屬性同樣決定了它們更新的方向和更新的距離。

  粒子們會(huì)追隨當(dāng)前的最優(yōu)粒子在解空間中搜索。

  粒子群算法的求解偽代碼如下:

  初始化粒子群

  while 未達(dá)到最大迭代次數(shù)或最小loss:

  for each_p in 粒子群:

  計(jì)算適應(yīng)度

  如果某個(gè)粒子適應(yīng)度高于歷史上的最佳適應(yīng)度(pbest)

  將該值設(shè)置為新的pbest

  選擇所有粒子的最佳適配值的粒子作為gbest

  for each_p in 粒子群:

  根據(jù)方程(a)計(jì)算粒子速度

  根據(jù)方程式(b)更新粒子位置

  其中方程(a)為:

在這里插入圖片描述


  方程(b)為:

在這里插入圖片描述


  在方程中,v[i] 是第i個(gè)粒子的速度,w是慣性權(quán)重(有助于跳出局部最優(yōu)解),present[i] 是第i個(gè)粒子的當(dāng)前位置,pbest[i]是第i個(gè)粒子的歷史最佳,gbest是全局最佳,rand () 是介于(0, 1)之間的隨機(jī)數(shù)。c1、c2 是學(xué)習(xí)因子,通常情況下,c1 = c2 = 2。

  對(duì)于方程(a)而言:

在這里插入圖片描述


  代表利用粒子本身所找到的最優(yōu)解更新自己的速度。

在這里插入圖片描述


  代表利用整個(gè)種群目前找到的最優(yōu)解更新自己的速度。

  實(shí)現(xiàn)代碼 無(wú)錫看婦科的醫(yī)院 http://www.ytsgfk120.com/

  這是一個(gè)求取二元一次方程y = -x^2 + 20*x + 10的最大值的例子。

  import numpy as np

  class PSO():

  def __init__(self,pN,dim,max_iter,func):

  self.w = 0.8 #慣性因子

  self.c1 = 2 #自身認(rèn)知因子

  self.c2 = 2 #社會(huì)認(rèn)知因子

  self.r1 = 0.6 #自身認(rèn)知學(xué)習(xí)率

  self.r2 = 0.3 #社會(huì)認(rèn)知學(xué)習(xí)率

  self.pN = pN #粒子數(shù)量

  self.dim = dim #搜索維度

  self.max_iter = max_iter #最大迭代次數(shù)

  self.X = np.zeros((self.pN,self.dim)) #初始粒子的位置和速度

  self.V = np.zeros((self.pN,self.dim))

  self.pbest = np.zeros((self.pN,self.dim),dtype = float) #粒子歷史最佳位置

  self.gbest = np.zeros((1,self.dim),dtype = float) #全局最佳位置

  self.p_bestfit = np.zeros(self.pN) #每個(gè)個(gè)體的歷史最佳適應(yīng)值

  self.fit = -1e15 #全局最佳適應(yīng)值

  self.func = func

  def function(self,x):

  return self.func(x)

  def init_pop(self,): #初始化種群

  for i in range(self.pN):

  #初始化每一個(gè)粒子的位置和速度

  self.X[i] = np.random.uniform(0,5,[1,self.dim])

  self.V[i] = np.random.uniform(0,5,[1,self.dim])

  self.pbest[i] = self.X[i] #初始化歷史最佳位置

  self.p_bestfit[i] = self.function(self.X[i]) #得到對(duì)應(yīng)的fit值

  if(self.p_bestfit[i] > self.fit):

  self.fit = self.p_bestfit[i]

  self.gbest = self.X[i] #得到全局最佳

  def update(self):

  fitness = []

  for _ in range(self.max_iter):

  for i in range(self.pN): #更新gbest\pbest

  temp = self.function(self.X[i]) #獲得當(dāng)前位置的適應(yīng)值

  if( temp > self.p_bestfit[i] ): #更新個(gè)體最優(yōu)

  self.p_bestfit[i] = temp

  self.pbest[i] = self.X[i]

  if(self.p_bestfit[i] > self.fit): #更新全局最優(yōu)

  self.gbest = self.X[i]

  self.fit = self.p_bestfit[i]

  for i in range(self.pN): #更新權(quán)重

  self.V[i] = self.w*self.V[i] + self.c1*self.r1*(self.pbest[i] - self.X[i]) + \

  self.c2*self.r2*(self.gbest - self.X[i])

  self.X[i] = self.X[i] + self.V[i]

  fitness.append(self.fit)

  return self.gbest,self.fit

  def count_func(x):

  y = -x**2 + 20*x + 10

  return y

  pso_example = PSO(pN = 50,dim = 1,max_iter = 300, func = count_func)

  pso_example.init_pop()

  x_best,fit_best= pso_example.update()

  print(x_best,fit_best)