mirror of
https://github.com/jung-geun/PSO.git
synced 2025-12-20 04:50:45 +09:00
빌드 단계 추가 및 코드 정리
This commit is contained in:
@@ -12,7 +12,12 @@ class PSO(object):
|
||||
Class implementing PSO algorithm
|
||||
"""
|
||||
|
||||
def __init__(self, model: keras.models, loss_method=keras.losses.MeanSquaredError(), n_particles: int = 5):
|
||||
def __init__(
|
||||
self,
|
||||
model: keras.models,
|
||||
loss_method=keras.losses.MeanSquaredError(),
|
||||
n_particles: int = 5,
|
||||
):
|
||||
"""
|
||||
Initialize the key variables.
|
||||
|
||||
@@ -21,40 +26,41 @@ class PSO(object):
|
||||
loss_method : 손실 함수
|
||||
n_particles(int) : 파티클의 개수
|
||||
"""
|
||||
self.model = model # 모델
|
||||
self.n_particles = n_particles # 파티클의 개수
|
||||
self.loss_method = loss_method # 손실 함수
|
||||
self.model_structure = self.model.to_json() # 모델의 구조 정보
|
||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||
self.model = model # 모델
|
||||
self.n_particles = n_particles # 파티클의 개수
|
||||
self.loss_method = loss_method # 손실 함수
|
||||
self.model_structure = self.model.to_json() # 모델의 구조 정보
|
||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||
m = keras.models.model_from_json(self.model_structure)
|
||||
m.compile(loss=self.loss_method,
|
||||
optimizer="adam", metrics=["accuracy"])
|
||||
m.compile(loss=self.loss_method, optimizer="adam", metrics=["accuracy"])
|
||||
self.particles_weights[_] = m.get_weights()
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||
self.velocities = [
|
||||
[0 for i in range(self.particle_depth)] for n in range(n_particles)]
|
||||
[0 for i in range(self.particle_depth)] for n in range(n_particles)
|
||||
]
|
||||
for i in tqdm(range(n_particles), desc="init velocities"):
|
||||
for index, layer in enumerate(self.init_weights):
|
||||
self.velocities[i][index] = np.random.rand(
|
||||
*layer.shape) / 5 - 0.10
|
||||
self.velocities[i][index] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||
|
||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||
self.g_best = (
|
||||
self.model.get_weights()
|
||||
) # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||
|
||||
# 각 파티클의 최적값의 점수
|
||||
self.p_best_score = [0 for i in range(n_particles)]
|
||||
|
||||
# 전역 최적값의 점수(초기화 - 0)
|
||||
self.g_best_score = 0
|
||||
self.loss_history = [[] for i in range(n_particles)] # 각 파티클의 손실값 변화
|
||||
self.acc_history = [[] for i in range(n_particles)] # 각 파티클의 정확도 변화
|
||||
self.g_best_score_history = [] # 전역 최적값의 점수 변화
|
||||
self.loss_history = [[] for i in range(n_particles)] # 각 파티클의 손실값 변화
|
||||
self.acc_history = [[] for i in range(n_particles)] # 각 파티클의 정확도 변화
|
||||
self.g_best_score_history = [] # 전역 최적값의 점수 변화
|
||||
|
||||
def _update_weights(self, weights, v):
|
||||
"""
|
||||
@@ -73,22 +79,22 @@ class PSO(object):
|
||||
for i in range(len(weights)):
|
||||
new_weights[i] = tf.add(weights[i], v[i])
|
||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
||||
return new_weights # 진행한 파티클들의 위치를 반환
|
||||
return new_weights # 진행한 파티클들의 위치를 반환
|
||||
|
||||
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||
"""
|
||||
Update particle velocity
|
||||
Update particle velocity
|
||||
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 속도
|
||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||
Args:
|
||||
weights (array-like) : 파티클의 현재 가중치
|
||||
v (array-like) : 속도
|
||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||
|
||||
Returns:
|
||||
(array-like) : 각 파티클의 새로운 속도
|
||||
Returns:
|
||||
(array-like) : 각 파티클의 새로운 속도
|
||||
"""
|
||||
# x = np.array(x)
|
||||
# v = np.array(v)
|
||||
@@ -106,9 +112,9 @@ class PSO(object):
|
||||
new_velocity = [None] * len(weights)
|
||||
for i, layer in enumerate(weights):
|
||||
|
||||
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_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
|
||||
|
||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
||||
@@ -141,13 +147,16 @@ class PSO(object):
|
||||
"""
|
||||
for _ in range(maxiter):
|
||||
|
||||
for i in tqdm(range(self.n_particles), desc=f"Iter {_}/{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] # 결과치 저장할 변수 지정
|
||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||
# 2. 속도 계산
|
||||
self.velocities[i] = self._update_velocity(
|
||||
weights, v, p_best, c0, c1, w)
|
||||
weights, v, p_best, c0, c1, w
|
||||
)
|
||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||
# 3. 위치 업데이트
|
||||
self.particles_weights[i] = self._update_weights(weights, v)
|
||||
@@ -156,8 +165,9 @@ class PSO(object):
|
||||
self.model.set_weights(self.particles_weights[i].copy())
|
||||
# self.particles_weights[i] = self.model.get_weights()
|
||||
# 4. 평가
|
||||
self.model.compile(loss=self.loss_method,
|
||||
optimizer='adam', metrics=['accuracy'])
|
||||
self.model.compile(
|
||||
loss=self.loss_method, optimizer="adam", metrics=["accuracy"]
|
||||
)
|
||||
score = self._get_score(x_, y_)
|
||||
|
||||
if score[1] > self.p_best_score[i]:
|
||||
@@ -166,14 +176,14 @@ class PSO(object):
|
||||
if score[1] > self.g_best_score:
|
||||
self.g_best_score = score[1]
|
||||
self.g_best = self.particles_weights[i].copy()
|
||||
self.g_best_score_history.append(
|
||||
self.g_best_score)
|
||||
self.g_best_score_history.append(self.g_best_score)
|
||||
|
||||
self.loss_history[i].append(score[0])
|
||||
self.acc_history[i].append(score[1])
|
||||
|
||||
print(
|
||||
f"loss avg : {score[0]/self.n_particles} | acc avg : {score[1]/self.n_particles} | best score : {self.g_best_score}")
|
||||
f"loss avg : {score[0]/self.n_particles} | acc avg : {score[1]/self.n_particles} | best score : {self.g_best_score}"
|
||||
)
|
||||
|
||||
# 전체 최소 위치, 전체 최소 벡터
|
||||
return self.g_best, self._get_score(x_, y_)
|
||||
@@ -193,6 +203,7 @@ class PSO(object):
|
||||
|
||||
def best_score(self):
|
||||
return self.g_best_score
|
||||
|
||||
"""
|
||||
Returns:
|
||||
global best score 의 갱신된 값의 변화를 반환
|
||||
|
||||
Reference in New Issue
Block a user