什么是粒子群算法
粒子群算法,也称粒子群优化算法或鸟群觅食算法(Particle Swarm Optimization,PSO)。由J. Kennedy和R. C. Eberhart等人于1995年提出。其属于进化算法的一种,也是从随机解出发,通过迭代寻找最优解,其通过适应度来评价解的品质。
这种算法以其实现容易、精度高、收敛快等优点引起了学术界的重视,并且在解决实际问题中展示了其优越性。
求解过程
PSO通过模拟鸟群的捕食行为完成最优解的求取。
假设一群鸟在一个空间捕捉食物。在这个区域里只有一块食物(对应着最优解)。所有的鸟都不知道食物在那里。但是它们可以判断自身与食物的大致距离(通过fit值判断与最优解的距离)。最简单有效的方法就是搜寻目前离食物最近的鸟的周围区域。
PSO中,问题的每个解都是搜索空间中的一只“鸟”。我们称之为“粒子”。所有的粒子都有一个由被优化的函数决定的适应值(fitness value),可以通过种群中适应度最高的粒子的位置和自身与自身最优情况的判断完成位置的更新。
即,PSO 会初始化一群随机粒子。利用迭代寻找最优解。在每一次迭代中,粒子通过跟踪两个"极值"来实现位置的更新。
1、粒子本身所找到的最优解,个体极值pbest。
2、整个种群目前找到的最优解,全局极值gBest。
每个粒子有一个重要的属性,名为速度,该属性同样决定了它们更新的方向和更新的距离。
粒子们会追随当前的最优粒子在解空间中搜索。
粒子群算法的求解伪代码如下:
初始化粒子群
while 未达到最大迭代次数或最小loss:
for each_p in 粒子群:
计算适应度
如果某个粒子适应度高于历史上的最佳适应度(pbest)
将该值设置为新的pbest
选择所有粒子的最佳适配值的粒子作为gbest
for each_p in 粒子群:
根据方程(a)计算粒子速度
根据方程式(b)更新粒子位置
其中方程(a)为:
方程(b)为:
在方程中,v[i] 是第i个粒子的速度,w是惯性权重(有助于跳出局部最优解),present[i] 是第i个粒子的当前位置,pbest[i]是第i个粒子的历史最佳,gbest是全局最佳,rand () 是介于(0, 1)之间的随机数。c1、c2 是学习因子,通常情况下,c1 = c2 = 2。
对于方程(a)而言:
代表利用粒子本身所找到的最优解更新自己的速度。
代表利用整个种群目前找到的最优解更新自己的速度。
实现代码
无锡看妇科的医院 http://www.ytsgfk120.com/
这是一个求取二元一次方程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 #自身认知因子
self.c2 = 2 #社会认知因子
self.r1 = 0.6 #自身认知学习率
self.r2 = 0.3 #社会认知学习率
self.pN = pN #粒子数量
self.dim = dim #搜索维度
self.max_iter = max_iter #最大迭代次数
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) #每个个体的历史最佳适应值
self.fit = -1e15 #全局最佳适应值
self.func = func
def function(self,x):
return self.func(x)
def init_pop(self,): #初始化种群
for i in range(self.pN):
#初始化每一个粒子的位置和速度
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]) #得到对应的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]) #获得当前位置的适应值
if( temp > self.p_bestfit[i] ): #更新个体最优
self.p_bestfit[i] = temp
self.pbest[i] = self.X[i]
if(self.p_bestfit[i] > self.fit): #更新全局最优
self.gbest = self.X[i]
self.fit = self.p_bestfit[i]
for i in range(self.pN): #更新权重
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)