avant-propos
Après avoir tourné en rond, je voulais faire un test de comparaison avec d'autres algorithmes d'essaim de particules. Il s'est avéré que s'il n'y a pas de code, ce n'est pas grave si python n'en a pas. Matlab ne peut pas le trouver. Si vous le trouvez, vous aura besoin d'argent. Bien qu'il existe des bibliothèques d'algorithmes intelligents en python, elles sont trop intégrées et certaines variantes de PSO ne sont pas spécifiquement intégrées. Bien qu'il existe une bibliothèque dédiée à PSO, cette chose intègre un algorithme et le fichier principal est un PSO.
Donc, puisqu'il n'y en a pas, je vais construire ma propre roue et jeter un coup d'œil d'abord, et je veux vraiment me plaindre, certains articles ne donnent pas le code, même si je ne donne pas les paramètres lors de l'expérience de comparaison , Je suis très confus et je dois le faire moi-même. Ajustez manuellement les paramètres. Et j'ai trouvé une chose très intéressante. Dans l'algorithme proposé par l'auteur de l'article, l'effet expérimental est très bon. Quand d'autres citent et comparent, même le PSO standard ne doit pas être capable de le faire.
Pour l'instant, je vais commencer par la version la plus simple, mais elle n'est intégrée qu'au PSO pour l'instant, et elle s'adresse pour l'instant aux plateformes mono-cibles. Pour les multi-cibles, il y a PlatEMO, donc à la base je n'ai pas besoin de écrivez-en une autre. S'il ne s'agit que d'une seule cible, je n'en ai pas trouvé une appropriée. Les auteurs de ces articles n'ont pas fourni de code et il y avait peu de ressources en ligne. Je ne sais pas si c'est trop simple ou j'ai peur de dévoiler les secrets... Il n'y a pas d'esprit open source.
droits d'auteur
郑重提示:本文版权归本人所有,任何人不得抄袭,搬运,使用需征得本人同意!
2022.7.4
Date : 2022.7.4
algorithme d'ensemble
À l'heure actuelle, cette chose est un algorithme PSO intégré. L'algorithme PSO est divisé en deux catégories, l'une est un algorithme basé sur l'optimisation des paramètres et l'autre est une stratégie multi-essaim. À l'origine, je voulais faire quelques structures de topologie d'optimisation . , mais d'un côté, c'est un problème de mise en œuvre, et de l'autre, le papier n'explique pas que l'anglais (en chinois) prend du temps. Je n'ai pas tellement le temps de faire cette merde, parce que mon l'algorithme n'est pas encore terminé, je veux juste un truc de test de comparaison.
Structuration du projet
Algorithme de base de l'essaim de particules SPSO
Structure de données
Afin d'unifier et de faciliter la gestion par la suite, une classe de données est également spécialement définie.
import random
from ALGSet.Config.PSO.SPSO import *
class SBird(object):
#这个是从1开始的
ID = 1
Y = None
X = None
V = None
PbestY = None
PBestX = None
GBestX = None
GBestY = None
def __init__(self,ID):
self.ID = ID
self.V = [random.random() *(V_max-V_min) + V_min for _ in range(DIM)]
self.X = [random.random() *(X_up-X_down) + X_down for _ in range(DIM)]
def __str__(self):
return "ID:"+str(self.ID)+" -Fintess:%.2e:"%(self.Y)+" -X"+str(self.X)+" -PBestFitness:%.2e"%(self.PbestY)+" -PBestX:"+str(self.PBestX)+\
"\n -GBestFitness:%.2e"%(self.GBestY)+" -GBestX:"+str(self.GBestX)
Paramétrage associé
La configuration correspond également au nom de l'algorithme, qui peut également être vu dans la figure ci-dessus.
#coding=utf-8
# 相关参数的设置通过配置中心完成
import sys
import os
sys.path.append(os.path.abspath(os.path.dirname(os.getcwd())))
C1=1.458
C2=1.458
W = 0.72
m = 3
DIM = 10
PopulationSize=30
#运行1000次(可以理解为训练1次这个粒子群要跑一千次)
IterationsNumber = 3000
X_down = -10.0
X_up = 10
V_min = -5.0
V_max = 5
Wmax = 0.9
Wmin = 0.4
def LinearW(iterate):
#传入迭代次数
w = Wmax-(iterate*((Wmax-Wmin)/IterationsNumber))
return w
def Dw(iterate):
w = Wmax-((iterate**2)*((Wmax-Wmin)/(IterationsNumber**2)))
return w
def Nw(iterate):
w = Wmin+(Wmax-Wmin)*(((IterationsNumber-iterate)**m)/(IterationsNumber**m))
return w
code d'implémentation
#coding=utf-8
#这个是最基础的PSO算法SPSO算法
import sys
import os
from ALGSet.Alg.PSO.Bird.SBird import SBird
sys.path.append(os.path.abspath(os.path.dirname(os.getcwd())))
from ALGSet.Target.Target import Target
from ALGSet.Config.PSO.SPSO import *
import random
import time
class SPso(object):
Population = None
Random = random.random
target = Target()
W = W
def __init__(self):
#为了方便,我们这边直接先从1开始
self.Population = [SBird(ID) for ID in range(1,PopulationSize+1)]
def ComputeV(self,bird):
#这个方法是用来计算速度滴
NewV=[]
for i in range(DIM):
v = bird.V[i]*self.W + C1*self.Random()*(bird.PBestX[i]-bird.X[i])\
+C2*self.Random()*(bird.GBestX[i]-bird.X[i])
#这里注意判断是否超出了范围
if(v>V_max):
v = V_max
elif(v<V_min):
v = V_min
NewV.append(v)
return NewV
def ComputeX(self,bird:SBird):
NewX = []
NewV = self.ComputeV(bird)
bird.V = NewV
for i in range(DIM):
x = bird.X[i]+NewV[i]
if(x>X_up):
x = X_up
elif(x<X_down):
x = X_down
NewX.append(x)
return NewX
def InitPopulation(self):
#初始化种群
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
for bird in self.Population:
bird.PBestX = bird.X
bird.Y = self.target.SquareSum(bird.X)
bird.PbestY = bird.Y
if(bird.Y<=Flag):
GBestX = bird.X
Flag = bird.Y
#便利了一遍我们得到了全局最优的种群
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
def Running(self):
#这里开始进入迭代运算
for iterate in range(1,IterationsNumber+1):
#这个算的GBestX其实始终是在算下一轮的最好的玩意
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
for bird in self.Population:
x = self.ComputeX(bird)
y = self.target.SquareSum(x)
bird.X = x
bird.Y = y
if(bird.Y<=bird.PbestY):
bird.PBestX=bird.X
bird.PbestY = bird.Y
#个体中的最优一定包含了全局经历过的最优值
if(bird.PbestY<=Flag):
GBestX = bird.PBestX
Flag = bird.PbestY
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY=Flag
if __name__ == '__main__':
start = time.time()
sPSO = SPso()
sPSO.InitPopulation()
sPSO.Running()
end = time.time()
print("Y: ",sPSO.Population[0].GBestY)
print("X: ",sPSO.Population[0].GBestX)
print("花费时长:",end-start)
fonction objectif
La fonction objective est en fait entièrement dans Target. À l'heure actuelle, elle fait encore de l'intégration d'algorithme. Beaucoup de choses qu'elle contient ne sont en fait pas du tout structurées, mais cela sera changé très rapidement plus tard. Maintenant, pour insérer quelques algorithmes.
import math
import sys
import os
sys.path.append(os.path.abspath(os.path.dirname(os.getcwd())))
class Target(object):
def SquareSum(self,X):
res = 0
for x in X:
res+=x*x
return res
Optimisation des paramètres (population unique) Algorithme de la série PSO
Nous en intégrons en fait trois ici
LPSO
Il s'agit en fait d'un poids qui change linéairement.
"""
LPSO:这个玩意其实还只是对W进行优化了
"""
import time
from ALGSet.Alg.PSO.SPSO import SPso
from ALGSet.Config.PSO.SPSO import *
class LPso(SPso):
def Running(self):
# 这里开始进入迭代运算
for iterate in range(1, IterationsNumber + 1):
# 这个算的GBestX其实始终是在算下一轮的最好的玩意
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
w = LinearW(iterate)
self.W = w
for bird in self.Population:
x = self.ComputeX(bird)
y = self.target.SquareSum(x)
bird.X = x
bird.Y = y
if (bird.Y <= bird.PbestY):
bird.PBestX = bird.X
bird.PbestY = bird.Y
# 个体中的最优一定包含了全局经历过的最优值
if (bird.PbestY <= Flag):
GBestX = bird.PBestX
Flag = bird.PbestY
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
if __name__ == '__main__':
start = time.time()
lPSO = LPso()
lPSO.InitPopulation()
lPSO.Running()
end = time.time()
print("Y: ",lPSO.Population[0].GBestY)
print("X: ",lPSO.Population[0].GBestX)
print("花费时长:",end-start)
DPSO
Cela transforme en fait des poids linéaires en cette chose
def Dw(iterate):
w = Wmax-((iterate**2)*((Wmax-Wmin)/(IterationsNumber**2)))
return w
代码其实就是把刚刚的WLinear变成了Dw
NPSO
同理,w函数变成这个了。
def Nw(iterate):
w = Wmin+(Wmax-Wmin)*(((IterationsNumber-iterate)**m)/(IterationsNumber**m))
return w
自适应PSO(VCAPSO)
这个算法的实现相对复杂一点,其实也不难。 具体资料的话自己感兴趣可以去查查,我这里还没整理好,就不发了。
参数配置
这个的话也是在Config那个包下面的
#coding=utf-8
# 相关参数的设置通过配置中心完成
import sys
import os
sys.path.append(os.path.abspath(os.path.dirname(os.getcwd())))
C1=1.458
C2=1.458
K1 = 0.72
K2 = 0.9
DIM = 10
PopulationSize=30
IterationsNumber = 3000
X_down = -10.0
X_up = 10
V_min = -5.0
V_max = 5
Wmax = 0.9
Wmin = 0.4
核心代码
"""
这个算法其实也是关于参数进行了优化的
基于云自适应算法进行适应的(什么叫做云我也不懂,不过公式给我就好了)
"""
import math
import time
import random
from ALGSet.Alg.PSO.SPSO import SPso
from ALGSet.Config.PSO.VCAPSO import *
class VCAPso(SPso):
F_avg = 0.
F_avg1=0.
F_avg2=0.
En = 0.
He = 0.
def InitPopulation(self):
#初始化种群
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
for bird in self.Population:
bird.PBestX = bird.X
bird.Y = self.target.SquareSum(bird.X)
bird.PbestY = bird.Y
self.F_avg+=bird.Y
if(bird.Y<=Flag):
GBestX = bird.X
Flag = bird.Y
#便利了一遍我们得到了全局最优的种群
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
self.F_avg/=PopulationSize
self.En = (self.F_avg-Flag)/C1
self.He = self.En/C2
self.En = random.uniform(self.En,self.He)
self.F_avg1,self.F_avg2 = self.__GetAvg2(self.Population)
def ComputeV(self,bird):
#这个方法是用来计算速度滴
NewV=[]
if(bird.Y<=self.F_avg1):
w = K1
elif(bird.Y>=self.F_avg2):
w = K2
else:
w = Wmax-Wmin*(math.exp(-((bird.Y-self.En)**2)/(2*(self.En**2))))
for i in range(DIM):
v = bird.V[i]*w + C1*self.Random()*(bird.PBestX[i]-bird.X[i])\
+C2*self.Random()*(bird.GBestX[i]-bird.X[i])
#这里注意判断是否超出了范围
if(v>V_max):
v = V_max
elif(v<V_min):
v = V_min
NewV.append(v)
return NewV
def __GetAvg2(self,Population):
F_avg1 = 0.
F_avg2 = 0.
F_avg1_index = 0
F_avg2_index = 0
for bird in Population:
if(bird.Y<self.F_avg):
F_avg1_index+=1
F_avg1+=bird.Y
elif(bird.Y>self.F_avg):
F_avg2_index+=1
F_avg2+=bird.Y
if (not F_avg1_index == 0):
F_avg1 /= F_avg1_index
else:
F_avg1 = float("inf")
if (not F_avg2_index == 0):
F_avg2 /= F_avg2_index
else:
F_avg2 = float("inf")
return F_avg1,F_avg2
def Running(self):
# 这里开始进入迭代运算
for iterate in range(1, IterationsNumber + 1):
# 这个算的GBestX其实始终是在算下一轮的最好的玩意
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
F_avg = 0.
for bird in self.Population:
x = self.ComputeX(bird)
y = self.target.SquareSum(x)
bird.X = x
bird.Y = y
F_avg += bird.Y
if (bird.Y <= bird.PbestY):
bird.PBestX = bird.X
bird.PbestY = bird.Y
# 个体中的最优一定包含了全局经历过的最优值
if (bird.PbestY <= Flag):
GBestX = bird.PBestX
Flag = bird.PbestY
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
self.F_avg = F_avg
self.F_avg /= PopulationSize
self.En = (self.F_avg - Flag) / C1
self.He = self.En / C2
self.En = random.uniform(self.En, self.He)
self.F_avg1, self.F_avg2 = self.__GetAvg2(self.Population)
if __name__ == '__main__':
start = time.time()
vcaPso = VCAPso()
vcaPso.InitPopulation()
vcaPso.Running()
end = time.time()
print("Y: ", vcaPso.Population[0].GBestY)
print("X: ", vcaPso.Population[0].GBestX)
print("花费时长:", end - start)
综合粒子群算法(CLPSO)
这个算法是在原来那篇论文里面提到的,先去复现的时候也是复现了的其实,现在只是单独提取出来罢了。 值得一提的是,这个玩意其实设计出来主要是应对多峰函数的,收敛也较慢。
import math
import time
from ALGSet.Target.Target import Target
from ALGSet.Config.PSO.CLPSO import *
from ALGSet.Alg.PSO.Bird.CLBird import CLBird
import random
class CLPso(object):
Population = None
Random = random.random
target = Target()
W = 0.
Math = math
def __init__(self):
#为了方便,我们这边直接先从1开始
self.Population = [CLBird(ID) for ID in range(1,PopulationSize+1)]
def __PCi(self,i,ps):
"""
论文当中的PCi的算子
:return:
"""
pci = 0.05+0.45*((self.Math.exp(10*(i-1)/(ps-1)))/(self.Math.exp(10)-1))
return pci
def NewComputeV(self, bird):
"""
:param bird:
:param params: 传入的数据格式为:[[w,c1,c2,c3],[],[],[],[]] 这里一共是5组共设置100个粒子
:return:
这里按照ID的顺序来调用不同的参数
"""
NewV = []
for i in range(DIM):
v = bird.V[i] * self.W
if (self.Random() < self.__PCi((i + 1), PopulationSize)):
pbestfi = bird.Follow.PBestX[i]
else:
pbestfi = bird.PBestX[i]
v = v + C1 * self.Random() * (pbestfi - bird.X[i])
if (v > V_max):
v = V_max
elif (v < V_min):
v = V_min
NewV.append(v)
return NewV
def NewComputeX(self, bird: CLBird):
NewX = []
NewV = self.NewComputeV(bird)
bird.V = NewV
for i in range(DIM):
x = bird.X[i] + NewV[i]
if (x > X_up):
x = X_up
elif (x < X_down):
x = X_down
NewX.append(x)
return NewX
def InitPopulation(self):
#初始化种群,不过是给ENV调用的,因为这个里面有一个CLPSO的思想
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
for bird in self.Population:
bird.PBestX = bird.X
bird.Y = self.target.SquareSum(bird.X)
bird.PbestY = bird.Y
if(bird.Y<=Flag):
GBestX = bird.X
Flag = bird.Y
#便利了一遍我们得到了全局最优的种群
self.GBestY = Flag
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
#现在是初始化,所以这个这样算是没问题的
self.GBestYLast = Flag
#给每一个粒子找到一个追随者
self.ChangeBird(bird,self.Population)
def ChangeBird(self,bird,Population):
#这个主要是实现锦标赛法来对粒子的跟踪对象进行更新
while True:
#被跟踪的粒子不能和自己一样,也不能和上一个一样
a,b = random.sample(range(PopulationSize),2)
a = Population[a];b=Population[b]
follow = a
if(a.PbestY>b.PbestY):
follow = b
if(follow.ID!=bird.ID):
if(bird.Follow):
if(bird.Follow.ID !=follow.ID):
bird.Follow = follow
return
else:
bird.Follow = follow
return
def Running(self):
for iterate in range(1,IterationsNumber+1):
#这个算的GBestX其实始终是在算下一轮的最好的玩意
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
self.W = LinearW(iterate)
for bird in self.Population:
x = self.NewComputeX(bird)
y = self.target.SquareSum(x)
bird.X = x
bird.Y = y
if(bird.Y<=bird.PbestY):
bird.PBestX=bird.X
bird.PbestY = bird.Y
elif (bird.Y == bird.PbestY):
bird.NoChange += 1
if (bird.NoChange == M_follow):
self.ChangeBird(bird, self.Population)
bird.NoChange = 0
#个体中的最优一定包含了全局经历过的最优值
if(bird.PbestY<=Flag):
GBestX = bird.PBestX
Flag = bird.PbestY
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY=Flag
if __name__ == '__main__':
start = time.time()
clPSO = CLPso()
clPSO.InitPopulation()
clPSO.Running()
end = time.time()
print("Y: ",clPSO.Population[0].GBestY)
print("X: ",clPSO.Population[0].GBestX)
print("花费时长:",end-start)
多种群算法
MPSO 算法
这个算法就是分三个种群,然后,一个执行LPSO,一个执行SPSO,还一个执行VCAPSO。
这个就是集成三个算法,然后改了一些速度方程。
v = bird.V[i] * w + C1 * self.Random() * (bird.PBestX[i] - bird.X[i]) \
+ C2*self.Random()*(bird.CBestX[i]-bird.X[i])\
+C3*self.Random()*(self.GBestX[i]-bird.X[i])
HPSO算法
这个就是混合多种群PSO。也是代码很简单,而且是目前测试效果最好的。
import random
import time
from ALGSet.Alg.PSO.Bird.Hbird import HBird
from ALGSet.Config.PSO.HPSO import *
from ALGSet.Target.Target import Target
class HPso():
rand = random.random
miu = miu
target = Target()
def __init__(self):
self.Population = [HBird(ID) for ID in range(1,PopulationSize+1)]
self.Divide()
def Divide(self):
#我们这边直接通过ID进行分类
CID = 0
for bird in self.Population:
bird.CID=CID
if(bird.ID % ClusterSize==0):
if(CID<=ClusterNumber):
CID+=1
def ComputeV(self,bird):
#这个方法是用来计算速度滴
NewV=[]
for i in range(DIM):
v1 = bird.V[i] * self.W + C1 * self.rand() * (bird.PBestX[i] - bird.X[i]) \
+ C2 * self.rand() * (bird.GBestX[i] - bird.X[i])
v2 = bird.V[i] * self.W + C1 * self.rand() * (bird.PBestX[i] - bird.X[i]) \
+ C2 * self.rand() * (bird.CBestX[i] - bird.X[i])
v = v1*self.miu+(1-self.miu)*v2
if(v>V_max):
v = V_max
elif(v<V_min):
v = V_min
NewV.append(v)
return NewV
def ComputeX(self,bird):
NewX = []
NewV = self.ComputeV(bird)
bird.V = NewV
for i in range(DIM):
x = bird.X[i]+NewV[i]
if (x > X_up):
x = X_up
elif (x < X_down):
x = X_down
NewX.append(x)
return NewX
def InitPopulation(self):
#初始化种群
#这个是记录全局最优解的
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
#还有一个是记录Cluster最优解的
CBest = {}
CFlag = {}
for i in range(ClusterNumber):
CFlag[i]=float("inf")
for bird in self.Population:
bird.PBestX = bird.X
bird.Y = self.target.SquareSum(bird.X)
bird.PbestY = bird.Y
bird.CBestX = bird.X
bird.CBestY = bird.Y
if(bird.Y<=Flag):
GBestX = bird.X
Flag = bird.Y
if(bird.Y<=CFlag.get(bird.CID)):
CBest[bird.CID]=bird.X
CFlag[bird.CID] = bird.Y
#便利了一遍我们得到了全局最优的种群
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY = Flag
bird.CBestY=CFlag.get(bird.CID)
bird.CBestX=CBest.get(bird.CID)
def Running(self):
#这里开始进入迭代运算
for iterate in range(1,IterationsNumber+1):
w = LinearW(iterate)
#这个算的GBestX其实始终是在算下一轮的最好的玩意
GBestX = [0. for _ in range(DIM)]
Flag = float("inf")
CBest = {}
CFlag = {}
for i in range(ClusterNumber):
CFlag[i] = float("inf")
for bird in self.Population:
#更改为线性权重
self.W = w
x = self.ComputeX(bird)
y = self.target.SquareSum(x)
bird.X = x
bird.Y = y
if(bird.Y<=bird.PbestY):
bird.PBestX=bird.X
bird.PbestY = bird.Y
#个体中的最优一定包含了全局经历过的最优值
if(bird.PbestY<=Flag):
GBestX = bird.PBestX
Flag = bird.PbestY
if (bird.Y <= CFlag.get(bird.CID)):
CBest[bird.CID] = bird.X
CFlag[bird.CID] = bird.Y
for bird in self.Population:
bird.GBestX = GBestX
bird.GBestY=Flag
bird.CBestY = CFlag.get(bird.CID)
bird.CBestX = CBest.get(bird.CID)
if __name__ == '__main__':
start = time.time()
hPso = HPso()
hPso.InitPopulation()
hPso.Running()
end = time.time()
print("Y: ", hPso.Population[0].GBestY)
print("X: ", hPso.Population[0].GBestX)
print("花费时长:", end - start)
后续工作
搞可视化测试,后面,不过,这个要后面在做,代码后面上传。
- 我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿。