粒子羣(PSO)算法的實現

粒子羣算法還是很有意思的

描述

粒子羣優化算法(PSO) 是由James Kennedy (肯尼迪)博士和R.C. Eberhart 博士於1995 年提出的。該算法源於對鳥羣、魚羣覓食行爲的模擬。
在PSO 中,首先初始化一羣隨機粒子(隨機解),然後通過迭代尋找最優解。
在每一次迭代中,粒子通過跟蹤兩個極值來更新自己的速度和位置

粒子跟蹤的兩個極值

第一個就是粒子本身所找到的最優解,這個解叫做個體極值;
另一個極值是整個種羣目前找到的最優解,這個極值是全局極值;
另外也可以不用整個種羣而只是用其中一部分作爲粒子的鄰居,那麼在該鄰居中的極值就是局部極值。
PSO 算法簡單易實現,不需要調整很多參數,主要應用有神經網絡的訓練、函數的優化等。

粒子羣優化算法是基於羣體的演化算法, 其思想來源於人工生命和演化計算理論。Reynolds 對鳥羣飛行的研究發現, 鳥僅僅是追蹤它有限數量的鄰居, 但最終的整體結果是整個鳥羣好像在一箇中心的控制之下, 即複雜的全局行爲是由簡單規則的相互作用引起的。
PSO 即源於對鳥羣捕食行爲的研究, 一羣鳥在隨機搜尋食物時, 如果這個區域裏只有一塊食物, 那麼找到食物的最簡單有效的策略就是搜尋目前離食物最近的鳥的周圍區域。

部分代碼

這裏使用一個類來描述粒子羣,每個粒子個體我們看作是這個類的一個實例,
並且通過把位置信息當作一個list,速度也當作一個list,算法本身即可支持任意維度的計算。從1-max,收斂效果也還不錯,其中使用了7個多目標測試函數。
後續將繼續進行PSO算法的改進。

完整代碼見git:sunxueliang96/Machine-learning-stuffs/tree/master/計算智能相關算法
class Swarm:
	def __init__(self):
		self.pos = [] #個體位置
		self.speed = []#個體速度
		self.fitness = 0 #當前適應值
		self.best_fitness = 0 #個體最優值
		self.best_pos = []#個體最優解
		for i in range(m):
			self.pos.append(np.random.uniform(-rang, rang))
		for i in range(m):
			#self.speed.append(np.random.uniform(-1,1)*rang/100)#隨機初始速度
			self.speed.append(0)#初始速度爲0
		self.fitness = cal_fitness(self.pos)
		self.best_fitness = self.fitness
		self.best_pos = list.copy(self.pos)
	def info(self):
		print('pos',self.pos)
		print('speed',self.speed)
		print('fitness',self.fitness)
		print('best_pos',self.best_pos)
	def refresh_memory(self): #每次個體更新適應度及全局最優適應度。
		global swarm_best_fitness,swarm_bset_id,swarm_best_pos 
		self.fitness = cal_fitness(self.pos)
		if(self.fitness<self.best_fitness): #比個體極值好,則更新記憶
			self.best_fitness = self.fitness
			self.best_pos = list.copy(self.pos)
		if(self.fitness<swarm_best_fitness):
			swarm_best_fitness = self.fitness
			swarm_best_pos = list.copy(self.pos)
	def refresh_pos(self):#跟新個體自己的速度和位置
		for i in range(m):
			self.speed[i] = self.speed[i] + c1*np.random.uniform() * (self.best_pos[i]-self.pos[i]) + c2*np.random.uniform()*(swarm_best_pos[i]-self.pos[i])
			next_pos = self.pos[i] + self.speed[i]
			if (-rang<next_pos and next_pos<rang):
				self.pos[i] = next_pos
			else:
				#print('out of range')
				pass

更新位置和速度比較簡單,根據公式即可
在這裏插入圖片描述

def update_swarm_best():#找到全局最好的粒子,更新全局最優解和全局極值,寫成函數方便切換最大最小
	global swarm_best_fitness,swarm_bset_id,swarm_best_pos 
	for i in range(n):
		if(swarm[i].best_fitness<swarm_best_fitness):
			#print('update at ',i,'best_fitness==',swarm_best_fitness)
			swarm_best_fitness = swarm[i].best_fitness
			swarm_best_pos = list.copy(swarm[i].best_pos)
			swarm_bset_id = i

部分截圖

在這裏插入圖片描述

Rosenbrock函數

在這裏插入圖片描述
在這裏插入圖片描述

Griewank函數

在這裏插入圖片描述

Schaffer’s F7

在這裏插入圖片描述
在這裏插入圖片描述

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