pso 알고리즘을 구현하는데 bp 를 완전히 배제하는 방법으로 구현
model 디렉토리를 자동으로 생성하게 수정
This commit is contained in:
jung-geun
2023-05-24 14:00:31 +09:00
parent 7c5f3a53a3
commit 27d40ab56c
9 changed files with 1556 additions and 352 deletions

View File

@@ -9,7 +9,7 @@ class PSO(object):
Class implementing PSO algorithm
"""
def __init__(self, model, loss_method=keras.losses.MeanSquaredError(), optimizer=keras.optimizers.SGD(), n_particles=5):
def __init__(self, model: keras.models, x_train, y_train, loss_method=keras.losses.MeanSquaredError(), n_particles=5):
"""
Initialize the key variables.
@@ -22,7 +22,6 @@ class PSO(object):
self.model = model # 모델
self.n_particles = n_particles # 파티클의 개수
self.loss_method = loss_method # 손실 함수
self.optimizer = optimizer # 최적화 함수
self.model_structure = self.model.to_json() # 모델의 구조
self.init_weights = self.model.get_weights() # 검색할 차원
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
@@ -30,9 +29,12 @@ class PSO(object):
for _ in tqdm(range(self.n_particles), desc="init particles position"):
# particle_node = []
m = keras.models.model_from_json(self.model_structure)
m.compile(loss=self.loss_method, optimizer=self.optimizer)
m.compile(loss=self.loss_method,
optimizer="adam", metrics=["accuracy"])
# m.fit(x_train, y_train, epochs=1, batch_size=32, verbose=0) # 결과가 너무 좋지 않아서 처음 초기화 할때 어느정도 위치를 수정
self.particles_weights[_] = m.get_weights()
# print(f"shape > {self.particles_weights[_][0]}")
# self.particles_weights.append(particle_node)
@@ -72,10 +74,12 @@ class PSO(object):
# 최대 사이즈로 전역 최적갑 저장 - global best
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치)
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
self.p_best_score = [np.inf for i in range(
self.p_best_score = [0 for i in range(
n_particles)] # 각 파티클의 최적값의 점수
self.g_best_score = np.inf # 전역 최적값의 점수(초기화 - 무한대)
self.g_best_score = 0 # 전역 최적값의 점수(초기화 - 무한대)
self.g_history = []
self.all_cost_history = [[] for i in range(n_particles)]
self.g_best_score_history = []
self.history = []
def _update_weights(self, weights, v):
@@ -139,12 +143,13 @@ class PSO(object):
new_v = w*v[i]
new_v = new_v + c0*r0*(p_best[i] - layer)
new_v = new_v + c1*r1*(self.g_best[i] - layer)
new_velocity[i] = new_v
# m2 = tf.multiply(tf.multiply(c0, r0),
# tf.subtract(p_best[i], layer))
new_v = new_v + c1*r1*(self.g_best[i] - layer)
# m3 = tf.multiply(tf.multiply(c1, r1),
# tf.subtract(g_best[i], layer))
new_velocity[i] = new_v
# new_v[i] = tf.add(m1, tf.add(m2, m3))
# new_v[i] = tf.add_n([m1, m2, m3])
# new_v[i] = tf.add_n(
@@ -172,7 +177,7 @@ class PSO(object):
return score
def optimize(self, x_train, y_train, x_test, y_test, maxiter=20, epoch=10, verbose=0):
def optimize(self, x_train, y_train, x_test, y_test, maxiter=10, c0=0.5, c1=1.5, w=0.75):
"""
Run the PSO optimization process utill the stoping critera is met.
Cas for minization. The aim is to minimize the cost function
@@ -186,40 +191,45 @@ class PSO(object):
for _ in range(maxiter):
loss = 0
acc = 0
for i in tqdm(range(self.n_particles), desc=f"Iteration {_} / {maxiter}", ascii=True):
for i in tqdm(range(self.n_particles), desc=f"Iter {_}/{maxiter}", ascii=True):
weights = self.particles_weights[i] # 각 파티클 추출
v = self.velocities[i] # 각 파티클의 다음 속도 추출
p_best = self.p_best[i] # 결과치 저장할 변수 지정
# 2. 속도 계산
self.velocities[i] = self._update_velocity(
weights, v, p_best)
weights, v, p_best, c0, c1, w)
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
# 3. 위치 업데이트
self.particles_weights[i] = self._update_weights(weights, v)
# 현재 위치 = 최초 위치 현재 속도
# Update the besst position for particle i
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
self.model.set_weights(self.particles_weights[i])
self.model.fit(x_train, y_train, epochs=epoch,
verbose=0, validation_data=(x_test, y_test))
self.particles_weights[i] = self.model.get_weights()
self.model.set_weights(self.particles_weights[i].copy())
# self.model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size,
# verbose=0, validation_data=(x_test, y_test))
# self.particles_weights[i] = self.model.get_weights()
# 4. 평가
self.model.compile(loss=self.loss_method,
optimizer='adam', metrics=['accuracy'])
score = self._get_score(x_test, y_test)
# print(score)
# print(f"score : {score}")
# print(f"loss : {loss}")
# print(f"p_best_score : {self.p_best_score[i]}")
if score[0] < self.p_best_score[i]:
self.p_best_score[i] = score[0]
self.p_best[i] = self.particles_weights[i]
if score[0] < self.g_best_score:
self.g_best_score = score[0]
if score[1] > self.p_best_score[i]:
self.p_best_score[i] = score[1]
self.p_best[i] = self.particles_weights[i].copy()
if score[1] > self.g_best_score:
self.g_best_score = score[1]
self.g_best = self.particles_weights[i].copy()
self.g_history.append(self.g_best.copy())
self.g_history.append(self.g_best)
self.g_best_score_history.append(
self.g_best_score)
self.score = score[0]
loss = score[0]
acc = score[1]
self.score = score
self.all_cost_history[i].append(score)
# if self.func(self.particles_weights[i]) < self.func(p_best):
# self.p_best[i] = self.particles_weights[i]
# if self.
@@ -229,7 +239,8 @@ class PSO(object):
# self.g_best = self.particles_weights[i]
# self.g_history.append(self.g_best)
# print(f"{i} particle score : {score[0]}")
print(f"loss : {loss} | acc : {acc}")
print(
f"loss avg : {self.score[0]/self.n_particles} | acc avg : {self.score[1]/self.n_particles} | best loss : {self.g_best_score}")
# self.history.append(self.particles_weights.copy())
@@ -259,3 +270,14 @@ class PSO(object):
def global_history(self):
return self.g_history.copy()
"""
Returns:
global best score 의 갱신된 값의 변화를 반환
"""
def global_score_history(self):
return self.g_best_score_history.copy()
def all_cost(self):
return self.all_cost_history.copy()