粒子群算法(PSO)简介及Python实现
一、概述
粒子群算法,也称粒子群优化算法或鸟群觅食算法(Particle Swarm Optimization) ,缩写为PSO.粒子群优化算法是一种进化计算技术(evolutionary computation),1995年由Eberhart博士和kennedy 博士提出,源于对鸟群捕食的行为研究。
该算法最初是受到飞鸟集群活动的规律性启发,进而利用群体智能建立的一个简化模型。粒子群算法在对动物集群活动行为观察基础上,利用群体中的个体对信息的共享使整个群体的运动在问题求解空间中产生从无序到有序的演化过程,从而获得最优解。
如果我们把一个优化问题看作是在空中觅食的鸟群,那么粒子群中每个优化问题的潜在解都是搜索空间的一只鸟,称之为“粒子”(Particle),“食物”就是优化问题的最优解。每个粒子都有一个由优化问题决定的适应度用来评价粒子的“好坏”程度,每个粒子还有一个速度决定它们飞翔的方向和距离,它根据自己的飞行经验和同伴的飞行经验来调整自己的飞行。粒子群初始化为一群随机粒子(随机解),然后通过迭代的方式寻找最优解,在每一次的迭代中,粒子通过跟踪两个“极值”来更新自己,第一个是粒子本身所经历过的最好位置,称为个体极值即pbest;另一个是整个群体经历过的最好位置称为全局极值gbest。每个粒子通过上述的两个极值不断更新自己,从而产生新一代的群体。
二、粒子群算法
假设搜索空间是D维空间,并且群体中有N个粒子。那么群体中的第i个粒子可以表示为一个D维的向量,粒子i位置:Xi=(xi1,xi2,…,xiD),i=1,2,⋯,N。它所经历的“最好”位置记作pbesti=(pi1,pi2,…piD) ,i=1,2,⋯,N。粒子的每个位置代表要求的一个潜在解,把它代入目标函数就可以得到它的适应度值,用来评判粒子的“好坏”程度。整个群体迄今为止搜索到的最优位置记作gbest=(g1,g2,…gD)。通常,在第d(1≤d≤D)维的位置变化范围限定在[Xmin,d,Xmax,d] 内,速度变化范围限定在[-Vmax,d,Vmax,d]内(即在迭代中Vid、Xid若超出了边界值,则该维的速度或位置被限制为该维最大速度或边界位置)
粒子i的第d维速度更新公式:
粒子i的第d维位置更新公式:
c1:个体学习因子,也称为个体加速因子。这个因子越大粒子越倾向于往它自己曾去的最好的地方
c2:社会学系因子,也成为社会加速因子。这个因子越大粒子越倾向于种群中最好的的地方
r1,r2:[0,1]上的随机数。随机代表着粒子比较佛系,他也不知道飞哪里
惯性权重,也叫惯性系数,这个数越大,代表着它不容易更改之前的运动路线,更倾向于探索未知领域。
参数的选择:
粒子数目一般取30~50,参数c1 , c2 一般取2。适应度函数、粒子的维数和取值范围要视具体问题而定。问题解的编码方式通常可以采用实数编码。更新速度后,先进行速度边界检测,一般采用v(v > Vmax)= Vmax,位置同理。常见终止条件为设定迭代进化次数、适应度n代不再变化等。
算法的主要流程:
第一步:对粒子群的随机位置和速度进行初始设定,同时设定迭代次数。
第二步:计算每个粒子的适应度值。
第三步:对每个粒子,将其适应度值与所经历的最好位置pbest i的适应度值进行比较,若较好,则将其作为当前的个体最优位置。
第四步:对每个粒子,将其适应度值与全局所经历的最好位置gbestg的适应度值进行比较,若较好,则将其作为当前的全局最优位置。
第五步:根据速度、位置公式对粒子的速度和位置进行优化,从而更新粒子位置。
第六步:如未达到结束条件(通常为最大循环数或最小误差要求),则返回第二步
三、算法优缺点
优点:
- PSO算法没有交叉和变异运算,依靠粒子速度完成搜索,并且在迭代进化中只有最优的粒子把信息传递给其它粒子,搜索速度快。
- PSO算法具有记忆性,粒子群体的历史最好位置可以记忆并传递给其它粒子。
- 需调整的参数较少,结构简单,易于工程实现。
- 采用实数编码,直接由问题的解决定,问题解的变量数直接作为粒子的维数。
缺点:
- 缺乏速度的动态调节,容易陷入局部最优,导致收敛精度低和不易收敛。
- 不能有效解决离散及组合优化问题。
- 参数控制,对于不同的问题,如何选择合适的参数来达到最优效果。
- 不能有效求解一些非直角坐标系描述问题,
粒子群算法的参数是固定的。w描述的是粒子的“惯性”,在进化前期w应该大一些,保证各个粒子独立飞行充分搜索空间,后期应该小一点,多向其他粒子学习。c1,c2分别向个体极值和全局极值最大飞行步长。前期c1,应该大一些,后期c2,应该大一些,这样就能平衡粒子的全局搜索能力和局部搜索能力。3个参数共同影响了粒子的飞行方向,导致即使其他粒子找到更好的,但是当前粒子惯性太大,不能很快的飞向更优的位置。
四、简单的实例及Python实现
import numpy as np
import random
class PSO_model:
def __init__(self,w,c1,c2,r1,r2,N,D,M):
self.w = w # 惯性权值
self.c1=c1
self.c2=c2
self.r1=r1
self.r2=r2
self.N=N # 初始化种群数量个数
self.D=D # 搜索空间维度
self.M=M # 迭代的最大次数
self.x=np.zeros((self.N,self.D)) #粒子的初始位置
self.v=np.zeros((self.N,self.D)) #粒子的初始速度
self.pbest=np.zeros((self.N,self.D)) #个体最优值初始化
self.gbest=np.zeros((1,self.D)) #种群最优值
self.p_fit=np.zeros(self.N)
self.fit=1e8 #初始化全局最优适应度
# 目标函数,也是适应度函数(求最小化问题)
def function(self,x):
A = 10
x1=x[0]
x2=x[1]
Z = 2 * A + x1 ** 2 - A * np.cos(2 * np.pi * x1) + x2 ** 2 - A * np.cos(2 * np.pi * x2)
return Z
# 初始化种群
def init_pop(self):
for i in range(self.N):
for j in range(self.D):
self.x[i][j] = random.random()
self.v[i][j] = random.random()
self.pbest[i] = self.x[i] # 初始化个体的最优值
aim=self.function(self.x[i]) # 计算个体的适应度值
self.p_fit[i]=aim # 初始化个体的最优位置
if aim < self.fit: # 对个体适应度进行比较,计算出最优的种群适应度
self.fit = aim
self.gbest = self.x[i]
# 更新粒子的位置与速度
def update(self):
for t in range(self.M): # 在迭代次数M内进行循环
for i in range(self.N): # 对所有种群进行一次循环
aim=self.function(self.x[i]) # 计算一次目标函数的适应度
if aim<self.p_fit[i]: # 比较适应度大小,将小的负值给个体最优
self.p_fit[i]=aim
self.pbest[i]=self.x[i]
if self.p_fit[i]<self.fit: # 如果是个体最优再将和全体最优进行对比
self.gbest=self.x[i]
self.fit = self.p_fit[i]
for i in range(self.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]
print("最优值:",self.fit,"位置为:",self.gbest)
if __name__ == '__main__':
# w,c1,c2,r1,r2,N,D,M参数初始化
w=random.random()
c1=c2=2#一般设置为2
r1=0.7
r2=0.5
N=30
D=2
M=200
pso_object=PSO_model(w,c1,c2,r1,r2,N,D,M)#设置初始权值
pso_object.init_pop()
pso_object.update()
来源:brilliantZC