Ich habe vor einiger Zeit in diesem Artikel einen genetischen Algorithmus geschrieben, aber diesmal habe ich versucht, einen Optimierungsalgorithmus zu erstellen, der mit derselben Idee erstellt wurde.
Ich sehe oft Fische und Vögel, die sich in Gruppen bewegen. Selbst wenn diese Schwärme Feinde oder Nahrung finden, führen sie optimale Bewegungen mit ungestörten Bewegungen aus. Es ist eine Methode, dies zur Funktionsoptimierung zu nutzen.
Referenzen gibt es hier Einführung in den evolutionären Berechnungsalgorithmus Partikelgruppenoptimierung und nichtlineares System
Ich habe nichts Kompliziertes getan und es auf einfachste Weise implementiert.
functions.py
import random
# min~Zahlen Sie zufällig zwischen max
def randRange(a : float,b : float) -> float:
return a + (b-a)*random.random()
#Erzeugen Sie n Partikel
def makeParticles(n : int,ranges : dict) -> list:
ls = [{key:0 for key in ranges.keys()} for key in range(n)]
for i in range(n):
for key in ranges.keys():
a,b = ranges[key]
ls[i][key] = randRange(a,b)
return ls
#Fügen Sie die gleichen Elemente von zwei Diktaten hinzu
def dictAdd(*dic : dict) -> dict:
ansDic = {}
for key in dic[0].keys():
ansDic[key] = 0
for i in range(len(dic)):
ansDic[key] += dic[i][key]
return ansDic
#Subtrahieren Sie die gleichen Elemente von zwei Diktaten
def dictDiff(dic1 : dict,dic2 : dict) -> dict:
ansDic = {}
for key in dic1.keys():
ansDic[key] = dic1[key] - dic2[key]
return ansDic
#Produkt der gleichen Elemente von zwei Diktaten
def dictMul(dic1 : dict, dic2 : dict) -> dict:
ansDic = {}
for key in dic1.keys():
ansDic[key] = dic1[key] * dic2[key]
#Multiplizieren Sie jedes Element des Diktats
def dictNumMul(dic : dict,n) -> dict:
ansDic = {}
for key in dic.keys():
ansDic[key] = dic[key] * n
return ansDic
PSO.py
import functions as func
import numpy as np
import copy
"""
time_max Maximale Anzahl von Iterationen
swam_Größe Anzahl der Partikel
Trägheit Trägheitskoeffizient
ap Persönlicher bester Beschleunigungskoeffizient
ag Global Best Acceleration Factor
"""
class PSO:
def __init__(self,time_max = 1000,swam_size = 100,
inertia = 0.9,ap = 0.8,ag = 0.8):
self.time_max = time_max
self.swam_size = swam_size
self.inertia = inertia
self.ap = ap
self.ag = ag
self.pBest = [np.inf for i in range(swam_size)]
self.gBest = np.inf
self.gPosi = {}
"""
Übergeben Sie die zu minimierende Funktion an das Argument f der Optimierungsfunktion
Dikt für Para-Argument
{"Argumentname":[Mindestwert,Maximalwert]}
Ich gebe es so weiter.
"""
#Erhalten Sie die zu optimierende Funktion und ihre Argumente
def optimize(self,f,para):
self.function = f
self.particleInitialization(para)
self.Update()
for i in range(self.time_max):
self.move()
self.Update()
return self.gPosi,self.gBest
#Initialisieren Sie die Partikel
def particleInitialization(self,ls : dict):
self.particle = func.makeParticles(self.swam_size,ls)
self.pPosi = copy.deepcopy(self.particle)
self.velocity = [{key:0 for key in ls.keys()} for i in range(self.swam_size)]
#Bewegung
def move(self):
for i in range(self.swam_size):
v0 = func.dictNumMul(self.velocity[i],self.inertia)
v1 = func.dictNumMul(func.dictDiff(self.pPosi[i],self.particle[i]),self.ap*func.randRange(0,1))
v2 = func.dictNumMul(func.dictDiff(self.gPosi,self.particle[i]),self.ag*func.randRange(0,1))
v = func.dictAdd(v0,v1,v2)
self.particle[i] = func.dictAdd(self.particle[i],v)
self.velocity[i] = v
#Aktualisieren Sie die persönliche Bestleistung und die globale Bestleistung
def Update(self):
for i in range(self.swam_size):
cost = self.function(**self.particle[i])
if cost < self.pBest[i]:
self.pBest[i] = cost
self.pPosi[i] = copy.deepcopy(self.particle[i])
if cost < self.gBest:
self.gBest = cost
self.gPosi = copy.deepcopy(self.particle[i])
main.py
import PSO
#Definieren Sie die Funktion, die Sie minimieren möchten
def f(x,y):
return x**4+4*x**3-8*(x+1)**2-1 + y**4 + x**3 - 5*(y - 2)**2 - 3*x
def main():
pso = PSO.PSO(time_max=1000)
#Frühe Partikel-10000<x<10000,-10000<y<Generieren Sie im Bereich von 10000 und minimieren Sie
a,b = pso.optimize(f,{"x":[-10000,10000],"y":[-10000,10000]})
print("Koordinate",a,"Mindestwert",b)
if __name__ == "__main__":
main()
Ausgabe Koordinaten {'x': -4.412547925687121, 'y': -2.187602966185929} Mindestwert -196.17514912856427
Ich konnte es minimieren.
[Ergebnisse mit wolframalpha](https://www.wolframalpha.com/input/?i=minimize%5Bx%5E4%2B4x%5E3-8%28x%2B1%29%5E2-1+%2B+ y% 5E4 +% 2B + x% 5E3 + - + 5 *% 28y + - + 2% 29% 5E2 + - + 3 * x% 5D)
Bis zu diesem Zeitpunkt habe ich es hochgeladen, aber es ist wirklich langweilig. Daher möchte ich eine logistische Regression mithilfe der Partikelgruppenoptimierungsmethode durchführen.
Hier wird die Klassifizierungsgrenze durch Minimieren der Kreuzentropiefehlerfunktion durch das Partikelgruppenoptimierungsverfahren vorhergesagt.
logistic.py
import functions as func
import math
import PSO
import numpy
#Grenze beim Beschriften generierte Zufallszahlen
def f(x,y):
if x + 2 * y < 11:return 1
else:return 0
#Sigmaid-Funktion
def sigmoid(x):
if 600 > x > -600:
return 1/(1 + math.exp(-x))
elif x > 0:
return 1
else:
return 0
#Unendlich zurückgeben, wenn es Null ist
def llog(x):
if x == 0:
return -numpy.inf
return math.log(x)
#Generieren Sie Daten mit Zufallszahlen
data = [[func.randRange(0,10),func.randRange(0,10)] for i in range(100)]
label = [f(x,y) for x,y in data]
#Kostenfunktion zu minimieren
def loss(w1,w2,b):
ent = 0
for i in range(len(data)):
x = sigmoid(data[i][0]*w1 + data[i][1]*w2 + b)
y = label[i]
ent -= y * llog(x) + (1-y) * llog(1-x)
return ent
def main():
pso = PSO.PSO()
a,b = pso.optimize(loss,{"w1":[-100,100],"w2":[-100,100],"b":[-100,100]})
print(a,b)
#Bewerten Sie, ob das erstellte Modell die Trainingsdaten richtig klassifizieren kann
c = 0
for i in range(100):
n = sigmoid(data[i][0]*a["w1"] + data[i][1]*a["w2"] + a["b"])
ans = 1 if n > 0.5 else 0
if ans == label[i]:
c += 1
print("Klassifizierungsgenauigkeit",c/100)
if __name__ == "__main__":
main()
Ergebnis
{'w1': -5.345994566644921, 'w2': -10.19111400412491, 'b': 56.97834543330356} 2.744570556357321 Klassifizierungsgenauigkeit 1.0
Ich konnte es fest einordnen.
Recommended Posts