Summary
1. 학습 곡선을 해석하는 방법과 모델 개발의 가이드를 살펴본다.
2. 학습 곡선에서 Overfitting과 Underfitting의 파악하고, 이를 개선하는 전략을 살펴본다.
보다 나은 이해를 돕기 위해 이전 포스팅을 읽어보는 것을 권장합니다.
3.MAE, Stochastic Gradient Descent
Interpreting Learning Curves (학습 곡석의 해석하기)
[사전 지식]
훈련 데이터의 정보는 Signal과 Noise의 두 종류가 있다.
Signal은 만들고자하는 모델이 새로운 데이터를 예측하는데 도움이 되는 정보이다.
Noise는 불규칙적인 변동(random fluctuation) 또는 모델이 예측하는데 필요 없는 정보이다. 즉, 정보가 없는 패턴(Non-infomative patterns)을 말한다.
모델을 훈련할 때 Epochs별로 훈련 손실(training loss)과 유효성 검사 손실(validation loss)를 도식화한(plotting) 것을 학습 곡선(Learning Curves)이라고 한다.
[학습 곡선 해석하기]
모델이 noise 또는 signal 를 학습하면 loss가 감소한다.
validation loss는 보이지 않는 데이터의 예상 오류의 예상치를 제공한다.
signal를 학습하면 validation loss를 감소하지만, noise를 학습하면 증가하게 된다.
training loss와 validation loss 간격은 모델이 학습한 noise의 양을 의미한다.
이상적으로는 signal만 학습하고, noise는 학습하지 않는 것이다.
하지만, 이는 불가능한 것이므로 noise를 학습하는 대신 더 많은 signal을 학습하도록 한다.
이렇게 학습하다 보면, validation lose가 감소하다가 증가하는 시점이 발생하는데, 이때 학습을 중단해야(Early Stopping) 더 나은 모델을 학습할 수 있다.
[Underfitting & Overfitting]
훈련 데이터의 두가지 문제 : signal이 부족하거나 또는 noise가 많은 경우.
Underfitting 은 모델이 signal을 충분히 학습하지 못해 꽤 큰 손실(loss)이 발생한 경우.
Overfitting 은 모델이 noise를 많이 학습해서 꽤 큰 손실(loss)이 발생한 경우.
지금부터는 Noise를 줄이면서 더 많은 Signal를 학습하기 위한 방법을 살펴본다.
Increasing Capacity
모델의 Capacity (수용성)는 학습할 수 있는 패턴의 복잡성과 크기를 의미한다.
신경망 모델의 경우 뉴런 수(neurons)와 이를 연결(connection) 방법에 따라 결정된다.
만약 신경망에 Underfitting이 발생했을 경우 Capacity(수용성)를 늘려야 한다.
- 선형(Linear) 선호 모델인 경우 기존 계층(Layer)에 유닛(Unit)을 추가하여 네트워크의 더 넓게(Wider) 만든다.
- 비선형(Nonlinear) 선호 모델인 경우 더 많은 계층(Layer)를 추가하여 네트워크를 더 깊게(Deeper) 만든다.
데이터 셋에 따라 특징에 따라 적절히 선택해야 한다.
from tensorflow import keras
model = keras.Sequential([
keras.layers.Dense(units=16, activation="relu"),
keras.layers.Dense(units=1)
])
# 더 넓은 네트워크 예시 : units을 16에서 32개로 확장
wider_model = keras.Sequential([
keras.layers.Dense(units=32, activation="relu"),
keras.layers.Dense(units=1)
])
# 더 깊은 네트워크 예시 : 16개의 유닛을 레이어 추가.
deeper_model = keras.Sequential([
keras.layers.Dense(units=16, activation="relu"),
keras.layers.Dense(units=16, activation="relu"),
keras.layers.Dense(units=1)
])
Early Stopping
앞서 언급했듯이 모델이 Noise를 많이 학습할 경우 validation loss가 증가하는 시점이 발생한다.
이를 방지하기 위해 validation loss가 더 이상 감소하지 않을 경우 학습을 중단할 수 있다.
이와 같이 훈련을 중단하는 것을 Early Stopping이라고 한다.
validation loss가 다시 증가하기 시작하는 시점을 감지하면 가중치를 최소값이 발생한 위치로 재설정한다.
이렇게 하면 모델이 Noise를 학습하고 Overfitting을 방지한다.
early stopping은 충분히 훈련하기 전에 중지되는 Underfitting을 방지한다.
Epochs는 높게 설정하더라도 Early Stopping 알아서 처리한다.
Adding Early Stopping
Keras에서는 callback을 통해서 훈련 중에 Early Stopping를 반영한다.
Early Stopping Callback은 Epochs 이후 실행된다.
다음 코드는 "20번의 epochs 동안(patience=20) validation loss가 0.001 이상 개선되지 않으면(min_delta=0.001) 훈련을 중지하고, 최상의 모델을 유지한다."라는 의미이다.
참고 : tensorflow.keras.callbacks.EarlyStopping document
import tensorflow.keras.callbacks import EarlyStopping
early_stopping = EarlyStopping(
min_delta=0.001,
patience=20,
restore_best_weights=True
)
Example - Train a Model with Early Stopping
이전 과정의 예제(Stochastic-Gradient-Descent 포스팅) 이어서 모델을 개발해본다.
해당 네트워크의 용량을 늘리지만, Overfitting을 방지하기 위해 Early Stopping을 콜백을 추가한다.
데이터를 다음과 같이 준비한다.
원본 데이터 및 데이터 전처리 코드
import pandas as pd
raw_df = pd.read_csv("../data/red-wine.csv")
# Create training and validation splits
df_train = raw_df.sample(frac=0.7, random_state=0)
df_valid = raw_df.drop(df_train.index)
#df_train.head(4)
# Scale to [0, 1]
max_ = df_train.max(axis=0)
min_ = df_train.min(axis=0)
df_train = (df_train - min_) / (max_ - min_)
df_valid = (df_valid - min_) / (max_ - min_)
# Split features and target
X_train = df_train.drop('quality', axis=1)
X_valid = df_valid.drop('quality', axis=1)
y_train = df_train['quality']
y_valid = df_valid['quality']
network의 capacity 늘리고, early stopping 통해 최적의 모델을 학습해본다.
이제 early stopping을 추가되었으니, fit()메소드에 epochs는 값을 큰 값으로 설정한다.
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.callbacks import EarlyStopping
# Early Stopping callback 생성
early_stopping = EarlyStopping(
min_delta = 0.001,
patience = 20,
restore_best_weights = True
)
# Layer, Unit 설정.
model = keras.Sequential([
layers.Dense(units=512, activation="relu", input_shape=[11]),
layers.Dense(units=512, activation="relu"),
layers.Dense(units=512, activation="relu"),
layers.Dense(units=1)
])
# loss-function, optimizer 설정.
model.compile(
optimizer = "adam",
loss = "mae"
)
# Training
history = model.fit(
X_train, y_train,
validation_data = (X_valid, y_valid),
batch_size = 256,
callbacks = [early_stopping], # 위에서 생성한 early stopping 콜백을 지정한다.
epochs=500,
verbose=0 #0=log message off
)
훈련 결과를 살펴보면 epoch가 500이 되기 전에 훈련이 중단된 것을 확인할 수 있다.
import pandas as pd
history_df = pd.DataFrame(history.history)
# history_df
history_df.loc[:, ['loss', 'val_loss']].plot()
print("Minimum validation loss: {}".format(history_df['val_loss'].min()))
<관련 포스팅>
[Intro to Deep Learning] A Single Neuron
[Intro to Deep Learning] Deep Neural Networks
[Intro to Deep Learning] MAE, Stochastic Gradient Descent
[Intro to Deep Learning] Dropout and Batch Normalization
<참고자료>
Source : https://www.kaggle.com/code/ryanholbrook/overfitting-and-underfitting
'Data Science > Deep Learning' 카테고리의 다른 글
PyTorch : #1 Tensors (0) | 2023.02.22 |
---|---|
Image Generate AI Testing (0) | 2023.02.14 |
[Intro to Deep Learning] MAE, Stochastic Gradient Descent (0) | 2022.09.06 |
[Intro to Deep Learning] Deep Neural Networks (0) | 2022.09.06 |
[Intro to Deep Learning] A Single Neuron (0) | 2022.09.02 |
최근댓글