粒子群优化(Particle Swarm Optimization, PSO)算法是通过模拟鸟群觅食过程中的迁徙和群聚行为而提出的一种基于群体智能的全局随机搜索算法。
PSO初始化为一群随机粒子(随机解)。然后通过迭代找到最优解在每一次迭代中,粒子通过跟踪两个"极值"来更新自己。第一个就是粒子本身所找到的最优解,这个解叫做个体极值。另一个极值是整个种群目前找到的最优解,这个极值是全局极值。
迭代公式:
v i d = w ∗ v i d + c 1 r 1 ( p i d − x i d ) + c 2 r 2 ( p g d − x i d ) {v_{id}} = w*{v_{id}} + {c_1}{r_1}({p_{id}} - {x_{id}}) + {c_2}{r_2}({p_{gd}} - {x_{id}}) vid=w∗vid+c1r1(pid−xid)+c2r2(pgd−xid)
x i d = x i d + v i d {x_{id}} = {x_{id}} + {v_{id}} xid=xid+vid
一式中右边由三部分组成
第一部分代表了粒子保持先前速度的趋势,相当于惯性
第二部分代表了粒子对自己发现的局部最优解的倾向
第三部分代表了粒子对全局最优解的倾向
w惯性权重,反映粒子自身惯性的影响程度
c1,c2学习因子
r2,r2 [0,1]的随机数,与c1,c2共同作用,反映粒子对局部最优解和全局最优解的一个倾向
这些参数都是作为超参数自行设置
Pid,个体极值,是单个粒子截止现在时刻搜索到的最优位置
Pgd ,全局极值,是整个粒子群截止现在时刻搜索到的最优位置
1.初始化变量
def __init__(self, pN, dim, max_iter):
#定义所需变量
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)) # 个体经历的最佳位置和全局最佳位置矩阵
self.gbest = np.zeros((1, self.dim))
self.p_fit = np.zeros(self.pN) # 每个个体的历史最佳适应值
self.fit = 1e10 # 全局最佳适应值
许多参数都为超参数,需要自行设置
2.初始化粒子群
def init_Population(self):
for i in range(self.pN):
for j in range(self.dim):
self.X[i][j] = random.uniform(0, 1)
self.V[i][j] = random.uniform(0, 1)
self.pbest[i] = self.X[i]
tmp = self.function(self.X[i])
self.p_fit[i] = tmp
if (tmp < self.fit):
self.fit = tmp
self.gbest = self.X[i]
以标准正态分布随机设置粒子位置,计算目标函数值,令目标函数最小化为目标
3.目标函数
#目标函数,根据使用场景进行设置
def function(self, x):
sum = 0
length = len(x)
for i in range(length):
sum += (4*x[i]**3-5*x[i]**2+x[i]+6)**2
return sum
目标函数是根据自己所需求解的数学模型建立
4.优化函数
def iterator(self):
fitness = []
for t in range(self.max_iter):
for i in range(self.pN): # 更新gbest\pbest
temp = self.function(self.X[i])
if (temp < self.p_fit[i]): # 更新个体最优
self.p_fit[i] = temp
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.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)
print(self.fit) # 输出最优值
print(self.gbest)
return fitness
粒子群算法的主体,用以实现最优解
5.完整代码
import numpy as np
import random
import matplotlib.pyplot as plt
import math
class PSO():
def __init__(self, pN, dim, max_iter):
#定义所需变量
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)) # 个体经历的最佳位置和全局最佳位置矩阵
self.gbest = np.zeros((1, self.dim))
self.p_fit = np.zeros(self.pN) # 每个个体的历史最佳适应值
self.fit = 1e10 # 全局最佳适应值
self.init_Population()
#目标函数,根据使用场景进行设置
def function(self, x):
sum = 0
length = len(x)
for i in range(length):
sum += (4*x[i]**3-5*x[i]**2+x[i]+6)**2
return sum
#初始化粒子群
def init_Population(self):
for i in range(self.pN):
for j in range(self.dim):
self.X[i][j] = random.uniform(0, 1)
self.V[i][j] = random.uniform(0, 1)
self.pbest[i] = self.X[i]
tmp = self.function(self.X[i])
self.p_fit[i] = tmp
if (tmp < self.fit):
self.fit = tmp
self.gbest = self.X[i]
def iterator(self):
fitness = []
for t in range(self.max_iter):
for i in range(self.pN): # 更新gbest\pbest
temp = self.function(self.X[i])
if (temp < self.p_fit[i]): # 更新个体最优
self.p_fit[i] = temp
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.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)
print(self.fit) # 输出最优值
print(self.gbest)
return fitness
if __name__ == '__main__':
my_pso = PSO(pN=30, dim=5, max_iter=100)
fitness = my_pso.iterator()
plt.figure(1)
plt.title("Figure1")
plt.xlabel("iterators", size=14)
plt.ylabel("fitness", size=14)
t = np.array([t for t in range(0, 100)])
fitness = np.array(fitness)
plt.plot(t, fitness, color='b', linewidth=3)
plt.show()