受到生物学家Frank Heppner建立的鸟群运动模型影响,James Kennedy和Russell Eberhart于1995年提出了粒子群优化算法(Particle Swarm Optimization, PSO),PSO算法的基本行为规则是:
1) 向背离最近的同伴的方向运动
2) 像目的地运动
3) 向群的中心运动
Kennedy和Eberhart受到这个模型的启发,将这个模型中的栖息地类比与所求解空间中的可能解的位置,通过个体间信息的传递,引导整个群体向可能解的方向移动,增加发现较好解的可能性。群体中的鸟被抽象为一个个没有质量没有形状的“粒子”,通过这些“粒子”的相互协作和信息共享,在复杂解空间寻找最好解。
混合PSO算法基于当前位置的适应值计算每个个体,并将这些适应值进行排序,然后将群体中一半适应值差的个体的当前位置和速度替换为另一半好的个体的当前位置和速度,并保留每个个体的最后位置pbest。因此,群体搜索集中到相对较优的空间,但还受到个体自身以前最好位置的影响。
混合PSO算法的流程如下:
1) 初始化所有粒子;
2) 评价每个粒子的适应值;
3) 使用适应值对粒子进行选择;
4) 调整粒子的搜索位置,粒子从新的位置开始搜索;
5) 检查终止条件。如果达到最大迭代次数或者最好解停滞不再变化,就终止迭代;否则回到步骤2)。
PSO算法主要包括以下几个要点:
(l)粒子以随机的方式在整个问题空间中流动并且可以对自己所处的环境
进行评价(计算适应度);
(2)每个粒子均可以记忆自己到过的最好位置;
(3)每个粒子可以感知邻近粒子己达到的最好位置;
(4)在改变速度的时候同时考虑自己到过的最好位置和邻近粒子已达到最
好位置"
PSO算法的实现步骤为:
(l)初始化粒子群。设群体规模为m,在允许的范围内随机设置粒子的初始位置和速度;
(2)评价每个粒子的适应值,即计算每个粒子的目标函数fitness,;
(3)对所有的i《{l,2,,,m},比较fitness和pbest。如果fitness优于pbest,则令pbest=fitness,, ;
(4)对所有的i《{l,2,,,m},比较声fitness和gbest,如果fitness优于gbest,则重新设置gbest的索引号g;
(5)根据(3-4),(3-5)式调整每一个粒子的位置和速度;
(6)检查终止条件"如果达到最大迭代次数 或者最好解停滞不再变化,就终止迭代;否则返回(2)。
python代码
import numpy as np
import matplotlib.pyplot as plt
class PSO(object):
def __init__(self, population_size, max_steps):
self.w = 0.6 # 惯性权重
self.c1 = self.c2 = 2
self.population_size = population_size # 粒子群数量
self.dim = 2 # 搜索空间的维度
self.max_steps = max_steps # 迭代次数
self.x_bound = [-10, 10] # 解空间范围
self.x = np.random.uniform(self.x_bound[0], self.x_bound[1],
(self.population_size, self.dim)) # 初始化粒子群位置
self.v = np.random.rand(self.population_size, self.dim) # 初始化粒子群速度
fitness = self.calculate_fitness(self.x)
self.p = self.x # 个体的最佳位置
self.pg = self.x[np.argmin(fitness)] # 全局最佳位置
self.individual_best_fitness = fitness # 个体的最优适应度
self.global_best_fitness = np.max(fitness) # 全局最佳适应度
def calculate_fitness(self, x):
return np.sum(np.square(x), axis=1)
def evolve(self):
fig = plt.figure()
for step in range(self.max_steps):
r1 = np.random.rand(self.population_size, self.dim)
r2 = np.random.rand(self.population_size, self.dim)
# 更新速度和权重
self.v = self.w * self.v + self.c1 * r1 * (self.p - self.x) + self.c2 * r2 * (self.pg - self.x)
self.x = self.v + self.x
plt.clf()
plt.scatter(self.x[:, 0], self.x[:, 1], s=30, color='k')
plt.xlim(self.x_bound[0], self.x_bound[1])
plt.ylim(self.x_bound[0], self.x_bound[1])
plt.pause(0.01)
fitness = self.calculate_fitness(self.x)
# 需要更新的个体
update_id = np.greater(self.individual_best_fitness, fitness)
self.p[update_id] = self.x[update_id]
self.individual_best_fitness[update_id] = fitness[update_id]
# 新一代出现了更小的fitness,所以更新全局最优fitness和位置
if np.min(fitness) < self.global_best_fitness:
self.pg = self.x[np.argmin(fitness)]
self.global_best_fitness = np.min(fitness)
print('best fitness: %.5f, mean fitness: %.5f' % (self.global_best_fitness, np.mean(fitness)))
pso = PSO(100, 100)
pso.evolve()
plt.show()