과적합을 방지하고 모델의 일반화 성능을 향상시키는 기법들

1. 과적합이란?

증상

  • 훈련 데이터에서는 높은 성능
  • 검증/테스트 데이터에서는 낮은 성능
  • 훈련 손실 << 검증 손실

원인

  • 모델이 너무 복잡
  • 데이터가 부족
  • 학습 시간이 너무 길음

해결책

→ 정규화 기법 사용!


2. 가중치 감쇠 (Weight Decay)

L2 정규화 (Ridge)

효과:

  • 가중치를 작게 유지
  • 모델을 단순화
  • 과적합 방지

하이퍼파라미터:

  • : 정규화 강도 (보통 0.0001 ~ 0.01)

코드:

# PyTorch
optimizer = torch.optim.Adam(model.parameters(), weight_decay=0.0001)
 
# Keras
from tensorflow.keras.regularizers import l2
model.add(Dense(128, activation='relu', kernel_regularizer=l2(0.0001)))

L1 정규화 (Lasso)

효과:

  • 일부 가중치를 정확히 0으로 만듦
  • 특징 선택 효과
  • 희소성 (Sparsity)

코드:

# Keras
from tensorflow.keras.regularizers import l1
model.add(Dense(128, activation='relu', kernel_regularizer=l1(0.0001)))

선택 가이드

정규화특징사용 시기
L2가중치를 작게일반적인 경우
L1일부 가중치를 0으로특징 선택 필요

3. 드롭아웃 (Dropout) ⭐

훈련 중 무작위로 일부 뉴런을 비활성화하는 기법

작동 원리

훈련 시:

  • 확률 로 뉴런 유지
  • 확률 로 뉴런 제거

테스트 시:

  • 모든 뉴런 사용
  • 출력에 곱함 (또는 훈련 시 스케일링)

시각화

훈련 시 (p=0.5):
입력층      은닉층 (일부 비활성화)    출력층
  ○  ------  ○  ------
            × (꺼짐)
  ○  ------  ○  ------
            \/
  ○  ------  × (꺼짐)

테스트 시:
모든 뉴런 활성화

효과

  1. 앙상블 효과: 여러 서브 네트워크를 학습하는 효과
  2. Co-adaptation 방지: 뉴런 간의 과도한 의존성 감소
  3. 일반화 성능 향상

Dropout 비율 가이드

층 종류추천 비율
Fully Connected Layerp = 0.5 (keep)
CNNp = 0.8 ~ 0.9 (작게)
RNNp = 0.5 ~ 0.8
입력층p = 0.8 ~ 0.9 (작게)

코드 예시

# Keras
from tensorflow.keras.layers import Dropout
 
model = keras.Sequential([
    Dense(128, activation='relu'),
    Dropout(0.5),  # 50% 드롭아웃
    Dense(64, activation='relu'),
    Dropout(0.3),  # 30% 드롭아웃
    Dense(10, activation='softmax')
])
# PyTorch
import torch.nn as nn
 
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.dropout1 = nn.Dropout(0.5)
        self.fc2 = nn.Linear(128, 64)
        self.dropout2 = nn.Dropout(0.3)
        self.fc3 = nn.Linear(64, 10)
 
    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.dropout1(x)
        x = torch.relu(self.fc2(x))
        x = self.dropout2(x)
        x = self.fc3(x)
        return x
 
# 훈련 모드
model.train()  # Dropout 활성화
 
# 평가 모드
model.eval()  # Dropout 비활성화

4. 배치 정규화 (Batch Normalization) ⭐

각 미니배치에서 활성화 값을 정규화하는 기법

작동 원리

1단계: 정규화

  • : 배치 평균
  • : 배치 분산
  • : 수치 안정성 (보통 )

2단계: 스케일 & 시프트 (학습 가능)

  • , : 학습 가능한 파라미터

효과

  1. 학습 속도 향상 (2~10배)
  2. 높은 학습률 사용 가능
  3. 가중치 초기화에 덜 민감
  4. 일부 정규화 효과 (Dropout 대체 가능)
  5. 기울기 소실/폭발 문제 완화

배치 정규화 위치

방법 1: 활성화 함수 전

Dense → Batch Norm → ReLU

방법 2: 활성화 함수 후

Dense → ReLU → Batch Norm

💡 논란: 둘 다 사용되지만, 일반적으로 활성화 전이 더 많이 사용됨

코드 예시

# Keras
from tensorflow.keras.layers import BatchNormalization
 
model = keras.Sequential([
    Dense(128),
    BatchNormalization(),  # 배치 정규화
    Activation('relu'),
    Dense(64),
    BatchNormalization(),
    Activation('relu'),
    Dense(10, activation='softmax')
])
# PyTorch
import torch.nn as nn
 
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.bn1 = nn.BatchNorm1d(128)
        self.fc2 = nn.Linear(128, 64)
        self.bn2 = nn.BatchNorm1d(64)
        self.fc3 = nn.Linear(64, 10)
 
    def forward(self, x):
        x = self.bn1(self.fc1(x))
        x = torch.relu(x)
        x = self.bn2(self.fc2(x))
        x = torch.relu(x)
        x = self.fc3(x)
        return x

주의사항

  • 배치 크기가 너무 작으면 통계가 불안정
  • RNN에는 부적합 → Layer Normalization 사용
  • 테스트 시: 전체 데이터의 이동 평균 사용

5. 레이어 정규화 (Layer Normalization)

배치가 아닌 각 샘플의 특징들을 정규화

Batch Norm vs Layer Norm

Batch NormLayer Norm
정규화 축배치 차원특징 차원
배치 크기 영향있음없음
사용처CNN, Fully ConnectedRNN, Transformer

코드

# PyTorch
import torch.nn as nn
layer_norm = nn.LayerNorm(normalized_shape=128)
 
# Keras
from tensorflow.keras.layers import LayerNormalization
LayerNormalization()

6. 조기 종료 (Early Stopping) ⭐

검증 손실이 개선되지 않으면 학습을 중단

작동 원리

에포크    훈련 손실    검증 손실
  1         0.8         0.9
  2         0.6         0.7
  3         0.5         0.6
  4         0.4         0.55  ← 최고 성능
  5         0.3         0.56
  6         0.2         0.58
  7         0.15        0.60  ← 5 에포크 동안 개선 없음 → 중단

코드 구현

# 수동 구현
best_val_loss = float('inf')
patience = 10
counter = 0
 
for epoch in range(epochs):
    train_loss = train(...)
    val_loss = validate(...)
 
    if val_loss < best_val_loss:
        best_val_loss = val_loss
        save_model()  # 최고 모델 저장
        counter = 0
    else:
        counter += 1
        if counter >= patience:
            print("Early stopping!")
            break
 
# 최고 모델 복원
load_model()
# Keras 콜백
from tensorflow.keras.callbacks import EarlyStopping
 
early_stop = EarlyStopping(
    monitor='val_loss',
    patience=10,
    restore_best_weights=True  # 최고 가중치 복원
)
 
model.fit(X, y, validation_data=(X_val, y_val), callbacks=[early_stop])

7. 데이터 증강 (Data Augmentation)

기존 데이터를 변형하여 학습 데이터를 인위적으로 늘림

이미지 데이터

일반적인 증강 기법:

  • 회전 (Rotation)
  • 이동 (Translation)
  • 확대/축소 (Scaling)
  • 좌우 반전 (Horizontal Flip)
  • 자르기 (Cropping)
  • 밝기 조절
  • 색상 변환

코드 (Keras):

from tensorflow.keras.preprocessing.image import ImageDataGenerator
 
datagen = ImageDataGenerator(
    rotation_range=20,           # 20도 회전
    width_shift_range=0.2,       # 좌우 20% 이동
    height_shift_range=0.2,      # 상하 20% 이동
    horizontal_flip=True,        # 좌우 반전
    zoom_range=0.2               # 20% 확대/축소
)
 
datagen.fit(X_train)
model.fit(datagen.flow(X_train, y_train, batch_size=32), ...)

텍스트 데이터

  • 동의어 대체
  • 역번역 (Back-translation)
  • 무작위 삽입/삭제

효과

  • ✅ 데이터 부족 문제 완화
  • ✅ 과적합 방지
  • ✅ 모델의 강건성 향상

8. 가중치 초기화 (Weight Initialization)

가중치를 어떻게 초기화하느냐가 학습 성공에 큰 영향

잘못된 초기화

모든 가중치를 0으로:

W = 0  # ❌ 절대 금지!
  • 대칭 문제: 모든 뉴런이 같은 값 학습
  • 모든 뉴런이 동일하게 업데이트

너무 큰 값:

  • 기울기 폭발
  • 불안정한 학습

너무 작은 값:

  • 기울기 소실
  • 학습이 느림

Xavier 초기화 (Glorot)

또는 Uniform:

사용 시기:

  • ✅ Sigmoid, Tanh 활성화 함수

코드:

# PyTorch
import torch.nn as nn
nn.init.xavier_normal_(layer.weight)
nn.init.xavier_uniform_(layer.weight)
 
# Keras (기본값)
Dense(128, kernel_initializer='glorot_normal')

He 초기화 ⭐

사용 시기:

  • ReLU 활성화 함수 (가장 많이 사용)

코드:

# PyTorch
nn.init.kaiming_normal_(layer.weight, mode='fan_in', nonlinearity='relu')
 
# Keras
Dense(128, kernel_initializer='he_normal')

편향 초기화

  • 보통 0으로 초기화
  • 가중치만 무작위로 초기화

초기화 선택 가이드

활성화 함수추천 초기화
ReLUHe
Sigmoid, TanhXavier
Leaky ReLUHe

9. 정규화 기법 조합

추천 조합

기본 구성:

model = keras.Sequential([
    Dense(256, kernel_initializer='he_normal'),
    BatchNormalization(),
    Activation('relu'),
    Dropout(0.3),
 
    Dense(128, kernel_initializer='he_normal'),
    BatchNormalization(),
    Activation('relu'),
    Dropout(0.3),
 
    Dense(10, activation='softmax')
])
 
# Weight Decay
optimizer = keras.optimizers.Adam(learning_rate=0.001)
model.compile(optimizer=optimizer, loss='categorical_crossentropy')

조합 순서

Dense → Batch Norm → Activation → Dropout

10. 정규화 기법 비교

기법효과계산 비용사용 빈도
Weight Decay과적합 방지낮음⭐⭐⭐⭐⭐
Dropout과적합 방지낮음⭐⭐⭐⭐⭐
Batch Norm학습 가속중간⭐⭐⭐⭐⭐
Early Stopping과적합 방지없음⭐⭐⭐⭐⭐
Data Augmentation데이터 증가높음⭐⭐⭐⭐
Layer NormRNN 안정화중간⭐⭐⭐

핵심 요약

과적합 방지 우선순위

  1. 🥇 더 많은 데이터 수집 (가장 효과적)
  2. 🥈 Dropout 추가 (0.3 ~ 0.5)
  3. 🥉 Weight Decay (0.0001)
  4. Batch Normalization (학습 속도 + 정규화)
  5. Early Stopping (항상 사용)
  6. Data Augmentation (이미지/텍스트)

모델 구성 체크리스트

  • ✅ He 초기화 (ReLU 사용 시)
  • ✅ Batch Normalization (각 층마다)
  • ✅ Dropout (0.3 ~ 0.5)
  • ✅ Weight Decay (0.0001)
  • ✅ Early Stopping (patience=10)

기억할 것

  • 정규화는 과적합 방지가 목적
  • 여러 기법을 조합하여 사용
  • 검증 세트로 성능을 모니터링
  • 과하지 않게 적절히 사용

다음 학습

  1. 딥러닝_실전_가이드 - 하이퍼파라미터 튜닝과 문제 해결
  2. 딥러닝_코드_실습 - 실제 프로젝트 구현

딥러닝 기초