T'SPACE

다채로운 에디터들의 이야기

컴퓨터공학/인공지능

딥러닝 모델 성능 향상을 위한 Dropout과 Batch Normalization

Tonny Kang 2024. 8. 2. 13:06
반응형

딥러닝 모델을 설계할 때, 뉴런이 포함되지 않은 특별한 레이어를 추가함으로써 모델의 성능을 향상시킬 수 있습니다. 이번 포스트에서는 그런 레이어 중 두 가지인 Dropout과 Batch Normalization에 대해 알아보겠습니다. 이 두 레이어는 현대적인 딥러닝 아키텍처에서 흔히 사용됩니다.

Dropout


첫 번째로 소개할 레이어는 과적합(overfitting)을 방지하는 데 도움을 주는 "드롭아웃 레이어"입니다.

딥러닝 모델은 때때로 특정 가중치 조합에 의존하여 잘못된 패턴을 학습할 수 있습니다. 이러한 조합은 매우 구체적이어서 하나만 제거해도 모델의 성능이 급격히 떨어질 수 있습니다. 이를 방지하기 위해 드롭아웃을 사용합니다. 드롭아웃은 훈련 중 매 스텝마다 레이어의 입력 유닛 일부를 무작위로 제거하여, 모델이 훈련 데이터의 잘못된 패턴을 학습하지 않도록 합니다. 대신, 모델은 더 일반적이고 견고한 패턴을 찾게 됩니다.

Here, 50% dropout has been added between the two hidden layers.

드롭아웃을 사용하면 하나의 큰 네트워크 대신 여러 작은 네트워크들의 집합으로 예측을 수행하는 효과가 있습니다. 개별 네트워크는 다양한 종류의 실수를 할 수 있지만, 전체 집합으로서의 네트워크는 더 정확한 예측을 할 수 있게 됩니다. 이는 랜덤 포레스트가 여러 개의 결정 트리로 구성된 것과 유사한 개념입니다.

Keras에서 Dropout 추가하기


Keras에서는 rate 인자를 통해 드롭아웃 비율을 설정할 수 있습니다. Dropout 레이어를 추가하고자 하는 레이어 바로 앞에 넣으면 됩니다.

keras.Sequential([
    # ...
    layers.Dropout(rate=0.3), # 다음 레이어에 30% 드롭아웃 적용
    layers.Dense(16),
    # ...
])

Batch Normalization


두 번째로 소개할 레이어는 훈련 속도나 안정성을 향상시키는 "배치 정규화 레이어"입니다.

뉴럴 네트워크에서는 일반적으로 데이터를 공통된 스케일로 정규화하는 것이 좋습니다. 이는 SGD(Stochastic Gradient Descent)가 데이터의 활성화 정도에 비례하여 네트워크 가중치를 조정하기 때문입니다. 활성화 크기가 매우 다른 피처들은 훈련 과정을 불안정하게 만들 수 있습니다.

외부에서 데이터를 정규화하는 것이 좋다면, 네트워크 내부에서도 정규화하는 것이 더 좋지 않을까요? 이를 위해 배치 정규화 레이어를 사용할 수 있습니다. 배치 정규화 레이어는 들어오는 배치를 받아 먼저 해당 배치의 평균과 표준 편차로 정규화한 다음, 두 개의 학습 가능한 재조정 매개변수를 사용하여 데이터를 새로운 스케일로 조정합니다.

배치 정규화는 최적화 과정에 도움을 주기 위해 자주 사용됩니다(때로는 예측 성능 향상에도 도움이 됩니다). 배치 정규화를 사용하면 훈련에 필요한 에포크 수를 줄일 수 있고, 훈련 중 발생할 수 있는 여러 문제를 해결할 수 있습니다. 특히 훈련이 중간에 "멈추는" 현상이 발생하는 경우, 배치 정규화를 추가해 보세요.

Keras에서 Batch Normalization 추가하기


배치 정규화는 네트워크 내 거의 모든 위치에 사용할 수 있습니다. 레이어 다음에 추가할 수 있고...

layers.Dense(16, activation='relu'),
layers.BatchNormalization(),

레이어와 활성화 함수 사이에 추가할 수도 있습니다:

layers.Dense(16),
layers.BatchNormalization(),
layers.Activation('relu'),

네트워크의 첫 번째 레이어로 추가하면, Sci-Kit Learn의 StandardScaler와 같은 전처리 역할을 할 수 있습니다.

예제 - Dropout과 Batch Normalization 사용하기


이번에는 모델의 용량을 더 늘리고, 드롭아웃을 사용하여 과적합을 제어하고 배치 정규화를 사용하여 최적화를 가속화해 보겠습니다. 이번에는 데이터를 표준화하지 않고, 배치 정규화가 훈련을 안정화시키는 모습을 보여드리겠습니다.

# 플로팅 설정
import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')
# Matplotlib 기본값 설정
plt.rc('figure', autolayout=True)
plt.rc('axes', labelweight='bold', labelsize='large',
       titleweight='bold', titlesize=18, titlepad=10)

import pandas as pd
red_wine = pd.read_csv('../input/dl-course-data/red-wine.csv')

# 훈련 및 검증 데이터 분할
df_train = red_wine.sample(frac=0.7, random_state=0)
df_valid = red_wine.drop(df_train.index)

# 피처와 타겟 분리
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']

드롭아웃을 추가하면 Dense 레이어의 유닛 수를 늘려야 할 수도 있습니다.

from tensorflow import keras
from tensorflow.keras import layers

model = keras.Sequential([
    layers.Dense(1024, activation='relu', input_shape=[11]),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1024, activation='relu'),
    layers.Dropout(0.3),
    layers.BatchNormalization(),
    layers.Dense(1),
])

훈련 설정 방법은 이전과 동일합니다.

model.compile(
    optimizer='adam',
    loss='mae',
)

history = model.fit(
    X_train, y_train,
    validation_data=(X_valid, y_valid),
    batch_size=256,
    epochs=100,
    verbose=0,
)

# 학습 곡선 표시
history_df = pd.DataFrame(history.history)
history_df.loc[:, ['loss', 'val_loss']].plot();

이 예제에서는 드롭아웃과 배치 정규화를 사용하여 과적합을 방지하고 최적화 과정을 가속화하는 방법을 살펴보았습니다. 모델이 훈련 데이터의 잘못된 패턴을 학습하지 않도록 도와주는 드롭아웃과, 훈련을 안정화시키고 가속화하는 배치 정규화를 활용하여 더 나은 성능을 얻을 수 있습니다.

반응형