성능 튜닝의 기본 방법
튜닝의 기본 목표는 val 성능을 잘 뽑는 것이다.
우리가 추구하는 바는 모집단을 예측하는 거니까.
따라서 모델링의 최종 지향점은 일반화 성능이다.
이를 위하여 다양한 시도를 해 볼 수 있는데,
learning_rate을 조절한다거나, epochs를 바꾼다거나, node를 늘릴 수도 있겠지.
딥러닝에서 우리가 조절해야 할 하이퍼파라미터는 다음과 같다.
1. Epoch 와 learning_rate
- 둘이 약한 Trade-off 관계인 것처럼 다루어야 한다.
- Epoch가 부족하면 학습이 채 되지 않을 수 있고, 지나치면 과적함의 위험이 커진다.
2. Hidden layer의 수, node의 수
- 늘어날수록 파라미터(가중치)의 개수가 늘어난다.
- 파라미터의 수가 많다 = 연결이 많다 = 모델이 복잡하다
- 파라미터가 아주 많은 언어 모델(Large Language Model) : LLM
--------------------------------------------------------------------------------------------------
이때 과적합을 막기 위해 사용하는 방법들로는 다음이 있다.
1. Early Stopping
2. Dropout
3. Regularization(L1, L2)
1과 2는 기본적으로 다음 과정을 따른다.
'하이퍼파라미터 범위 설정 - 탐색(RandomSearch/GridSearch) - 최적 성능 선택'
저 '최적 성능 선택'을 일일이 손으로 할 수는 없겠지.
따라서 우리는 모델에 규제를 가해 스스로 과적합까지 도달하지 않도록 해야 한다.
이런 방법을 규제(Regularization)이라고 한다.
EarlyStopping
위처럼 과적합이 발생하면 모델의 성능이 더 떨어지기 때문에,
최적의 성능이 나왔을 때 학습을 중단하는 것이 현명하다.
EarlyStopping은 최적의 타이밍에 학습을 중단해 주는 역할을 한다.
기본적으로 keras.callbacks에서 불러와 객체로 생성해서 쓴다.
# 모델 선언
clear_session()
model2 = Sequential( [Input(shape = (nfeatures,)),
Dense(128, activation= 'relu'),
Dense(64, activation= 'relu'),
Dense(32, activation= 'relu'),
Dense(1, activation= 'sigmoid')] )
model2.compile(optimizer= Adam(learning_rate = 0.001), loss='binary_crossentropy')
# EarlyStopping 설정 ------------
min_de = 0.001
pat = 5
es = EarlyStopping(monitor = 'val_loss', min_delta = min_de, patience = pat)
# --------------------------------
# 학습
hist = model2.fit(x_train, y_train, epochs = 100, validation_split=0.2,
callbacks = [es]).history
dl_history_plot(hist)
보아하니, fit()의 매개변수 callbacks로 쓰기 위해 es 객체를 생성하는 코드가 필요하다.
이때 EarlyStopping 객체 es가 갖는 옵션을 보아하니, 다음의 것들이 있다.
monitor : 성능평가지표
min_delta : 성능평가기준.
이 값 이상으로 성능이 개선되지 않으면, patience가 카운트된다.
patience : 인내심(?). 모델이 더이상 개선되지 않을때 허용하는 학습 횟수.
Dropout
딥러닝 뉴럴넷에서, 과적합이 일어난다는 것은
일부 노드의 중요도가 과대평가된다는 말이기도 하다.
이를 방지하기 위한 것이 Dropout인데,
학습 시마다 랜덤하게 일부 노드를 비활성화함으로써
학습의 편중을 예방한다.
Dropout은 모델 구조 단계에서 Dropout층을 집어넣어 만든다.
이때 Dropout층의 매개변수로 Dropout Rate가 들어가는데,
일반적으로 0.2 ~ 0.5의 값을 사용한다.
# Dropout import
from keras.layers import Dropout
# 메모리 정리
clear_session()
# Sequential 타입
model3 = Sequential( [Input(shape = (nfeatures,)),
Dense(128, activation= 'relu'),
Dropout(0.4),
Dense(64, activation= 'relu'),
Dropout(0.4),
Dense(32, activation= 'relu'),
Dropout(0.4),
Dense(1, activation= 'sigmoid')] )
# 컴파일
model3.compile(optimizer= Adam(learning_rate = 0.001), loss='binary_crossentropy')
Dropout을 적용하지 않았을 때가 왼쪽. val_loss가 과적합으로 상승하는 모습.
오른쪽처럼 Dropout을 적용하니 val_loss가 유지된다.