mirror of
https://github.com/jung-geun/PSO.git
synced 2025-12-20 04:50:45 +09:00
23-05-29
EBPSO 알고리즘 구현 - 선택지로 추가 random 으로 분산시키는 방법 구현 - 선택지로 추가 iris 기준 98퍼센트로 나오나 정확한 결과를 지켜봐야 할것으로 보임
This commit is contained in:
14
psokeras/__init__.py
Executable file
14
psokeras/__init__.py
Executable file
@@ -0,0 +1,14 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""PSOkeras - Particle Swarm Optimizer for Keras models
|
||||
|
||||
This module implements a particle swarm optimizer for training the weights of Keras models. The
|
||||
|
||||
"""
|
||||
|
||||
|
||||
from .version import __version__
|
||||
from .optimizer import Optimizer
|
||||
|
||||
__all__ = [
|
||||
'Optimizer',
|
||||
]
|
||||
67
psokeras/optimizer.py
Executable file
67
psokeras/optimizer.py
Executable file
@@ -0,0 +1,67 @@
|
||||
BIG_SCORE = 1.e6 # type: float
|
||||
|
||||
import keras
|
||||
from psokeras.particle import Particle
|
||||
from .util import ProgressBar
|
||||
|
||||
|
||||
class Optimizer:
|
||||
def __init__(self, model, loss,
|
||||
n=10,
|
||||
acceleration=0.1,
|
||||
local_rate=1.0,
|
||||
global_rate=1.0):
|
||||
|
||||
self.n_particles = n
|
||||
self.structure = model.to_json()
|
||||
self.particles = [None] * n
|
||||
self.loss = loss
|
||||
self.length = len(model.get_weights())
|
||||
|
||||
params = {'acc': acceleration, 'local_acc': local_rate, 'global_acc': global_rate}
|
||||
|
||||
for i in range(n-1):
|
||||
m = keras.models.model_from_json(self.structure)
|
||||
m.compile(loss=loss,optimizer='sgd')
|
||||
self.particles[i] = Particle(m, params)
|
||||
|
||||
self.particles[n-1] = Particle(model, params)
|
||||
|
||||
self.global_best_weights = None
|
||||
self.global_best_score = BIG_SCORE
|
||||
|
||||
def fit(self, x, y, steps=0, batch_size=32):
|
||||
num_batches = x.shape[0] // batch_size
|
||||
|
||||
for i, p in enumerate(self.particles):
|
||||
local_score = p.get_score(x, y)
|
||||
|
||||
if local_score < self.global_best_score:
|
||||
self.global_best_score = local_score
|
||||
self.global_best_weights = p.get_best_weights()
|
||||
|
||||
print("PSO -- Initial best score {:0.4f}".format(self.global_best_score))
|
||||
|
||||
bar = ProgressBar(steps, updates=20)
|
||||
|
||||
for i in range(steps):
|
||||
for j in range(num_batches):
|
||||
x_ = x[j*batch_size:(j+1)*batch_size,:]
|
||||
y_ = y[j*batch_size:(j+1)*batch_size]
|
||||
|
||||
for p in self.particles:
|
||||
local_score = p.step(x_, y_, self.global_best_weights)
|
||||
|
||||
if local_score < self.global_best_score:
|
||||
self.global_best_score = local_score
|
||||
self.global_best_weights = p.get_best_weights()
|
||||
|
||||
bar.update(i)
|
||||
|
||||
bar.done()
|
||||
|
||||
def get_best_model(self):
|
||||
best_model = keras.models.model_from_json(self.structure)
|
||||
best_model.set_weights(self.global_best_weights)
|
||||
best_model.compile(loss=self.loss,optimizer='sgd')
|
||||
return best_model
|
||||
66
psokeras/particle.py
Executable file
66
psokeras/particle.py
Executable file
@@ -0,0 +1,66 @@
|
||||
import random
|
||||
|
||||
import numpy as np
|
||||
|
||||
from psokeras.optimizer import BIG_SCORE
|
||||
|
||||
|
||||
class Particle:
|
||||
def __init__(self, model, params):
|
||||
self.model = model
|
||||
self.params = params
|
||||
self.init_weights = model.get_weights()
|
||||
self.velocities = [None] * len(self.init_weights)
|
||||
self.length = len(self.init_weights)
|
||||
for i, layer in enumerate(self.init_weights):
|
||||
self.velocities[i] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||
# self.velocities[i] = np.zeros(layer.shape)
|
||||
|
||||
self.best_weights = None
|
||||
self.best_score = BIG_SCORE
|
||||
|
||||
def get_score(self, x, y, update=True):
|
||||
local_score = self.model.evaluate(x, y, verbose=0)
|
||||
if local_score < self.best_score and update:
|
||||
self.best_score = local_score
|
||||
self.best_weights = self.model.get_weights()
|
||||
|
||||
return local_score
|
||||
|
||||
def _update_velocities(self, global_best_weights, depth):
|
||||
new_velocities = [None] * len(self.init_weights)
|
||||
weights = self.model.get_weights()
|
||||
local_rand, global_rand = random.random(), random.random()
|
||||
|
||||
for i, layer in enumerate(weights):
|
||||
if i >= depth:
|
||||
new_velocities[i] = self.velocities[i]
|
||||
continue
|
||||
new_v = self.params['acc'] * self.velocities[i]
|
||||
new_v = new_v + self.params['local_acc'] * local_rand * (self.best_weights[i] - layer)
|
||||
new_v = new_v + self.params['global_acc'] * global_rand * (global_best_weights[i] - layer)
|
||||
new_velocities[i] = new_v
|
||||
|
||||
self.velocities = new_velocities
|
||||
|
||||
def _update_weights(self, depth):
|
||||
old_weights = self.model.get_weights()
|
||||
new_weights = [None] * len(old_weights)
|
||||
for i, layer in enumerate(old_weights):
|
||||
if i>= depth:
|
||||
new_weights[i] = layer
|
||||
continue
|
||||
new_w = layer + self.velocities[i]
|
||||
new_weights[i] = new_w
|
||||
|
||||
self.model.set_weights(new_weights)
|
||||
|
||||
def step(self, x, y, global_best_weights,depth=None):
|
||||
if depth is None:
|
||||
depth = self.length
|
||||
self._update_velocities(global_best_weights, depth)
|
||||
self._update_weights(depth)
|
||||
return self.get_score(x, y)
|
||||
|
||||
def get_best_weights(self):
|
||||
return self.best_weights
|
||||
31
psokeras/util.py
Executable file
31
psokeras/util.py
Executable file
@@ -0,0 +1,31 @@
|
||||
class ProgressBar:
|
||||
def __init__(self, steps, updates=10):
|
||||
self.step = 0
|
||||
self.step_size = (steps // updates)
|
||||
self.total_steps = steps
|
||||
self.updates = updates
|
||||
|
||||
bar = self._make_bar(0)
|
||||
print(bar, end=' ')
|
||||
|
||||
def update(self, i):
|
||||
if i % self.step_size > 0:
|
||||
return
|
||||
|
||||
self.step = i // self.step_size
|
||||
bar = self._make_bar(i)
|
||||
|
||||
print(bar, end=' ')
|
||||
|
||||
def done(self):
|
||||
self.step = self.total_steps
|
||||
bar = self._make_bar(self.updates)
|
||||
print(bar)
|
||||
|
||||
def _make_bar(self, x):
|
||||
bar = "["
|
||||
for x in range(self.updates):
|
||||
print("\r", end=' ')
|
||||
bar += "=" if x < self.step else " "
|
||||
bar += "]"
|
||||
return bar
|
||||
1
psokeras/version.py
Executable file
1
psokeras/version.py
Executable file
@@ -0,0 +1 @@
|
||||
__version__ = '0.2.0'
|
||||
Reference in New Issue
Block a user