AIFFEL을 진행하며 케창딥 13장 케라스 하이퍼 파라미터 튜닝을 학습하고 실습하였다.
하이퍼 파라미터 튜닝 Flow
케라스 창시자에게 배우는 딥러닝에서 소개하는 하이퍼 파라미터 튜닝을 포함한 모델 훈련의 Flow는 아래와 같다.
- hp 인수를 포함한 모델 구축 함수 정의
- Tuner 정의(RandomSearch, Bayesian Optimization, hyperband)
- 데이터 준비(training, validation, testing)
- 최상의 하이퍼파라미터 설정 확인하기 (call back 함수 설정)
- 최적의 epoch 찾기
- 최종 모델 훈련 및 평가
1. 모델 구축 함수 정의
케라스 창시자에게 배우는 딥러닝에서 소개하는 모델 구축방법은 2가지로 함수형 접근 방식, HyperModel 클래스 접근 방식이 있다.
하이퍼 파라미터를 튜닝할때의 모델은 HyperParameters 클래스의 객체를 받아와 하이퍼 파라미터의 종류와 범위를 정해야 한다
우선 두가지 모델을 살펴보자.
HyperParameters 객체란?
hp는 Keras Tuner의 HyperParameters 클래스의 객체로 모델 구축 과정에서 튜닝할 하이퍼파라미터들의 범위와 종류를 정의하는 역할을 하며, hp.Int, hp.Choice 등의 메서드를 활용하여 탐색할 하이퍼파라미터를 정의하고, 최소값, 최대값, 단계 등을 설정할 수 있다.
KerasTuner 모델 구축 함수
- build_model 함수를 정의, 하이퍼파라미터 범위를 샘플링할 수 있는 hp 매개변수를 받고 컴파일된 케라스 모델 반환.
from tensorflow import keras
from tensorflow.keras import layers
def build_model(hp):
units = hp.Int(name="units", min_value=16, max_value=64, step=16)
#units라는 이름의 정수형 하이퍼파라미터를 정의함
#최소값은 16, 최대값은 64, 단계는 16으로 설정하여 16, 32, 48, 64 중 하나의 값이 선택됨
model = keras.Sequential([
layers.Dense(units, activation="relu"),
layers.Dense(10, activation="softmax")
])
optimizer = hp.Choice(name="optimizer", values=["rmsprop", "adam"])\
#optimizer라는 이름의 선택형 하이퍼파라미터를 정의
#"rmsprop" 또는 "adam" 중 하나의 값이 선택됨
model.compile(
optimizer=optimizer,
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
return model
KerasTuner의 HyperModel
- 모델 구축을 조금 더 모듈화하고 설정하기 쉽게 만들기 위해 HyperModel 클래스를 상속하여 build 메서드를 정의함.
import kerastuner as kt
class SimpleMLP(kt.HyperModel):
def __init__(self, num_classes):
self.num_classes = num_classes
def build(self, hp):
units = hp.Int(name="units", min_value=16, max_value=64, step=16)
model = keras.Sequential([
layers.Dense(units, activation="relu"),
layers.Dense(self.num_classes, activation="softmax")
])
optimizer = hp.Choice(name="optimizer", values=["rmsprop", "adam"])
model.compile(
optimizer=optimizer,
loss="sparse_categorical_crossentropy",
metrics=["accuracy"])
return model
hypermodel = SimpleMLP(num_classes=10)
하이퍼 파라미터 튜닝시에 모델은 hp 로 Keras Tuner의 HyperParameters 클래스의 객체를 받아오게 된다. 이를 통해서 하이퍼파라미터 범위를 샘플링할 수 있다.
2. Tuner 정의
하이퍼 파라미터를 설정하기 위해서는 튜너를 정의해야 하는데, 튜너는 다음 과정을 반복하는 for 루프라고 생각할 수 있다.
- 일련의 하이퍼파라미터 값 선택
- 선택된 값으로 모델 구축 함수를 호출하여 모델을 만듬
- 모델을 훈련하고 평가를 기록
KerasTuner의 기본 내장 튜너는 RandomSearch, BayesianOptimization, Hyperband 이 있으며 책에서는 BayesianOptimization을 이용하여 튜너를 사용하였다.
BayesianOptimization을 이용한 튜너 정의 코드
tuner = kt.BayesianOptimization(
build_model, #모델구축함수 또는 HyperModel 클래스 객체
objective="val_accuracy", #최적화할 지표 설정
max_trials=10, # 탐색을 끝내기 전까지 시도할 모델 설정의 최대 횟수
executions_per_trial=2, #동일한 모델을 여러번 훈련해 결과를 평균(측정값의 분산을 줄이기 위함)
#여기서는 2회
directory="mnist_kt_test",#탐색로그 저장위치
overwrite=True,#디렉터리에 있는 데이터를 덮어쓸지
)
max_trials 매개변수의 모델 설정의 최대 횟수가 무엇을 의미하는지 헷갈릴 수 있는데 간단히, 하이퍼 파라미터 조합을 몇번 시도할껀지 시도할 횟수를 지정하는 매개변수이다.
- max_trials=10: 튜너는 최대 10번의 하이퍼파라미터 조합을 시도
- max_trials=100: 튜너는 최대 100번의 하이퍼파라미터 조합을 시도
탐색 공간의 요약정보 출력
tuner.search_space_summary()
Search space summary
Default search space size: 2
units (Int)
{'default': None, 'conditions': [], 'min_value': 16, 'max_value': 64, 'step': 16, 'sampling': 'linear'}
optimizer (Choice)
{'default': 'rmsprop', 'conditions': [], 'values': ['rmsprop', 'adam'], 'ordered': False}
3. 데이터 준비
데이터는 mnist 데이터를 통하여 실습을 진행하였다.
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
x_train = x_train.reshape((-1, 28 * 28)).astype("float32") / 255
x_test = x_test.reshape((-1, 28 * 28)).astype("float32") / 255
x_train_full = x_train[:]
y_train_full = y_train[:]
num_val_samples = 10000
x_train, x_val = x_train[:-num_val_samples], x_train[-num_val_samples:]
y_train, y_val = y_train[:-num_val_samples], y_train[-num_val_samples:]
4. 최상의 하이퍼파라미터 설정 확인하기 (call back 함수 설정)
(1) 하이퍼파라미터 서치
이제 본격적으로 하이퍼 파라미터 서치를 실시하게 되는데, 우선 서치 과정중 훈련리소스를 줄이기 위해 callback함수를 추가하였다.
Tuner 탐색 (tuner.search)과 CallBack 함수 정의 코드
callbacks = [
keras.callbacks.EarlyStopping(monitor="val_loss", patience=5),
]
tuner.search(
x_train, y_train,
batch_size=128,
epochs=100,
validation_data=(x_val, y_val),
callbacks=callbacks,
verbose=2,
)
tuner.search 함수의 매개변수를 살펴보면, 딥러닝에서 모델 train시 사용하는 fit() 함수와 동일한 것을 알 수 있는데, 그 이유는 하이퍼파라미터 서치시 학습되는 모델마다 fit() 메서드를 정의하고 매개변수를 전달하기 때문임
함수 실행 결과
Trial 10 Complete [00h 01m 14s]
val_accuracy: 0.9758500158786774
Best val_accuracy So Far: 0.9758500158786774
Total elapsed time: 00h 12m 40s
10 번의 탐색이 진행된 것과 best model의 val_accuracy 등이 확인됨
(2) 최상의 하이퍼파라미터 설정 확인
탐색 결과를 통해 최상의 하이퍼 파라미터 설정을 확인. get_best_hyperparameters(top_n) 함수를 통해 불러올 수 있음
top_n = 4
best_hps = tuner.get_best_hyperparameters(top_n)
여기서 top_n 은 최고 결과를 보여준 모델들 중 top 4 모델의 하이퍼 파라미터 값을 가져온다는 의미이렇게 다양한 파라미터의 조합을 가져오는 이유는 (1) 앙상블 모델 구축, (2) 과적합 방지, (3) 문제 정의와 모델 특성에 따른 적합 모델 선택 등의 이유라고 함앙상블 모델의 경우 내용 마지막 부분에 짧게 소개할 예정
5. 최적의 epoch 찾기
모델 훈련 전 결정해야하는 마지막 파라미터로 epoch가 있음.
최적의 epoch 찾기 코드
아래 코드는 최적의 epoch 을 찾는 함수 코드이다
def get_best_epoch(hp):
model = build_model(hp) #하이퍼 파라미터조합 hp를 사용하여 모델 생성
callbacks=[
keras.callbacks.EarlyStopping(
monitor="val_loss", mode="min", patience=10)
]
history = model.fit(
x_train, y_train,
validation_data=(x_val, y_val),
epochs=100,
batch_size=128,
callbacks=callbacks)
val_loss_per_epoch = history.history["val_loss"] #기록된 epoch 별 val_loss값을 저장
best_epoch = val_loss_per_epoch.index(min(val_loss_per_epoch)) + 1
#손실값이 가장 낮았던 인덱스의 +1을 하여 실제 epoch 값 변환
print(f"Best epoch: {best_epoch}")
return best_epoch
6. 최적의 하이퍼파라미터 조합과 에폭
최적의 하이퍼파라미터 조합과 에폭(epoch)을 사용하여 모델을 훈련 후 테스트 하는 코드
#주어진 하이퍼 파라미터 조합을 이용하여 최적의 에폭을 찾고 모델 훈련
def get_best_trained_model(hp):
best_epoch = get_best_epoch(hp)
model.fit(
x_train_full, y_train_full,
#최적 에폭에 1.2배로 모델 훈련
batch_size=128, epochs=int(best_epoch * 1.2))
return model
best_models = []
for hp in best_hps:
model = get_best_trained_model(hp)
model.evaluate(x_test, y_test)
best_models.append(model)
책에서는 최적의 하이퍼 파라미터 조합 4가지를 모두 훈련시키는데, get_best_hyperparameters(top_n) 통해 최적의 하이퍼 파라미터 조합 4가지가 들어있는 best_hps 를 조금 살펴보자
best_hps 살펴보기!
모든 하이퍼파라미터의 이름과 값을 딕셔너리 형태로 출력
best_hps[0]._hps
defaultdict(list,
{'units': [Int(name: 'units', min_value: 16, max_value: 64, step: 16, sampling: linear, default: 16)],
'optimizer': [Choice(name: 'optimizer', values: ['rmsprop', 'adam'], ordered: False, default: rmsprop)]})
최적 하이퍼파라미터 조합에 'units' 하이퍼파라미터가 포함되어 있는지 확인
best_hps[0]._exists('units', [])
{'units': 64, 'optimizer': 'rmsprop'}
최적 하이퍼파라미터 조합에 포함된 모든 하이퍼파라미터의 값을 리스트 형태로 출력
best_hps[0].values
{'units': 64, 'optimizer': 'rmsprop'}
'AI' 카테고리의 다른 글
Transformer - Structure, Posititonal Encoding (0) | 2024.06.20 |
---|---|
LSTM의 Cell State와 Gate별 특징 (0) | 2024.06.19 |
RNN(Recurrent Neural Networks) (1) | 2024.06.19 |
시퀀스-투-시퀀스(Sequence-to-Sequence) (0) | 2024.06.18 |
Semantic Segmentation 기반 아웃포커싱: Depth Estimation, Instance Segmentation을 통한 정확도 향상에 관하여 (0) | 2024.06.05 |