粒子群算法
一、介绍
- 粒子群算法(Particle Swarm Optimization, PSO)属于进化算法的一种,粒子群算法从随机解出发,通过不断的迭代更新,寻找最优解,通过适应度来评价解的品质。
- PSO可以用于解决最优化问题,在PSO中,每个优化问题的潜在解都是搜索空间中的一个粒子,每个粒子都由一个被优化的函数决定适值,每个粒子还有一个速度决定他们的“飞行”的方向和距离。然后粒子们就会追随当前的最有粒子在解空间中搜索,粒子的更新方式如图所示:
其中,x 表示粒子的起始位置,v表示粒子的“飞行速度”,p表示搜索到的粒子的最优位置。
PSO初始化为一群随机粒子(可理解为随机解),然后通过不断的迭代更新寻找最优解,在每一次迭代中,粒子通过跟踪两个极值来对自我完成更新:一个是粒子本身找到的最优解,称为个体极值;一个是整个种群找到的最优解,称为全局极值。
二、算法思路
假设在一个D维的目标搜索空间中,有N个粒子组成一个群落
其中,第i个粒子表示一个D维的向量:
第i个粒子的“飞行”速度也是一个D维向量
第i个粒子搜索到的个体极值
整个粒子种群搜索到的最优位置的全局极值
找到两个最优值时,其进行更新自己的位置和速度:
其中,C1,C2为学习因子,也称为加速常数,r1,r2为[0,1]之间的均匀随机小数。
由于粒子群算法具有高效的搜索能力,有利于得到多目标意义下的最优解,通过迭代整个解集种群,按并行的方式同时搜索多个优解。同时粒子群算法通用性较好,适合处理多种类型的目标函数和约束,并且容易与传统的优化方法相结合,改善自身的局限性,更高效的解决问题,适用于多目标优化问题。
三、例题
求解目标函数的最小值:
代码 Python版
import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
def fitness(x):
F = 0
for i in range(x.shape[0]):
F = F + x[i]**2 + x[i] - 6
return F
def PSO(N,c1,c2,w,M,D):
"""
初始化条件
Parameters
----------
fitness : TYPE
目标函数
N : TYPE
初始化群体个体数目
c1 : TYPE
学习因子1
c2 : TYPE
学习因子2
w : TYPE
惯性权重
M : TYPE
最大迭代次数
D : TYPE
搜索空间的维度
Returns
-------
xm 为目标函数取最小值时的自变量
fv 是目标函数的最小值
"""
img = np.zeros((600,600,3))
x = np.zeros((N,D))
y = np.zeros((N,D))
v = np.zeros((N,D))
p = {}
p_best = {}
for i in range(N):
for j in range(D):
x[i,j] = np.random.randn(1)[0] #初始化位置
v[i,j] = np.random.randn(1)[0] #初始化速度
# 计算粒子的适应度 初始化pi 和 pg
for i in range(N):
p[i] = fitness(x[i,:])
y[i,:] = x[i,:]
pg = x[N-1,:]
fv_lidt = []
for i in range(N-1):
if fitness(x[i,:]) < fitness(pg):
pg = x[i, :]
for t in range(M):
for i in range(N):
v[i,:] = w*v[i,:] + c1*np.random.rand(1)[0]*(y[i,:] - x[i,:])+c2*np.random.rand(1)*(pg-x[i,:])
x[i,:] = x[i,:] + v[i,:]
fv_lidt.append(fitness(x[i,:]))
# print("fitness(pg)1: ", fitness(x[i,:]))
# print("y[i,:]: ", y[i,:])
if fitness(x[i,:]) < p[i]:
p[i] = fitness(x[i,:])
y[i, :] = x[i, :]
if p[i] < fitness(pg):
pg = y[i,:]
# fv_lidt.append(fitness(pg))
p_best[t]=fitness(pg)
# print("p_best: ", p_best[0])
xm = pg
fv = fitness(pg)
print("xm: ", pg)
print("fv: ", fitness(pg))
return xm, fv_lidt
if __name__ == "__main__":
N = 50
c1 = 1.5
c2 = 2.5
w = 0.5
M = 10
D = 30
x1 = np.zeros((1,30))
xm1,fv2 = PSO(N, c1, c2, w, M, D)
plt.plot(xm1, lw=3, label='xm1')
plt.legend()
plt.show()
plt.plot(fv2, lw=3, label='fv2')
plt.legend()
plt.show()
运行结果