mirror of
https://github.com/jung-geun/PSO.git
synced 2025-12-19 20:44:39 +09:00
빌드 단계 추가 및 코드 정리
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
stages:
|
stages:
|
||||||
- sonarqube-check
|
- sonarqube-check
|
||||||
|
- build
|
||||||
|
|
||||||
include:
|
include:
|
||||||
- local: ".gitlab/ci/*.gitlab-ci.yml"
|
- local: ".gitlab/ci/*.gitlab-ci.yml"
|
||||||
|
|||||||
18
.gitlab/ci/pypi.gitlab-ci.yml
Normal file
18
.gitlab/ci/pypi.gitlab-ci.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
variables:
|
||||||
|
PYTHON_VERSION: "3.9"
|
||||||
|
TWINE_USERNAME: "__token__"
|
||||||
|
|
||||||
|
build-package:
|
||||||
|
stage: build
|
||||||
|
image: python:${PYTHON_VERSION}
|
||||||
|
script:
|
||||||
|
- pip install --upgrade pip
|
||||||
|
- if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||||
|
- pip install setuptools wheel twine
|
||||||
|
- python setup.py bdist_wheel sdist
|
||||||
|
- twine upload dist/*.whl dist/*.tar.gz
|
||||||
|
|
||||||
|
only:
|
||||||
|
changes:
|
||||||
|
- "setup.py"
|
||||||
|
- "pso/__init__.py"
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
[](https://github.com/jung-geun/PSO/actions/workflows/pypi.yml)
|
[](https://github.com/jung-geun/PSO/actions/workflows/pypi.yml)
|
||||||
[](https://pypi.org/project/pso2keras/)
|
[](https://pypi.org/project/pso2keras/)
|
||||||
|
[](https://sonar.pieroot.xyz/dashboard?id=pieroot_pso_6a2f36a9-2688-4900-a4a5-5be85f36f75a)
|
||||||
|
[](https://sonar.pieroot.xyz/dashboard?id=pieroot_pso_6a2f36a9-2688-4900-a4a5-5be85f36f75a)
|
||||||
|
[](https://sonar.pieroot.xyz/dashboard?id=pieroot_pso_6a2f36a9-2688-4900-a4a5-5be85f36f75a)
|
||||||
|
|
||||||
### 목차
|
### 목차
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -14,10 +14,7 @@ from pso2keras import Particle
|
|||||||
gpus = tf.config.experimental.list_physical_devices("GPU")
|
gpus = tf.config.experimental.list_physical_devices("GPU")
|
||||||
if gpus:
|
if gpus:
|
||||||
try:
|
try:
|
||||||
# tf.config.experimental.set_visible_devices(gpus[0], "GPU")
|
|
||||||
# print(tf.config.experimental.get_visible_devices("GPU"))
|
|
||||||
tf.config.experimental.set_memory_growth(gpus[0], True)
|
tf.config.experimental.set_memory_growth(gpus[0], True)
|
||||||
# print("set memory growth")
|
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
print(e)
|
print(e)
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,13 @@ class PSO(object):
|
|||||||
Class implementing PSO algorithm
|
Class implementing PSO algorithm
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, model: keras.models, loss_method=keras.losses.MeanSquaredError(), optimizer='adam', n_particles=5):
|
def __init__(
|
||||||
|
self,
|
||||||
|
model: keras.models,
|
||||||
|
loss_method=keras.losses.MeanSquaredError(),
|
||||||
|
optimizer="adam",
|
||||||
|
n_particles=5,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Initialize the key variables.
|
Initialize the key variables.
|
||||||
|
|
||||||
@@ -19,39 +25,39 @@ class PSO(object):
|
|||||||
optimizer : 최적화 함수
|
optimizer : 최적화 함수
|
||||||
n_particles(int) : 파티클의 개수
|
n_particles(int) : 파티클의 개수
|
||||||
"""
|
"""
|
||||||
self.model = model # 모델
|
self.model = model # 모델
|
||||||
self.n_particles = n_particles # 파티클의 개수
|
self.n_particles = n_particles # 파티클의 개수
|
||||||
self.loss_method = loss_method # 손실 함수
|
self.loss_method = loss_method # 손실 함수
|
||||||
self.optimizer = optimizer # 최적화 함수
|
self.optimizer = optimizer # 최적화 함수
|
||||||
self.model_structure = self.model.to_json() # 모델의 구조
|
self.model_structure = self.model.to_json() # 모델의 구조
|
||||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||||
# particle_node = []
|
# particle_node = []
|
||||||
m = keras.models.model_from_json(self.model_structure)
|
m = keras.models.model_from_json(self.model_structure)
|
||||||
m.compile(loss=self.loss_method,
|
m.compile(
|
||||||
optimizer=self.optimizer, metrics=["accuracy"])
|
loss=self.loss_method, optimizer=self.optimizer, metrics=["accuracy"]
|
||||||
|
)
|
||||||
self.particles_weights[_] = m.get_weights()
|
self.particles_weights[_] = m.get_weights()
|
||||||
# print(f"shape > {self.particles_weights[_][0]}")
|
# print(f"shape > {self.particles_weights[_][0]}")
|
||||||
|
|
||||||
|
|
||||||
# self.particles_weights.append(particle_node)
|
# self.particles_weights.append(particle_node)
|
||||||
|
|
||||||
# print(f"particles_weights > {self.particles_weights}")
|
# print(f"particles_weights > {self.particles_weights}")
|
||||||
# self.particles_weights = np.random.uniform(size=(n_particles, self.particle_depth)) \
|
# self.particles_weights = np.random.uniform(size=(n_particles, self.particle_depth)) \
|
||||||
# * self.init_pos
|
# * self.init_pos
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||||
# self.velocities = [None] * self.n_particles
|
# self.velocities = [None] * self.n_particles
|
||||||
self.velocities = [
|
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 i in tqdm(range(n_particles), desc="init velocities"):
|
||||||
# print(i)
|
# print(i)
|
||||||
for index, layer in enumerate(self.init_weights):
|
for index, layer in enumerate(self.init_weights):
|
||||||
# print(f"index > {index}")
|
# print(f"index > {index}")
|
||||||
# print(f"layer > {layer.shape}")
|
# print(f"layer > {layer.shape}")
|
||||||
self.velocities[i][index] = np.random.rand(
|
self.velocities[i][index] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||||
*layer.shape) / 5 - 0.10
|
|
||||||
# if layer.ndim == 1:
|
# if layer.ndim == 1:
|
||||||
# self.velocities[i][index] = np.random.uniform(
|
# self.velocities[i][index] = np.random.uniform(
|
||||||
# size=(layer.shape[0],))
|
# size=(layer.shape[0],))
|
||||||
@@ -72,11 +78,10 @@ class PSO(object):
|
|||||||
# size=(n_particles, self.particle_depth))
|
# size=(n_particles, self.particle_depth))
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||||
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치)
|
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치)
|
||||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||||
self.p_best_score = [0 for i in range(
|
self.p_best_score = [0 for i in range(n_particles)] # 각 파티클의 최적값의 점수
|
||||||
n_particles)] # 각 파티클의 최적값의 점수
|
self.g_best_score = 0 # 전역 최적값의 점수(초기화 - 무한대)
|
||||||
self.g_best_score = 0 # 전역 최적값의 점수(초기화 - 무한대)
|
|
||||||
self.g_history = []
|
self.g_history = []
|
||||||
self.g_best_score_history = []
|
self.g_best_score_history = []
|
||||||
self.history = []
|
self.history = []
|
||||||
@@ -101,22 +106,22 @@ class PSO(object):
|
|||||||
# print(f"shape > w : {np.shape(w[i])}, v : {np.shape(v[i])}")
|
# print(f"shape > w : {np.shape(w[i])}, v : {np.shape(v[i])}")
|
||||||
new_weights[i] = tf.add(weights[i], v[i])
|
new_weights[i] = tf.add(weights[i], v[i])
|
||||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
# 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):
|
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||||
"""
|
"""
|
||||||
Update particle velocity
|
Update particle velocity
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
weights (array-like) : 파티클의 현재 가중치
|
weights (array-like) : 파티클의 현재 가중치
|
||||||
v (array-like) : 속도
|
v (array-like) : 속도
|
||||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(array-like) : 각 파티클의 새로운 속도
|
(array-like) : 각 파티클의 새로운 속도
|
||||||
"""
|
"""
|
||||||
# x = np.array(x)
|
# x = np.array(x)
|
||||||
# v = np.array(v)
|
# v = np.array(v)
|
||||||
@@ -140,9 +145,9 @@ class PSO(object):
|
|||||||
new_velocity = [None] * len(weights)
|
new_velocity = [None] * len(weights)
|
||||||
for i, layer in enumerate(weights):
|
for i, layer in enumerate(weights):
|
||||||
|
|
||||||
new_v = w*v[i]
|
new_v = w * v[i]
|
||||||
new_v = new_v + c0*r0*(p_best[i] - layer)
|
new_v = new_v + c0 * r0 * (p_best[i] - layer)
|
||||||
new_v = new_v + c1*r1*(self.g_best[i] - layer)
|
new_v = new_v + c1 * r1 * (self.g_best[i] - layer)
|
||||||
new_velocity[i] = new_v
|
new_velocity[i] = new_v
|
||||||
|
|
||||||
# m2 = tf.multiply(tf.multiply(c0, r0),
|
# m2 = tf.multiply(tf.multiply(c0, r0),
|
||||||
@@ -176,7 +181,19 @@ class PSO(object):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
def optimize(self, x_train, y_train, x_test, y_test, maxiter=10, epochs=1, batch_size=32, c0=0.5, c1=1.5, w=0.75):
|
def optimize(
|
||||||
|
self,
|
||||||
|
x_train,
|
||||||
|
y_train,
|
||||||
|
x_test,
|
||||||
|
y_test,
|
||||||
|
maxiter=10,
|
||||||
|
epochs=1,
|
||||||
|
batch_size=32,
|
||||||
|
c0=0.5,
|
||||||
|
c1=1.5,
|
||||||
|
w=0.75,
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Run the PSO optimization process utill the stoping critera is met.
|
Run the PSO optimization process utill the stoping critera is met.
|
||||||
Cas for minization. The aim is to minimize the cost function
|
Cas for minization. The aim is to minimize the cost function
|
||||||
@@ -190,13 +207,18 @@ class PSO(object):
|
|||||||
for _ in range(maxiter):
|
for _ in range(maxiter):
|
||||||
loss = 0
|
loss = 0
|
||||||
acc = 1e-10
|
acc = 1e-10
|
||||||
for i in tqdm(range(self.n_particles), desc=f"Iter {_}/{maxiter} | acc avg {round(acc/(_+1) ,4)}", ascii=True):
|
for i in tqdm(
|
||||||
|
range(self.n_particles),
|
||||||
|
desc=f"Iter {_}/{maxiter} | acc avg {round(acc/(_+1) ,4)}",
|
||||||
|
ascii=True,
|
||||||
|
):
|
||||||
weights = self.particles_weights[i] # 각 파티클 추출
|
weights = self.particles_weights[i] # 각 파티클 추출
|
||||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||||
# 2. 속도 계산
|
# 2. 속도 계산
|
||||||
self.velocities[i] = self._update_velocity(
|
self.velocities[i] = self._update_velocity(
|
||||||
weights, v, p_best, c0, c1, w)
|
weights, v, p_best, c0, c1, w
|
||||||
|
)
|
||||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||||
# 3. 위치 업데이트
|
# 3. 위치 업데이트
|
||||||
self.particles_weights[i] = self._update_weights(weights, v)
|
self.particles_weights[i] = self._update_weights(weights, v)
|
||||||
@@ -204,12 +226,19 @@ class PSO(object):
|
|||||||
# Update the besst position for particle i
|
# Update the besst position for particle i
|
||||||
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
# 내 현재 위치가 내 위치의 최소치보다 작으면 갱신
|
||||||
self.model.set_weights(self.particles_weights[i].copy())
|
self.model.set_weights(self.particles_weights[i].copy())
|
||||||
self.model.fit(x_train, y_train, epochs=epochs, batch_size=batch_size,
|
self.model.fit(
|
||||||
verbose=0, validation_data=(x_test, y_test))
|
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()
|
self.particles_weights[i] = self.model.get_weights()
|
||||||
# 4. 평가
|
# 4. 평가
|
||||||
self.model.compile(loss=self.loss_method,
|
self.model.compile(
|
||||||
optimizer='adam', metrics=['accuracy'])
|
loss=self.loss_method, optimizer="adam", metrics=["accuracy"]
|
||||||
|
)
|
||||||
score = self._get_score(x_test, y_test)
|
score = self._get_score(x_test, y_test)
|
||||||
# print(score)
|
# print(score)
|
||||||
|
|
||||||
@@ -224,8 +253,7 @@ class PSO(object):
|
|||||||
self.g_best_score = score[1]
|
self.g_best_score = score[1]
|
||||||
self.g_best = self.particles_weights[i].copy()
|
self.g_best = self.particles_weights[i].copy()
|
||||||
self.g_history.append(self.g_best)
|
self.g_history.append(self.g_best)
|
||||||
self.g_best_score_history.append(
|
self.g_best_score_history.append(self.g_best_score)
|
||||||
self.g_best_score)
|
|
||||||
|
|
||||||
self.score = score[1]
|
self.score = score[1]
|
||||||
loss = loss + score[0]
|
loss = loss + score[0]
|
||||||
@@ -240,7 +268,8 @@ class PSO(object):
|
|||||||
# self.g_history.append(self.g_best)
|
# self.g_history.append(self.g_best)
|
||||||
# print(f"{i} particle score : {score[0]}")
|
# print(f"{i} particle score : {score[0]}")
|
||||||
print(
|
print(
|
||||||
f"loss avg : {loss/self.n_particles} | acc avg : {acc/self.n_particles} | best loss : {self.g_best_score}")
|
f"loss avg : {loss/self.n_particles} | acc avg : {acc/self.n_particles} | best loss : {self.g_best_score}"
|
||||||
|
)
|
||||||
|
|
||||||
# self.history.append(self.particles_weights.copy())
|
# self.history.append(self.particles_weights.copy())
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
|
|
||||||
class PSO(object):
|
class PSO(object):
|
||||||
"""
|
"""
|
||||||
Class implementing PSO algorithm
|
Class implementing PSO algorithm
|
||||||
@@ -16,16 +17,16 @@ class PSO(object):
|
|||||||
"""
|
"""
|
||||||
self.func = func
|
self.func = func
|
||||||
self.n_particles = n_particles
|
self.n_particles = n_particles
|
||||||
self.init_pos = init_pos # 검색할 차원
|
self.init_pos = init_pos # 검색할 차원
|
||||||
self.particle_dim = len(init_pos) # 검색할 차원의 크기
|
self.particle_dim = len(init_pos) # 검색할 차원의 크기
|
||||||
self.particles_pos = np.random.uniform(size=(n_particles, self.particle_dim)) \
|
self.particles_pos = (
|
||||||
* self.init_pos
|
np.random.uniform(size=(n_particles, self.particle_dim)) * self.init_pos
|
||||||
|
)
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||||
self.velocities = np.random.uniform(
|
self.velocities = np.random.uniform(size=(n_particles, self.particle_dim))
|
||||||
size=(n_particles, self.particle_dim))
|
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||||
self.g_best = init_pos # 최대 사이즈로 전역 최적갑 저장 - global best
|
self.g_best = init_pos # 최대 사이즈로 전역 최적갑 저장 - global best
|
||||||
self.p_best = self.particles_pos # 모든 파티클의 위치 - particles best
|
self.p_best = self.particles_pos # 모든 파티클의 위치 - particles best
|
||||||
self.g_history = []
|
self.g_history = []
|
||||||
self.history = []
|
self.history = []
|
||||||
|
|
||||||
@@ -42,24 +43,24 @@ class PSO(object):
|
|||||||
"""
|
"""
|
||||||
x = np.array(x) # 각 파티클의 위치
|
x = np.array(x) # 각 파티클의 위치
|
||||||
v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||||
new_x = x + v # 각 파티클을 랜덤한 속도만큼 진행
|
new_x = x + v # 각 파티클을 랜덤한 속도만큼 진행
|
||||||
return new_x # 진행한 파티클들의 위치를 반환
|
return new_x # 진행한 파티클들의 위치를 반환
|
||||||
|
|
||||||
def update_velocity(self, x, v, p_best, g_best, c0=0.5, c1=1.5, w=0.75):
|
def update_velocity(self, x, v, p_best, g_best, c0=0.5, c1=1.5, w=0.75):
|
||||||
"""
|
"""
|
||||||
Update particle velocity
|
Update particle velocity
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
x(array-like): particle current position
|
x(array-like): particle current position
|
||||||
v (array-like): particle current velocity
|
v (array-like): particle current velocity
|
||||||
p_best(array-like): the best position found so far for a particle
|
p_best(array-like): the best position found so far for a particle
|
||||||
g_best(array-like): the best position regarding all the particles found so far
|
g_best(array-like): the best position regarding all the particles found so far
|
||||||
c0 (float): the congnitive scaling constant, 인지 스케일링 상수
|
c0 (float): the congnitive scaling constant, 인지 스케일링 상수
|
||||||
c1 (float): the social scaling constant
|
c1 (float): the social scaling constant
|
||||||
w (float): the inertia weight, 관성 중량
|
w (float): the inertia weight, 관성 중량
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The updated velocity (array-like).
|
The updated velocity (array-like).
|
||||||
"""
|
"""
|
||||||
x = np.array(x)
|
x = np.array(x)
|
||||||
v = np.array(v)
|
v = np.array(v)
|
||||||
@@ -73,7 +74,7 @@ class PSO(object):
|
|||||||
# 가중치(상수)*속도 + \
|
# 가중치(상수)*속도 + \
|
||||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||||
new_v = w*v + c0*r*(p_best - x) + c1*r*(g_best - x)
|
new_v = w * v + c0 * r * (p_best - x) + c1 * r * (g_best - x)
|
||||||
return new_v
|
return new_v
|
||||||
|
|
||||||
def optimize(self, maxiter=200):
|
def optimize(self, maxiter=200):
|
||||||
@@ -90,10 +91,9 @@ class PSO(object):
|
|||||||
for _ in range(maxiter):
|
for _ in range(maxiter):
|
||||||
for i in range(self.n_particles):
|
for i in range(self.n_particles):
|
||||||
x = self.particles_pos[i] # 각 파티클 추출
|
x = self.particles_pos[i] # 각 파티클 추출
|
||||||
v = self.velocities[i] # 랜덤 생성한 속도 추출
|
v = self.velocities[i] # 랜덤 생성한 속도 추출
|
||||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||||
self.velocities[i] = self.update_velocity(
|
self.velocities[i] = self.update_velocity(x, v, p_best, self.g_best)
|
||||||
x, v, p_best, self.g_best)
|
|
||||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||||
self.particles_pos[i] = self.update_position(x, v)
|
self.particles_pos[i] = self.update_position(x, v)
|
||||||
# 현재 위치 = 최초 위치 현재 속도
|
# 현재 위치 = 최초 위치 현재 속도
|
||||||
|
|||||||
@@ -12,13 +12,17 @@ import gc
|
|||||||
import cupy as cp
|
import cupy as cp
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PSO(object):
|
class PSO(object):
|
||||||
"""
|
"""
|
||||||
Class implementing PSO algorithm
|
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.
|
Initialize the key variables.
|
||||||
|
|
||||||
@@ -27,37 +31,38 @@ class PSO(object):
|
|||||||
loss_method : 손실 함수
|
loss_method : 손실 함수
|
||||||
n_particles(int) : 파티클의 개수
|
n_particles(int) : 파티클의 개수
|
||||||
"""
|
"""
|
||||||
self.model = model # 모델
|
self.model = model # 모델
|
||||||
self.n_particles = n_particles # 파티클의 개수
|
self.n_particles = n_particles # 파티클의 개수
|
||||||
self.loss_method = loss_method # 손실 함수
|
self.loss_method = loss_method # 손실 함수
|
||||||
model_structure = self.model.to_json() # 모델의 구조 정보
|
model_structure = self.model.to_json() # 모델의 구조 정보
|
||||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||||
m = keras.models.model_from_json(model_structure)
|
m = keras.models.model_from_json(model_structure)
|
||||||
m.compile(loss=self.loss_method,
|
m.compile(loss=self.loss_method, optimizer="adam", metrics=["accuracy"])
|
||||||
optimizer="adam", metrics=["accuracy"])
|
|
||||||
self.particles_weights[_] = m.get_weights()
|
self.particles_weights[_] = m.get_weights()
|
||||||
|
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||||
self.velocities = [
|
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 i in tqdm(range(n_particles), desc="init velocities"):
|
||||||
|
|
||||||
self.init_weights = self.model.get_weights()
|
self.init_weights = self.model.get_weights()
|
||||||
w_,s_,l_ = self._encode(self.init_weights)
|
w_, s_, l_ = self._encode(self.init_weights)
|
||||||
w_ = np.random.rand(len(w_)) / 5 - 0.10
|
w_ = np.random.rand(len(w_)) / 5 - 0.10
|
||||||
self.velocities[i] = self._decode(w_,s_,l_)
|
self.velocities[i] = self._decode(w_, s_, l_)
|
||||||
# for index, layer in enumerate(self.init_weights):
|
# for index, layer in enumerate(self.init_weights):
|
||||||
# self.velocities[i][index] = np.random.rand(
|
# self.velocities[i][index] = np.random.rand(
|
||||||
# *layer.shape) / 5 - 0.10
|
# *layer.shape) / 5 - 0.10
|
||||||
|
|
||||||
|
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||||
self.g_best=self.model.get_weights() # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
self.g_best = (
|
||||||
|
self.model.get_weights()
|
||||||
|
) # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||||
|
|
||||||
# 각 파티클의 최적값의 점수
|
# 각 파티클의 최적값의 점수
|
||||||
self.p_best_score = [0 for i in range(n_particles)]
|
self.p_best_score = [0 for i in range(n_particles)]
|
||||||
@@ -77,7 +82,7 @@ class PSO(object):
|
|||||||
del self.p_best_score
|
del self.p_best_score
|
||||||
del self.g_best_score
|
del self.g_best_score
|
||||||
|
|
||||||
def _encode(self,weights: list):
|
def _encode(self, weights: list):
|
||||||
# w_gpu = cp.array([])
|
# w_gpu = cp.array([])
|
||||||
w_gpu = np.array([])
|
w_gpu = np.array([])
|
||||||
lenght = []
|
lenght = []
|
||||||
@@ -91,7 +96,7 @@ class PSO(object):
|
|||||||
|
|
||||||
return w_gpu, shape, lenght
|
return w_gpu, shape, lenght
|
||||||
|
|
||||||
def _decode(self,weight, shape, lenght):
|
def _decode(self, weight, shape, lenght):
|
||||||
weights = []
|
weights = []
|
||||||
start = 0
|
start = 0
|
||||||
for i in range(len(shape)):
|
for i in range(len(shape)):
|
||||||
@@ -121,30 +126,30 @@ class PSO(object):
|
|||||||
# v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
# v = np.array(v) # 각 파티클의 속도(방향과 속력을 가짐)
|
||||||
# new_weights = [0 for i in range(len(weights))]
|
# new_weights = [0 for i in range(len(weights))]
|
||||||
# print(f"weights : {weights}")
|
# print(f"weights : {weights}")
|
||||||
encode_w, w_sh, w_len = self._encode(weights = weights)
|
encode_w, w_sh, w_len = self._encode(weights=weights)
|
||||||
encode_v, _, _ = self._encode(weights = v)
|
encode_v, _, _ = self._encode(weights=v)
|
||||||
new_w = encode_w + encode_v
|
new_w = encode_w + encode_v
|
||||||
new_weights = self._decode(new_w, w_sh, w_len)
|
new_weights = self._decode(new_w, w_sh, w_len)
|
||||||
|
|
||||||
# for i in range(len(weights)):
|
# for i in range(len(weights)):
|
||||||
# new_weights[i] = tf.add(weights[i], v[i])
|
# new_weights[i] = tf.add(weights[i], v[i])
|
||||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
# 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):
|
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||||
"""
|
"""
|
||||||
Update particle velocity
|
Update particle velocity
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
weights (array-like) : 파티클의 현재 가중치
|
weights (array-like) : 파티클의 현재 가중치
|
||||||
v (array-like) : 속도
|
v (array-like) : 속도
|
||||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(array-like) : 각 파티클의 새로운 속도
|
(array-like) : 각 파티클의 새로운 속도
|
||||||
"""
|
"""
|
||||||
# x = np.array(x)
|
# x = np.array(x)
|
||||||
# v = np.array(v)
|
# v = np.array(v)
|
||||||
@@ -160,20 +165,24 @@ class PSO(object):
|
|||||||
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
# 스케일링 상수*랜덤 가중치*(나의 최적값 - 처음 위치) + \
|
||||||
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
# 전역 스케일링 상수*랜덤 가중치*(전체 최적값 - 처음 위치)
|
||||||
|
|
||||||
encode_w, w_sh, w_len = self._encode(weights = weights)
|
encode_w, w_sh, w_len = self._encode(weights=weights)
|
||||||
encode_v, _, _ = self._encode(weights = v)
|
encode_v, _, _ = self._encode(weights=v)
|
||||||
encode_p, _, _ = self._encode(weights = p_best)
|
encode_p, _, _ = self._encode(weights=p_best)
|
||||||
encode_g, _, _ = self._encode(weights = self.g_best)
|
encode_g, _, _ = self._encode(weights=self.g_best)
|
||||||
|
|
||||||
new_v = encode_w * encode_v + c0*r0*(encode_p - encode_w) + c1*r1*(encode_g - encode_w)
|
new_v = (
|
||||||
|
encode_w * encode_v
|
||||||
|
+ c0 * r0 * (encode_p - encode_w)
|
||||||
|
+ c1 * r1 * (encode_g - encode_w)
|
||||||
|
)
|
||||||
new_velocity = self._decode(new_v, w_sh, w_len)
|
new_velocity = self._decode(new_v, w_sh, w_len)
|
||||||
# new_velocity = [None] * len(weights)
|
# new_velocity = [None] * len(weights)
|
||||||
# for i, layer in enumerate(weights):
|
# for i, layer in enumerate(weights):
|
||||||
|
|
||||||
# new_v = w*v[i]
|
# new_v = w*v[i]
|
||||||
# new_v = new_v + c0*r0*(p_best[i] - layer)
|
# new_v = new_v + c0*r0*(p_best[i] - layer)
|
||||||
# new_v = new_v + c1*r1*(self.g_best[i] - layer)
|
# new_v = new_v + c1*r1*(self.g_best[i] - layer)
|
||||||
# new_velocity[i] = new_v
|
# new_velocity[i] = new_v
|
||||||
|
|
||||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
||||||
return new_velocity
|
return new_velocity
|
||||||
@@ -192,7 +201,17 @@ class PSO(object):
|
|||||||
|
|
||||||
return score
|
return score
|
||||||
|
|
||||||
def optimize(self, x_, y_, maxiter=10, c0=0.5, c1=1.5, w=0.75, save=False, save_path="./result/history"):
|
def optimize(
|
||||||
|
self,
|
||||||
|
x_,
|
||||||
|
y_,
|
||||||
|
maxiter=10,
|
||||||
|
c0=0.5,
|
||||||
|
c1=1.5,
|
||||||
|
w=0.75,
|
||||||
|
save=False,
|
||||||
|
save_path="./result/history",
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Run the PSO optimization process utill the stoping critera is met.
|
Run the PSO optimization process utill the stoping critera is met.
|
||||||
Cas for minization. The aim is to minimize the cost function
|
Cas for minization. The aim is to minimize the cost function
|
||||||
@@ -205,17 +224,20 @@ class PSO(object):
|
|||||||
"""
|
"""
|
||||||
if save:
|
if save:
|
||||||
os.makedirs(save_path, exist_ok=True)
|
os.makedirs(save_path, exist_ok=True)
|
||||||
day = datetime.datetime.now().strftime('%m-%d-%H-%M')
|
day = datetime.datetime.now().strftime("%m-%d-%H-%M")
|
||||||
|
|
||||||
for _ in range(maxiter):
|
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] # 각 파티클 추출
|
weights = self.particles_weights[i] # 각 파티클 추출
|
||||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||||
# 2. 속도 계산
|
# 2. 속도 계산
|
||||||
self.velocities[i] = self._update_velocity(
|
self.velocities[i] = self._update_velocity(
|
||||||
weights, v, p_best, c0, c1, w)
|
weights, v, p_best, c0, c1, w
|
||||||
|
)
|
||||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||||
# 3. 위치 업데이트
|
# 3. 위치 업데이트
|
||||||
self.particles_weights[i] = self._update_weights(weights, v)
|
self.particles_weights[i] = self._update_weights(weights, v)
|
||||||
@@ -224,8 +246,9 @@ class PSO(object):
|
|||||||
self.model.set_weights(self.particles_weights[i])
|
self.model.set_weights(self.particles_weights[i])
|
||||||
# self.particles_weights[i] = self.model.get_weights()
|
# self.particles_weights[i] = self.model.get_weights()
|
||||||
# 4. 평가
|
# 4. 평가
|
||||||
self.model.compile(loss=self.loss_method,
|
self.model.compile(
|
||||||
optimizer='sgd', metrics=['accuracy'])
|
loss=self.loss_method, optimizer="sgd", metrics=["accuracy"]
|
||||||
|
)
|
||||||
score = self._get_score(x_, y_)
|
score = self._get_score(x_, y_)
|
||||||
|
|
||||||
if score[1] > self.p_best_score[i]:
|
if score[1] > self.p_best_score[i]:
|
||||||
@@ -236,16 +259,23 @@ class PSO(object):
|
|||||||
self.g_best = self.particles_weights[i]
|
self.g_best = self.particles_weights[i]
|
||||||
|
|
||||||
if save:
|
if save:
|
||||||
with open(f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",'a')as f:
|
with open(
|
||||||
|
f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",
|
||||||
|
"a",
|
||||||
|
) as f:
|
||||||
f.write(f"{score[0]}, {score[1]}")
|
f.write(f"{score[0]}, {score[1]}")
|
||||||
if i != self.n_particles - 1:
|
if i != self.n_particles - 1:
|
||||||
f.write(",")
|
f.write(",")
|
||||||
|
|
||||||
if save:
|
if save:
|
||||||
with open(f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",'a')as f:
|
with open(
|
||||||
|
f"{save_path}/{day}_{self.n_particles}_{maxiter}_{c0}_{c1}_{w}.csv",
|
||||||
|
"a",
|
||||||
|
) as f:
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
print(
|
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}"
|
||||||
|
)
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
|
||||||
# 전체 최소 위치, 전체 최소 벡터
|
# 전체 최소 위치, 전체 최소 벡터
|
||||||
|
|||||||
@@ -12,7 +12,12 @@ class PSO(object):
|
|||||||
Class implementing PSO algorithm
|
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.
|
Initialize the key variables.
|
||||||
|
|
||||||
@@ -21,40 +26,41 @@ class PSO(object):
|
|||||||
loss_method : 손실 함수
|
loss_method : 손실 함수
|
||||||
n_particles(int) : 파티클의 개수
|
n_particles(int) : 파티클의 개수
|
||||||
"""
|
"""
|
||||||
self.model = model # 모델
|
self.model = model # 모델
|
||||||
self.n_particles = n_particles # 파티클의 개수
|
self.n_particles = n_particles # 파티클의 개수
|
||||||
self.loss_method = loss_method # 손실 함수
|
self.loss_method = loss_method # 손실 함수
|
||||||
self.model_structure = self.model.to_json() # 모델의 구조 정보
|
self.model_structure = self.model.to_json() # 모델의 구조 정보
|
||||||
self.init_weights = self.model.get_weights() # 검색할 차원
|
self.init_weights = self.model.get_weights() # 검색할 차원
|
||||||
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
self.particle_depth = len(self.model.get_weights()) # 검색할 차원의 깊이
|
||||||
self.particles_weights = [None] * n_particles # 파티클의 위치
|
self.particles_weights = [None] * n_particles # 파티클의 위치
|
||||||
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
for _ in tqdm(range(self.n_particles), desc="init particles position"):
|
||||||
m = keras.models.model_from_json(self.model_structure)
|
m = keras.models.model_from_json(self.model_structure)
|
||||||
m.compile(loss=self.loss_method,
|
m.compile(loss=self.loss_method, optimizer="adam", metrics=["accuracy"])
|
||||||
optimizer="adam", metrics=["accuracy"])
|
|
||||||
self.particles_weights[_] = m.get_weights()
|
self.particles_weights[_] = m.get_weights()
|
||||||
|
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 균등한 위치를 생성
|
||||||
self.velocities = [
|
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 i in tqdm(range(n_particles), desc="init velocities"):
|
||||||
for index, layer in enumerate(self.init_weights):
|
for index, layer in enumerate(self.init_weights):
|
||||||
self.velocities[i][index] = np.random.rand(
|
self.velocities[i][index] = np.random.rand(*layer.shape) / 5 - 0.10
|
||||||
*layer.shape) / 5 - 0.10
|
|
||||||
|
|
||||||
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
# 입력받은 파티클의 개수 * 검색할 차원의 크기 만큼의 속도를 무작위로 초기화
|
||||||
# 최대 사이즈로 전역 최적갑 저장 - global best
|
# 최대 사이즈로 전역 최적갑 저장 - global best
|
||||||
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
self.p_best = self.particles_weights # 각 파티클의 최적값(최적의 가중치)
|
||||||
self.g_best = self.model.get_weights() # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
self.g_best = (
|
||||||
|
self.model.get_weights()
|
||||||
|
) # 전역 최적값(최적의 가중치) | 초기값은 모델의 가중치
|
||||||
|
|
||||||
# 각 파티클의 최적값의 점수
|
# 각 파티클의 최적값의 점수
|
||||||
self.p_best_score = [0 for i in range(n_particles)]
|
self.p_best_score = [0 for i in range(n_particles)]
|
||||||
|
|
||||||
# 전역 최적값의 점수(초기화 - 0)
|
# 전역 최적값의 점수(초기화 - 0)
|
||||||
self.g_best_score = 0
|
self.g_best_score = 0
|
||||||
self.loss_history = [[] for i in range(n_particles)] # 각 파티클의 손실값 변화
|
self.loss_history = [[] for i in range(n_particles)] # 각 파티클의 손실값 변화
|
||||||
self.acc_history = [[] for i in range(n_particles)] # 각 파티클의 정확도 변화
|
self.acc_history = [[] for i in range(n_particles)] # 각 파티클의 정확도 변화
|
||||||
self.g_best_score_history = [] # 전역 최적값의 점수 변화
|
self.g_best_score_history = [] # 전역 최적값의 점수 변화
|
||||||
|
|
||||||
def _update_weights(self, weights, v):
|
def _update_weights(self, weights, v):
|
||||||
"""
|
"""
|
||||||
@@ -73,22 +79,22 @@ class PSO(object):
|
|||||||
for i in range(len(weights)):
|
for i in range(len(weights)):
|
||||||
new_weights[i] = tf.add(weights[i], v[i])
|
new_weights[i] = tf.add(weights[i], v[i])
|
||||||
# new_w = tf.add(w, v) # 각 파티클을 랜덤한 속도만큼 진행
|
# 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):
|
def _update_velocity(self, weights, v, p_best, c0=0.5, c1=1.5, w=0.75):
|
||||||
"""
|
"""
|
||||||
Update particle velocity
|
Update particle velocity
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
weights (array-like) : 파티클의 현재 가중치
|
weights (array-like) : 파티클의 현재 가중치
|
||||||
v (array-like) : 속도
|
v (array-like) : 속도
|
||||||
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
p_best(array-like) : 각 파티클의 최적의 위치 (최적의 가중치)
|
||||||
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
c0 (float) : 인지 스케일링 상수 (가중치의 중요도 - 지역) - 지역 관성
|
||||||
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
c1 (float) : 사회 스케일링 상수 (가중치의 중요도 - 전역) - 전역 관성
|
||||||
w (float) : 관성 상수 (현재 속도의 중요도)
|
w (float) : 관성 상수 (현재 속도의 중요도)
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
(array-like) : 각 파티클의 새로운 속도
|
(array-like) : 각 파티클의 새로운 속도
|
||||||
"""
|
"""
|
||||||
# x = np.array(x)
|
# x = np.array(x)
|
||||||
# v = np.array(v)
|
# v = np.array(v)
|
||||||
@@ -106,9 +112,9 @@ class PSO(object):
|
|||||||
new_velocity = [None] * len(weights)
|
new_velocity = [None] * len(weights)
|
||||||
for i, layer in enumerate(weights):
|
for i, layer in enumerate(weights):
|
||||||
|
|
||||||
new_v = w*v[i]
|
new_v = w * v[i]
|
||||||
new_v = new_v + c0*r0*(p_best[i] - layer)
|
new_v = new_v + c0 * r0 * (p_best[i] - layer)
|
||||||
new_v = new_v + c1*r1*(self.g_best[i] - layer)
|
new_v = new_v + c1 * r1 * (self.g_best[i] - layer)
|
||||||
new_velocity[i] = new_v
|
new_velocity[i] = new_v
|
||||||
|
|
||||||
# new_v = w*v + c0*r0*(p_best - weights) + c1*r1*(g_best - weights)
|
# 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 _ 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] # 각 파티클 추출
|
weights = self.particles_weights[i] # 각 파티클 추출
|
||||||
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
v = self.velocities[i] # 각 파티클의 다음 속도 추출
|
||||||
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
p_best = self.p_best[i] # 결과치 저장할 변수 지정
|
||||||
# 2. 속도 계산
|
# 2. 속도 계산
|
||||||
self.velocities[i] = self._update_velocity(
|
self.velocities[i] = self._update_velocity(
|
||||||
weights, v, p_best, c0, c1, w)
|
weights, v, p_best, c0, c1, w
|
||||||
|
)
|
||||||
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
# 다음에 움직일 속도 = 최초 위치, 현재 속도, 현재 위치, 최종 위치
|
||||||
# 3. 위치 업데이트
|
# 3. 위치 업데이트
|
||||||
self.particles_weights[i] = self._update_weights(weights, v)
|
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.model.set_weights(self.particles_weights[i].copy())
|
||||||
# self.particles_weights[i] = self.model.get_weights()
|
# self.particles_weights[i] = self.model.get_weights()
|
||||||
# 4. 평가
|
# 4. 평가
|
||||||
self.model.compile(loss=self.loss_method,
|
self.model.compile(
|
||||||
optimizer='adam', metrics=['accuracy'])
|
loss=self.loss_method, optimizer="adam", metrics=["accuracy"]
|
||||||
|
)
|
||||||
score = self._get_score(x_, y_)
|
score = self._get_score(x_, y_)
|
||||||
|
|
||||||
if score[1] > self.p_best_score[i]:
|
if score[1] > self.p_best_score[i]:
|
||||||
@@ -166,14 +176,14 @@ class PSO(object):
|
|||||||
if score[1] > self.g_best_score:
|
if score[1] > self.g_best_score:
|
||||||
self.g_best_score = score[1]
|
self.g_best_score = score[1]
|
||||||
self.g_best = self.particles_weights[i].copy()
|
self.g_best = self.particles_weights[i].copy()
|
||||||
self.g_best_score_history.append(
|
self.g_best_score_history.append(self.g_best_score)
|
||||||
self.g_best_score)
|
|
||||||
|
|
||||||
self.loss_history[i].append(score[0])
|
self.loss_history[i].append(score[0])
|
||||||
self.acc_history[i].append(score[1])
|
self.acc_history[i].append(score[1])
|
||||||
|
|
||||||
print(
|
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_)
|
return self.g_best, self._get_score(x_, y_)
|
||||||
@@ -193,6 +203,7 @@ class PSO(object):
|
|||||||
|
|
||||||
def best_score(self):
|
def best_score(self):
|
||||||
return self.g_best_score
|
return self.g_best_score
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Returns:
|
Returns:
|
||||||
global best score 의 갱신된 값의 변화를 반환
|
global best score 의 갱신된 값의 변화를 반환
|
||||||
|
|||||||
@@ -83,30 +83,30 @@ class Optimizer:
|
|||||||
try:
|
try:
|
||||||
if model is None:
|
if model is None:
|
||||||
raise ValueError("model is None")
|
raise ValueError("model is None")
|
||||||
if model is not None and not isinstance(model, keras.models.Model):
|
elif model is not None and not isinstance(model, keras.models.Model):
|
||||||
raise ValueError("model is not keras.models.Model")
|
raise ValueError("model is not keras.models.Model")
|
||||||
|
|
||||||
if loss is None:
|
elif loss is None:
|
||||||
raise ValueError("loss is None")
|
raise ValueError("loss is None")
|
||||||
|
|
||||||
if n_particles is None:
|
elif n_particles is None:
|
||||||
raise ValueError("n_particles is None")
|
raise ValueError("n_particles is None")
|
||||||
if n_particles < 1:
|
elif n_particles < 1:
|
||||||
raise ValueError("n_particles < 1")
|
raise ValueError("n_particles < 1")
|
||||||
|
|
||||||
if c0 < 0 or c1 < 0:
|
elif c0 < 0 or c1 < 0:
|
||||||
raise ValueError("c0 or c1 < 0")
|
raise ValueError("c0 or c1 < 0")
|
||||||
|
|
||||||
if np_seed is not None:
|
elif np_seed is not None:
|
||||||
np.random.seed(np_seed)
|
np.random.seed(np_seed)
|
||||||
if tf_seed is not None:
|
elif tf_seed is not None:
|
||||||
tf.random.set_seed(tf_seed)
|
tf.random.set_seed(tf_seed)
|
||||||
|
|
||||||
self.random_state = np.random.get_state()
|
elif random_state is not None:
|
||||||
|
|
||||||
if random_state is not None:
|
|
||||||
np.random.set_state(random_state)
|
np.random.set_state(random_state)
|
||||||
|
|
||||||
|
self.random_state = np.random.get_state()
|
||||||
|
|
||||||
model.compile(loss=loss, optimizer="adam", metrics=["accuracy", "mse"])
|
model.compile(loss=loss, optimizer="adam", metrics=["accuracy", "mse"])
|
||||||
self.model = model # 모델 구조
|
self.model = model # 모델 구조
|
||||||
self.loss = loss # 손실함수
|
self.loss = loss # 손실함수
|
||||||
@@ -116,8 +116,12 @@ class Optimizer:
|
|||||||
self.c1 = c1 # global rate - 전역 최적값 관성 수치
|
self.c1 = c1 # global rate - 전역 최적값 관성 수치
|
||||||
self.w_min = w_min # 최소 관성 수치
|
self.w_min = w_min # 최소 관성 수치
|
||||||
self.w_max = w_max # 최대 관성 수치
|
self.w_max = w_max # 최대 관성 수치
|
||||||
self.negative_swarm = negative_swarm # 최적해와 반대로 이동할 파티클 비율 - 0 ~ 1 사이의 값
|
self.negative_swarm = (
|
||||||
self.mutation_swarm = mutation_swarm # 관성을 추가로 사용할 파티클 비율 - 0 ~ 1 사이의 값
|
negative_swarm # 최적해와 반대로 이동할 파티클 비율 - 0 ~ 1 사이의 값
|
||||||
|
)
|
||||||
|
self.mutation_swarm = (
|
||||||
|
mutation_swarm # 관성을 추가로 사용할 파티클 비율 - 0 ~ 1 사이의 값
|
||||||
|
)
|
||||||
self.avg_score = 0 # 평균 점수
|
self.avg_score = 0 # 평균 점수
|
||||||
# self.sigma = 1.0
|
# self.sigma = 1.0
|
||||||
|
|
||||||
@@ -136,9 +140,9 @@ class Optimizer:
|
|||||||
self.particles[i] = Particle(
|
self.particles[i] = Particle(
|
||||||
model,
|
model,
|
||||||
self.loss,
|
self.loss,
|
||||||
negative=True
|
negative=(
|
||||||
if i < self.negative_swarm * self.n_particles
|
True if i < self.negative_swarm * self.n_particles else False
|
||||||
else False,
|
),
|
||||||
mutation=self.mutation_swarm,
|
mutation=self.mutation_swarm,
|
||||||
converge_reset=convergence_reset,
|
converge_reset=convergence_reset,
|
||||||
converge_reset_patience=convergence_reset_patience,
|
converge_reset_patience=convergence_reset_patience,
|
||||||
|
|||||||
Reference in New Issue
Block a user