mirror of
https://github.com/jung-geun/PSO.git
synced 2025-12-19 20:44:39 +09:00
23-07-21
pypi 0.1.4 업데이트 keras 의 메모리 누수를 어느정도 해결했으나 아직 완벽히 해결이 되지 않음 입력 데이터를 tensor 형태로 변환해주어 넣는 방식으로 전환
This commit is contained in:
2
.github/workflows/pypi.yml
vendored
2
.github/workflows/pypi.yml
vendored
@@ -1,4 +1,4 @@
|
|||||||
name: Python Package Index publish
|
name: PyPI package
|
||||||
|
|
||||||
on: [push]
|
on: [push]
|
||||||
|
|
||||||
|
|||||||
75
README.md
75
README.md
@@ -1,3 +1,5 @@
|
|||||||
|
[](https://github.com/jung-geun/PSO/actions/workflows/pypi.yml)
|
||||||
|
|
||||||
# PSO 알고리즘 구현 및 새로운 시도
|
# PSO 알고리즘 구현 및 새로운 시도
|
||||||
|
|
||||||
pso 알고리즘을 사용하여 새로운 학습 방법을 찾는중 입니다
|
pso 알고리즘을 사용하여 새로운 학습 방법을 찾는중 입니다
|
||||||
@@ -21,16 +23,24 @@ pso 알고리즘을 사용하여 새로운 학습 방법을 찾는중 입니다
|
|||||||
> \end{cases}
|
> \end{cases}
|
||||||
> $$
|
> $$
|
||||||
|
|
||||||
### 위치를 현재 전역해로 변경(덮어쓰기)하면 안되는 이유
|
|
||||||
|
|
||||||
위치를 가장 최적값으로 변경하면 지역 최적값에서 벗어나지 못합니다. 따라서 전역 최적값을 찾을 수 없습니다.
|
|
||||||
|
|
||||||
# 초기 세팅
|
# 초기 세팅
|
||||||
|
|
||||||
|
자동으로 conda 환경을 설정하기 위해서는 다음 명령어를 사용합니다
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
conda env create -f ./conda_env/environment.yaml
|
conda env create -f ./conda_env/environment.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
|
현재 python 3.9 버전, tensorflow 2.11 버전에서 테스트 되었습니다
|
||||||
|
</br>
|
||||||
|
직접 설치하여 사용할 경우 pso2keras 패키지를 pypi 에서 다운로드 받아서 사용하시기 바랍니다
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install pso2keras==0.1.4
|
||||||
|
```
|
||||||
|
|
||||||
|
위의 패키지를 사용하기 위해서는 tensorflow 와 tensorboard 가 설치되어 있어야 합니다
|
||||||
|
|
||||||
# 현재 진행 상황
|
# 현재 진행 상황
|
||||||
|
|
||||||
## 1. PSO 알고리즘 구현
|
## 1. PSO 알고리즘 구현
|
||||||
@@ -55,6 +65,7 @@ conda env create -f ./conda_env/environment.yaml
|
|||||||
|-- mnist_tf.py # tensorflow 를 이용한 mnist 문제 풀이
|
|-- mnist_tf.py # tensorflow 를 이용한 mnist 문제 풀이
|
||||||
|-- plt.ipynb # pyplot 으로 학습 결과를 그래프로 표현
|
|-- plt.ipynb # pyplot 으로 학습 결과를 그래프로 표현
|
||||||
|-- README.md # 현재 파일
|
|-- README.md # 현재 파일
|
||||||
|
|-- requirements.txt # pypi 에서 다운로드 받을 패키지 목록
|
||||||
```
|
```
|
||||||
|
|
||||||
pso 라이브러리는 tensorflow 모델을 학습하기 위해 기본 ./metacode/pso_meta.py 코드에서 수정하였습니다 [2]
|
pso 라이브러리는 tensorflow 모델을 학습하기 위해 기본 ./metacode/pso_meta.py 코드에서 수정하였습니다 [2]
|
||||||
@@ -63,20 +74,12 @@ pso 라이브러리는 tensorflow 모델을 학습하기 위해 기본 ./metacod
|
|||||||
|
|
||||||
pso 알고리즘을 이용하여 오차역전파 함수를 최적화 하는 방법을 찾는 중입니다
|
pso 알고리즘을 이용하여 오차역전파 함수를 최적화 하는 방법을 찾는 중입니다
|
||||||
|
|
||||||
### 브레인스토밍
|
### 알고리즘 작동 방식
|
||||||
|
|
||||||
> 1. 오차역전파 함수를 1~5회 실행하여 오차를 구합니다
|
> 1. 파티클의 위치와 속도를 초기화 한다.
|
||||||
> 2. 오차가 가장 적은 다른 노드(particle) 가중치로 유도합니다.
|
> 2. 각 파티클의 점수를 계산한다.
|
||||||
>
|
> 3. 각 파티클의 지역 최적해와 전역 최적해를 구한다.
|
||||||
> > 2-1. 만약 오차가 가장 작은 다른 노드가 현재 노드보다 오차가 크다면, 현재 노드의 가중치를 유지합니다. - 현재의 가중치를 최적값으로 업로드합니다
|
> 4. 각 파티클의 속도를 업데이트 한다.
|
||||||
> >
|
|
||||||
> > 2-2. 지역 최적값을 찾았다면, 전역 최적값을 찾을 때까지 1~2 과정을 반복합니다
|
|
||||||
>
|
|
||||||
> 3. 전역 최적값이 특정 임계치에서 변화율이 적다면 학습을 종료합니다 - 현재 결과가 정확도가 높지 않아서 이 기능은 추후에 추가할 예정입니다
|
|
||||||
|
|
||||||
</br>
|
|
||||||
위의 아이디어는 원래의 목표와 다른 방향으로 가고 있습니다. 따라서 다른 방법을 모색해야할 것 같습니다
|
|
||||||
</br>
|
|
||||||
|
|
||||||
## 3. PSO 알고리즘을 이용하여 풀이한 문제들의 정확도
|
## 3. PSO 알고리즘을 이용하여 풀이한 문제들의 정확도
|
||||||
|
|
||||||
@@ -160,30 +163,33 @@ loss = 'mean_squared_error'
|
|||||||
pso_mnist = Optimizer(
|
pso_mnist = Optimizer(
|
||||||
model,
|
model,
|
||||||
loss=loss,
|
loss=loss,
|
||||||
n_particles=75,
|
n_particles=100,
|
||||||
c0=0.25,
|
c0=0.3,
|
||||||
c1=0.4,
|
c1=0.5,
|
||||||
w_min=0.2,
|
w_min=0.4,
|
||||||
w_max=0.6,
|
w_max=0.7,
|
||||||
negative_swarm=0.1,
|
negative_swarm=0.1,
|
||||||
mutation_swarm=0.2,
|
mutation_swarm=0.2,
|
||||||
|
particle_min=-5,
|
||||||
|
particle_max=5,
|
||||||
)
|
)
|
||||||
|
|
||||||
best_score = pso_mnist.fit(
|
best_score = pso_mnist.fit(
|
||||||
x_test,
|
x_train,
|
||||||
y_test,
|
y_train,
|
||||||
epochs=200,
|
epochs=200,
|
||||||
save=True,
|
save_info=True,
|
||||||
|
log=2,
|
||||||
|
log_name="mnist",
|
||||||
save_path="./result/mnist",
|
save_path="./result/mnist",
|
||||||
renewal="acc",
|
renewal="acc",
|
||||||
empirical_balance=False,
|
check_point=25,
|
||||||
Dispersion=False,
|
|
||||||
check_point=25
|
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
위의 파라미터 기준 현재 정확도 43.38%를 보이고 있습니다
|
위의 파라미터 기준 현재 정확도 51.84%를 보이고 있습니다
|
||||||

|

|
||||||
|

|
||||||
|
|
||||||
### Trouble Shooting
|
### Trouble Shooting
|
||||||
|
|
||||||
@@ -194,13 +200,20 @@ best_score = pso_mnist.fit(
|
|||||||
|
|
||||||
> 2. 지역최적값에 계속 머무르는 조기 수렴 현상이 나타난다. - 30% 정도의 정확도를 가진다
|
> 2. 지역최적값에 계속 머무르는 조기 수렴 현상이 나타난다. - 30% 정도의 정확도를 가진다
|
||||||
|
|
||||||
-> 지역최적값에 머무르는 것을 방지하기 위해 negative_swarm, mutation_swarm 파라미터를 추가하였습니다 - 현재 43% 정도의 정확도를 보이고 있습니다
|
-> 지역최적값에 머무르는 것을 방지하기 위해 negative_swarm, mutation_swarm 파라미터를 추가하였습니다 - 현재 51% 정도의 정확도를 보이고 있습니다
|
||||||
|
|
||||||
|
> 3. 파티클의 수를 늘리면 전역 최적해에 좀더 가까워지는 현상을 발견하였다. 하지만 파티클의 수를 늘리면 메모리 사용량이 기하급수적으로 늘어난다.
|
||||||
|
|
||||||
|
-> keras 모델을 사용할때 predict, evaluate 함수를 사용하면 메모리 누수가 발생하는 문제를 찾았습니다. 해결방법을 추가로 찾아보는중 입니다.
|
||||||
|
-> 추가로 파티클의 수가 적을때에도 전역 최적해를 쉽게 찾는 방법을 찾는중 입니다
|
||||||
|
|
||||||
### 개인적인 생각
|
### 개인적인 생각
|
||||||
|
|
||||||
> 머신러닝 분류 방식에 존재하는 random forest 방식을 이용하여, 오차역전파 함수를 최적화 하는 방법이 있을것 같습니다
|
> 머신러닝 분류 방식에 존재하는 random forest 방식을 이용하여, 오차역전파 함수를 최적화 하는 방법이 있을것 같습니다
|
||||||
>
|
>
|
||||||
> > pso 와 random forest 방식이 매우 유사하다고 생각하여 학습할 때 뿐만 아니라 예측 할 때도 이러한 방식으로 사용할 수 있을 것 같습니다
|
> > pso 와 random forest 방식이 매우 유사하다고 생각하여 학습할 때 뿐만 아니라 예측 할 때도 이러한 방식으로 사용할 수 있을 것 같습니다
|
||||||
|
>
|
||||||
|
> 각
|
||||||
|
|
||||||
# 참고 자료
|
# 참고 자료
|
||||||
|
|
||||||
|
|||||||
BIN
history_plt/mnist_51.74_acc.png
Executable file
BIN
history_plt/mnist_51.74_acc.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 217 KiB |
BIN
history_plt/mnist_51.74_loss.png
Executable file
BIN
history_plt/mnist_51.74_loss.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 220 KiB |
37
mnist.py
37
mnist.py
@@ -1,4 +1,5 @@
|
|||||||
# %%
|
# %%
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
@@ -6,6 +7,7 @@ os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
|
|||||||
|
|
||||||
import gc
|
import gc
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
import tensorflow as tf
|
import tensorflow as tf
|
||||||
from keras.datasets import mnist
|
from keras.datasets import mnist
|
||||||
from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D
|
from keras.layers import Conv2D, Dense, Dropout, Flatten, MaxPooling2D
|
||||||
@@ -24,6 +26,9 @@ def get_data():
|
|||||||
|
|
||||||
y_train, y_test = tf.one_hot(y_train, 10), tf.one_hot(y_test, 10)
|
y_train, y_test = tf.one_hot(y_train, 10), tf.one_hot(y_test, 10)
|
||||||
|
|
||||||
|
x_train, x_test = tf.convert_to_tensor(x_train), tf.convert_to_tensor(x_test)
|
||||||
|
y_train, y_test = tf.convert_to_tensor(y_train), tf.convert_to_tensor(y_test)
|
||||||
|
|
||||||
print(f"x_train : {x_train[0].shape} | y_train : {y_train[0].shape}")
|
print(f"x_train : {x_train[0].shape} | y_train : {y_train[0].shape}")
|
||||||
print(f"x_test : {x_test[0].shape} | y_test : {y_test[0].shape}")
|
print(f"x_test : {x_test[0].shape} | y_test : {y_test[0].shape}")
|
||||||
|
|
||||||
@@ -37,6 +42,9 @@ def get_data_test():
|
|||||||
|
|
||||||
y_test = tf.one_hot(y_test, 10)
|
y_test = tf.one_hot(y_test, 10)
|
||||||
|
|
||||||
|
x_test = tf.convert_to_tensor(x_test)
|
||||||
|
y_test = tf.convert_to_tensor(y_test)
|
||||||
|
|
||||||
print(f"x_test : {x_test[0].shape} | y_test : {y_test[0].shape}")
|
print(f"x_test : {x_test[0].shape} | y_test : {y_test[0].shape}")
|
||||||
|
|
||||||
return x_test, y_test
|
return x_test, y_test
|
||||||
@@ -58,6 +66,23 @@ def make_model():
|
|||||||
return model
|
return model
|
||||||
|
|
||||||
|
|
||||||
|
def random_state():
|
||||||
|
with open(
|
||||||
|
"result/mnist/20230720-192726/mean_squared_error_[0.4970000088214874, 0.10073449462652206].json",
|
||||||
|
"r",
|
||||||
|
) as f:
|
||||||
|
json_ = json.load(f)
|
||||||
|
rs = (
|
||||||
|
json_["random_state_0"],
|
||||||
|
np.array(json_["random_state_1"]),
|
||||||
|
json_["random_state_2"],
|
||||||
|
json_["random_state_3"],
|
||||||
|
json_["random_state_4"],
|
||||||
|
)
|
||||||
|
|
||||||
|
return rs
|
||||||
|
|
||||||
|
|
||||||
# %%
|
# %%
|
||||||
model = make_model()
|
model = make_model()
|
||||||
x_train, y_train = get_data_test()
|
x_train, y_train = get_data_test()
|
||||||
@@ -76,15 +101,16 @@ loss = [
|
|||||||
"mean_absolute_percentage_error",
|
"mean_absolute_percentage_error",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# rs = random_state()
|
||||||
|
|
||||||
pso_mnist = Optimizer(
|
pso_mnist = Optimizer(
|
||||||
model,
|
model,
|
||||||
loss=loss[0],
|
loss=loss[0],
|
||||||
n_particles=70,
|
n_particles=100,
|
||||||
c0=0.3,
|
c0=0.25,
|
||||||
c1=0.5,
|
c1=0.4,
|
||||||
w_min=0.4,
|
w_min=0.3,
|
||||||
w_max=0.7,
|
w_max=0.9,
|
||||||
negative_swarm=0.1,
|
negative_swarm=0.1,
|
||||||
mutation_swarm=0.2,
|
mutation_swarm=0.2,
|
||||||
particle_min=-5,
|
particle_min=-5,
|
||||||
@@ -105,5 +131,4 @@ best_score = pso_mnist.fit(
|
|||||||
|
|
||||||
print("Done!")
|
print("Done!")
|
||||||
|
|
||||||
gc.collect()
|
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
from .optimizer import Optimizer
|
from .optimizer import Optimizer
|
||||||
from .particle import Particle
|
from .particle import Particle
|
||||||
|
|
||||||
__version__ = "0.1.3"
|
__version__ = "0.1.4"
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"Optimizer",
|
"Optimizer",
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ class Optimizer:
|
|||||||
mutation_swarm: float = 0,
|
mutation_swarm: float = 0,
|
||||||
np_seed: int = None,
|
np_seed: int = None,
|
||||||
tf_seed: int = None,
|
tf_seed: int = None,
|
||||||
|
random_state: tuple = None,
|
||||||
particle_min: float = -5,
|
particle_min: float = -5,
|
||||||
particle_max: float = 5,
|
particle_max: float = 5,
|
||||||
):
|
):
|
||||||
@@ -66,6 +67,9 @@ class Optimizer:
|
|||||||
|
|
||||||
self.random_state = np.random.get_state()
|
self.random_state = np.random.get_state()
|
||||||
|
|
||||||
|
if random_state is not None:
|
||||||
|
np.random.set_state(random_state)
|
||||||
|
|
||||||
self.model = model # 모델 구조
|
self.model = model # 모델 구조
|
||||||
self.loss = loss # 손실함수
|
self.loss = loss # 손실함수
|
||||||
self.n_particles = n_particles # 파티클 개수
|
self.n_particles = n_particles # 파티클 개수
|
||||||
@@ -113,6 +117,8 @@ class Optimizer:
|
|||||||
print(f"mutation swarm : {mutation_swarm * 100}%")
|
print(f"mutation swarm : {mutation_swarm * 100}%")
|
||||||
|
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
tf.keras.backend.reset_uids()
|
||||||
|
tf.keras.backend.clear_session()
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
del self.model
|
del self.model
|
||||||
@@ -129,6 +135,8 @@ class Optimizer:
|
|||||||
del self.g_best_
|
del self.g_best_
|
||||||
del self.avg_score
|
del self.avg_score
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
tf.keras.backend.reset_uids()
|
||||||
|
tf.keras.backend.clear_session()
|
||||||
|
|
||||||
def _encode(self, weights):
|
def _encode(self, weights):
|
||||||
"""
|
"""
|
||||||
@@ -304,7 +312,8 @@ class Optimizer:
|
|||||||
tf.summary.scalar("accuracy", local_score[1], step=0)
|
tf.summary.scalar("accuracy", local_score[1], step=0)
|
||||||
del local_score
|
del local_score
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
tf.keras.backend.reset_uids()
|
||||||
|
tf.keras.backend.clear_session()
|
||||||
print(
|
print(
|
||||||
f"initial g_best_score : {self.g_best_score[0] if self.renewal == 'acc' else self.g_best_score[1]}"
|
f"initial g_best_score : {self.g_best_score[0] if self.renewal == 'acc' else self.g_best_score[1]}"
|
||||||
)
|
)
|
||||||
@@ -454,7 +463,9 @@ class Optimizer:
|
|||||||
f.write(", ")
|
f.write(", ")
|
||||||
else:
|
else:
|
||||||
f.write("\n")
|
f.write("\n")
|
||||||
|
# gc.collect()
|
||||||
|
# tf.keras.backend.reset_uids()
|
||||||
|
# tf.keras.backend.clear_session()
|
||||||
part_pbar.refresh()
|
part_pbar.refresh()
|
||||||
|
|
||||||
if check_point is not None:
|
if check_point is not None:
|
||||||
@@ -463,6 +474,8 @@ class Optimizer:
|
|||||||
self._check_point_save(f"./{save_path}/{self.day}/ckpt-{epoch}")
|
self._check_point_save(f"./{save_path}/{self.day}/ckpt-{epoch}")
|
||||||
|
|
||||||
gc.collect()
|
gc.collect()
|
||||||
|
tf.keras.backend.reset_uids()
|
||||||
|
tf.keras.backend.clear_session()
|
||||||
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
print("Ctrl + C : Stop Training")
|
print("Ctrl + C : Stop Training")
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import gc
|
import gc
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import tensorflow as tf
|
||||||
from tensorflow import keras
|
from tensorflow import keras
|
||||||
|
|
||||||
|
|
||||||
@@ -37,7 +38,6 @@ class Particle:
|
|||||||
|
|
||||||
del i_w_, s_, l_
|
del i_w_, s_, l_
|
||||||
del init_weights
|
del init_weights
|
||||||
gc.collect()
|
|
||||||
|
|
||||||
def __del__(self):
|
def __del__(self):
|
||||||
del self.model
|
del self.model
|
||||||
@@ -46,7 +46,6 @@ class Particle:
|
|||||||
del self.negative
|
del self.negative
|
||||||
del self.best_score
|
del self.best_score
|
||||||
del self.best_weights
|
del self.best_weights
|
||||||
gc.collect()
|
|
||||||
|
|
||||||
def _encode(self, weights: list):
|
def _encode(self, weights: list):
|
||||||
"""
|
"""
|
||||||
@@ -109,7 +108,7 @@ class Particle:
|
|||||||
(float): 점수
|
(float): 점수
|
||||||
"""
|
"""
|
||||||
self.model.compile(loss=self.loss, optimizer="sgd", metrics=["accuracy"])
|
self.model.compile(loss=self.loss, optimizer="sgd", metrics=["accuracy"])
|
||||||
score = self.model.evaluate(x, y, verbose=0)
|
score = self.model.evaluate(x, y, verbose=0, use_multiprocessing=True)
|
||||||
if renewal == "acc":
|
if renewal == "acc":
|
||||||
if score[1] > self.best_score:
|
if score[1] > self.best_score:
|
||||||
self.best_score = score[1]
|
self.best_score = score[1]
|
||||||
@@ -221,26 +220,6 @@ class Particle:
|
|||||||
del encode_w, w_sh, w_len
|
del encode_w, w_sh, w_len
|
||||||
del encode_v, v_sh, v_len
|
del encode_v, v_sh, v_len
|
||||||
|
|
||||||
def f(self, x, y, weights):
|
|
||||||
"""
|
|
||||||
EBPSO의 목적함수(예상)
|
|
||||||
|
|
||||||
Args:
|
|
||||||
x (list): 입력 데이터
|
|
||||||
y (list): 출력 데이터
|
|
||||||
weights (list): 가중치
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
float: 목적함수 값
|
|
||||||
"""
|
|
||||||
self.model.set_weights(weights)
|
|
||||||
score = self.model.evaluate(x, y, verbose=0)[1]
|
|
||||||
|
|
||||||
if score > 0:
|
|
||||||
return 1 / (1 + score)
|
|
||||||
else:
|
|
||||||
return 1 + np.abs(score)
|
|
||||||
|
|
||||||
def step(self, x, y, local_rate, global_rate, w, g_best, renewal: str = "acc"):
|
def step(self, x, y, local_rate, global_rate, w, g_best, renewal: str = "acc"):
|
||||||
"""
|
"""
|
||||||
파티클의 한 스텝을 진행합니다.
|
파티클의 한 스텝을 진행합니다.
|
||||||
|
|||||||
6
setup.py
6
setup.py
@@ -12,16 +12,14 @@ setup(
|
|||||||
author_email="jgbong0306@gmail.com",
|
author_email="jgbong0306@gmail.com",
|
||||||
url="https://github.com/jung-geun/PSO",
|
url="https://github.com/jung-geun/PSO",
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"tqdm==4.65.0",
|
"tqdm",
|
||||||
"tensorflow==2.11.1",
|
|
||||||
"tensorboard==2.11.2",
|
|
||||||
"numpy",
|
"numpy",
|
||||||
"pandas",
|
"pandas",
|
||||||
"ipython",
|
"ipython",
|
||||||
],
|
],
|
||||||
packages=find_packages(exclude=[]),
|
packages=find_packages(exclude=[]),
|
||||||
keywords=["pso", "tensorflow", "keras"],
|
keywords=["pso", "tensorflow", "keras"],
|
||||||
python_requires="==3.8",
|
python_requires="==3.9",
|
||||||
package_data={},
|
package_data={},
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
long_description=open("README.md", encoding="UTF8").read(),
|
long_description=open("README.md", encoding="UTF8").read(),
|
||||||
|
|||||||
Reference in New Issue
Block a user