pypi 0.1.4 업데이트
keras 의 메모리 누수를 어느정도 해결했으나 아직 완벽히 해결이 되지 않음
입력 데이터를 tensor 형태로 변환해주어 넣는 방식으로 전환
This commit is contained in:
jung-geun
2023-07-21 15:20:24 +09:00
parent 23176bafb2
commit 99b1de3f82
9 changed files with 96 additions and 68 deletions

View File

@@ -1,4 +1,4 @@
name: Python Package Index publish
name: PyPI package
on: [push]

View File

@@ -1,3 +1,5 @@
[![Python Package Index publish](https://github.com/jung-geun/PSO/actions/workflows/pypi.yml/badge.svg?event=push)](https://github.com/jung-geun/PSO/actions/workflows/pypi.yml)
# PSO 알고리즘 구현 및 새로운 시도
pso 알고리즘을 사용하여 새로운 학습 방법을 찾는중 입니다
@@ -21,16 +23,24 @@ pso 알고리즘을 사용하여 새로운 학습 방법을 찾는중 입니다
> \end{cases}
> $$
### 위치를 현재 전역해로 변경(덮어쓰기)하면 안되는 이유
위치를 가장 최적값으로 변경하면 지역 최적값에서 벗어나지 못합니다. 따라서 전역 최적값을 찾을 수 없습니다.
# 초기 세팅
자동으로 conda 환경을 설정하기 위해서는 다음 명령어를 사용합니다
```shell
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 알고리즘 구현
@@ -55,6 +65,7 @@ conda env create -f ./conda_env/environment.yaml
|-- mnist_tf.py # tensorflow 를 이용한 mnist 문제 풀이
|-- plt.ipynb # pyplot 으로 학습 결과를 그래프로 표현
|-- README.md # 현재 파일
|-- requirements.txt # pypi 에서 다운로드 받을 패키지 목록
```
pso 라이브러리는 tensorflow 모델을 학습하기 위해 기본 ./metacode/pso_meta.py 코드에서 수정하였습니다 [2]
@@ -63,20 +74,12 @@ pso 라이브러리는 tensorflow 모델을 학습하기 위해 기본 ./metacod
pso 알고리즘을 이용하여 오차역전파 함수를 최적화 하는 방법을 찾는 중입니다
### 브레인스토밍
### 알고리즘 작동 방식
> 1. 오차역전파 함수를 1~5회 실행하여 오차를 구합니다
> 2. 오차가 가장 적은 다른 노드(particle) 가중치로 유도합니다.
>
> > 2-1. 만약 오차가 가장 작은 다른 노드가 현재 노드보다 오차가 크다면, 현재 노드의 가중치를 유지합니다. - 현재의 가중치를 최적값으로 업로드합니다
> >
> > 2-2. 지역 최적값을 찾았다면, 전역 최적값을 찾을 때까지 1~2 과정을 반복합니다
>
> 3. 전역 최적값이 특정 임계치에서 변화율이 적다면 학습을 종료합니다 - 현재 결과가 정확도가 높지 않아서 이 기능은 추후에 추가할 예정입니다
</br>
위의 아이디어는 원래의 목표와 다른 방향으로 가고 있습니다. 따라서 다른 방법을 모색해야할 것 같습니다
</br>
> 1. 파티클의 위치와 속도를 초기화 한다.
> 2. 각 파티클의 점수를 계산한다.
> 3. 각 파티클의 지역 최적해와 전역 최적해를 구한다.
> 4. 각 파티클의 속도를 업데이트 한다.
## 3. PSO 알고리즘을 이용하여 풀이한 문제들의 정확도
@@ -160,30 +163,33 @@ loss = 'mean_squared_error'
pso_mnist = Optimizer(
model,
loss=loss,
n_particles=75,
c0=0.25,
c1=0.4,
w_min=0.2,
w_max=0.6,
n_particles=100,
c0=0.3,
c1=0.5,
w_min=0.4,
w_max=0.7,
negative_swarm=0.1,
mutation_swarm=0.2,
particle_min=-5,
particle_max=5,
)
best_score = pso_mnist.fit(
x_test,
y_test,
x_train,
y_train,
epochs=200,
save=True,
save_info=True,
log=2,
log_name="mnist",
save_path="./result/mnist",
renewal="acc",
empirical_balance=False,
Dispersion=False,
check_point=25
check_point=25,
)
```
위의 파라미터 기준 현재 정확도 43.38%를 보이고 있습니다
![mnist](./history_plt/mnist_mse_43.38.png)
위의 파라미터 기준 현재 정확도 51.84%를 보이고 있습니다
![mnist_acc](./history_plt/mnist_51.74_acc.png)
![mnist_loss](./history_plt/mnist_51.74_loss.png)
### Trouble Shooting
@@ -194,13 +200,20 @@ best_score = pso_mnist.fit(
> 2. 지역최적값에 계속 머무르는 조기 수렴 현상이 나타난다. - 30% 정도의 정확도를 가진다
-> 지역최적값에 머무르는 것을 방지하기 위해 negative_swarm, mutation_swarm 파라미터를 추가하였습니다 - 현재 43% 정도의 정확도를 보이고 있습니다
-> 지역최적값에 머무르는 것을 방지하기 위해 negative_swarm, mutation_swarm 파라미터를 추가하였습니다 - 현재 51% 정도의 정확도를 보이고 있습니다
> 3. 파티클의 수를 늘리면 전역 최적해에 좀더 가까워지는 현상을 발견하였다. 하지만 파티클의 수를 늘리면 메모리 사용량이 기하급수적으로 늘어난다.
-> keras 모델을 사용할때 predict, evaluate 함수를 사용하면 메모리 누수가 발생하는 문제를 찾았습니다. 해결방법을 추가로 찾아보는중 입니다.
-> 추가로 파티클의 수가 적을때에도 전역 최적해를 쉽게 찾는 방법을 찾는중 입니다
### 개인적인 생각
> 머신러닝 분류 방식에 존재하는 random forest 방식을 이용하여, 오차역전파 함수를 최적화 하는 방법이 있을것 같습니다
>
> > pso 와 random forest 방식이 매우 유사하다고 생각하여 학습할 때 뿐만 아니라 예측 할 때도 이러한 방식으로 사용할 수 있을 것 같습니다
>
>
# 참고 자료

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View File

@@ -1,4 +1,5 @@
# %%
import json
import os
import sys
@@ -6,6 +7,7 @@ os.environ["TF_CPP_MIN_LOG_LEVEL"] = "2"
import gc
import numpy as np
import tensorflow as tf
from keras.datasets import mnist
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)
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_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)
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}")
return x_test, y_test
@@ -58,6 +66,23 @@ def make_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()
x_train, y_train = get_data_test()
@@ -76,15 +101,16 @@ loss = [
"mean_absolute_percentage_error",
]
# rs = random_state()
pso_mnist = Optimizer(
model,
loss=loss[0],
n_particles=70,
c0=0.3,
c1=0.5,
w_min=0.4,
w_max=0.7,
n_particles=100,
c0=0.25,
c1=0.4,
w_min=0.3,
w_max=0.9,
negative_swarm=0.1,
mutation_swarm=0.2,
particle_min=-5,
@@ -105,5 +131,4 @@ best_score = pso_mnist.fit(
print("Done!")
gc.collect()
sys.exit(0)

View File

@@ -1,7 +1,7 @@
from .optimizer import Optimizer
from .particle import Particle
__version__ = "0.1.3"
__version__ = "0.1.4"
__all__ = [
"Optimizer",

View File

@@ -38,6 +38,7 @@ class Optimizer:
mutation_swarm: float = 0,
np_seed: int = None,
tf_seed: int = None,
random_state: tuple = None,
particle_min: float = -5,
particle_max: float = 5,
):
@@ -66,6 +67,9 @@ class Optimizer:
self.random_state = np.random.get_state()
if random_state is not None:
np.random.set_state(random_state)
self.model = model # 모델 구조
self.loss = loss # 손실함수
self.n_particles = n_particles # 파티클 개수
@@ -113,6 +117,8 @@ class Optimizer:
print(f"mutation swarm : {mutation_swarm * 100}%")
gc.collect()
tf.keras.backend.reset_uids()
tf.keras.backend.clear_session()
def __del__(self):
del self.model
@@ -129,6 +135,8 @@ class Optimizer:
del self.g_best_
del self.avg_score
gc.collect()
tf.keras.backend.reset_uids()
tf.keras.backend.clear_session()
def _encode(self, weights):
"""
@@ -304,7 +312,8 @@ class Optimizer:
tf.summary.scalar("accuracy", local_score[1], step=0)
del local_score
gc.collect()
tf.keras.backend.reset_uids()
tf.keras.backend.clear_session()
print(
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(", ")
else:
f.write("\n")
# gc.collect()
# tf.keras.backend.reset_uids()
# tf.keras.backend.clear_session()
part_pbar.refresh()
if check_point is not None:
@@ -463,6 +474,8 @@ class Optimizer:
self._check_point_save(f"./{save_path}/{self.day}/ckpt-{epoch}")
gc.collect()
tf.keras.backend.reset_uids()
tf.keras.backend.clear_session()
except KeyboardInterrupt:
print("Ctrl + C : Stop Training")

View File

@@ -1,6 +1,7 @@
import gc
import numpy as np
import tensorflow as tf
from tensorflow import keras
@@ -37,7 +38,6 @@ class Particle:
del i_w_, s_, l_
del init_weights
gc.collect()
def __del__(self):
del self.model
@@ -46,7 +46,6 @@ class Particle:
del self.negative
del self.best_score
del self.best_weights
gc.collect()
def _encode(self, weights: list):
"""
@@ -109,7 +108,7 @@ class Particle:
(float): 점수
"""
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 score[1] > self.best_score:
self.best_score = score[1]
@@ -221,26 +220,6 @@ class Particle:
del encode_w, w_sh, w_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"):
"""
파티클의 한 스텝을 진행합니다.

View File

@@ -12,16 +12,14 @@ setup(
author_email="jgbong0306@gmail.com",
url="https://github.com/jung-geun/PSO",
install_requires=[
"tqdm==4.65.0",
"tensorflow==2.11.1",
"tensorboard==2.11.2",
"tqdm",
"numpy",
"pandas",
"ipython",
],
packages=find_packages(exclude=[]),
keywords=["pso", "tensorflow", "keras"],
python_requires="==3.8",
python_requires="==3.9",
package_data={},
zip_safe=False,
long_description=open("README.md", encoding="UTF8").read(),