🤖 AI/ML

과적합

Overfitting

모델이 학습 데이터에 지나치게 맞춰져 새로운 데이터에 대한 일반화 성능이 떨어지는 현상.

📖 상세 설명

과적합(Overfitting)은 머신러닝 모델이 학습 데이터의 노이즈나 세부 패턴까지 외워버려서 새로운 데이터에 대한 예측 성능이 떨어지는 현상입니다. 학습 데이터에서는 거의 완벽한 성능을 보이지만, 테스트 데이터나 실제 서비스에서는 성능이 크게 하락합니다. 이는 모델이 데이터의 일반적인 패턴이 아닌 학습 데이터의 특수한 특성을 학습했기 때문입니다.

과적합이 발생하는 주요 원인은 모델 복잡도가 데이터 양에 비해 높거나, 학습을 너무 오래 진행하거나, 학습 데이터가 편향되어 있는 경우입니다. 예를 들어 100개의 데이터 포인트에 수백만 개의 파라미터를 가진 딥러닝 모델을 학습하면 모델이 모든 데이터를 암기하게 됩니다. 또한 검증 없이 학습 에포크를 계속 증가시키면 학습 손실은 줄어들지만 검증 손실은 오히려 증가하는 시점이 옵니다.

과적합을 방지하는 대표적인 기법으로 정규화(Regularization), 드롭아웃(Dropout), 조기 종료(Early Stopping), 데이터 증강(Data Augmentation)이 있습니다. L1/L2 정규화는 가중치 크기에 페널티를 부과하여 모델 복잡도를 제한합니다. 드롭아웃은 학습 시 무작위로 뉴런을 비활성화하여 특정 뉴런에 대한 의존도를 낮춥니다. 조기 종료는 검증 손실이 더 이상 개선되지 않을 때 학습을 멈춥니다. 데이터 증강은 이미지 회전, 자르기 등으로 학습 데이터를 인위적으로 늘립니다.

과적합과 반대되는 개념으로 과소적합(Underfitting)이 있습니다. 과소적합은 모델이 너무 단순하거나 학습이 부족하여 학습 데이터의 패턴조차 포착하지 못하는 상태입니다. 좋은 모델은 과적합과 과소적합 사이의 최적 지점을 찾아 편향-분산 트레이드오프(Bias-Variance Tradeoff)를 균형있게 맞춥니다. 이를 위해 교차 검증, 하이퍼파라미터 튜닝, 앙상블 기법 등을 활용합니다.

💻 코드 예제

PyTorch에서 드롭아웃과 조기 종료를 활용하여 과적합을 방지하는 예제입니다.

# pip install torch scikit-learn matplotlib import torch import torch.nn as nn import torch.optim as optim from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split import matplotlib.pyplot as plt # 데이터 생성 (일부러 작은 데이터셋) X, y = make_classification(n_samples=200, n_features=20, n_informative=10, n_redundant=5, random_state=42) X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.3, random_state=42) # 텐서 변환 X_train = torch.FloatTensor(X_train) y_train = torch.FloatTensor(y_train).unsqueeze(1) X_val = torch.FloatTensor(X_val) y_val = torch.FloatTensor(y_val).unsqueeze(1) # 과적합 방지를 위한 모델 (드롭아웃 적용) class RegularizedModel(nn.Module): def __init__(self, dropout_rate=0.5): super().__init__() self.fc1 = nn.Linear(20, 128) self.dropout1 = nn.Dropout(dropout_rate) self.fc2 = nn.Linear(128, 64) self.dropout2 = nn.Dropout(dropout_rate) self.fc3 = nn.Linear(64, 1) self.relu = nn.ReLU() self.sigmoid = nn.Sigmoid() def forward(self, x): x = self.relu(self.fc1(x)) x = self.dropout1(x) x = self.relu(self.fc2(x)) x = self.dropout2(x) x = self.sigmoid(self.fc3(x)) return x # 조기 종료 클래스 class EarlyStopping: def __init__(self, patience=10, min_delta=0.001): self.patience = patience self.min_delta = min_delta self.counter = 0 self.best_loss = float('inf') self.early_stop = False def __call__(self, val_loss): if val_loss < self.best_loss - self.min_delta: self.best_loss = val_loss self.counter = 0 else: self.counter += 1 if self.counter >= self.patience: self.early_stop = True # 모델 학습 model = RegularizedModel(dropout_rate=0.5) criterion = nn.BCELoss() optimizer = optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4) # L2 정규화 early_stopping = EarlyStopping(patience=15) train_losses, val_losses = [], [] for epoch in range(500): # 학습 model.train() optimizer.zero_grad() outputs = model(X_train) train_loss = criterion(outputs, y_train) train_loss.backward() optimizer.step() # 검증 model.eval() with torch.no_grad(): val_outputs = model(X_val) val_loss = criterion(val_outputs, y_val) train_losses.append(train_loss.item()) val_losses.append(val_loss.item()) # 조기 종료 체크 early_stopping(val_loss.item()) if early_stopping.early_stop: print(f"조기 종료! Epoch: {epoch+1}") break if (epoch + 1) % 50 == 0: print(f"Epoch {epoch+1}: Train Loss={train_loss:.4f}, Val Loss={val_loss:.4f}") # 학습 곡선 시각화 plt.figure(figsize=(10, 5)) plt.plot(train_losses, label='Train Loss') plt.plot(val_losses, label='Validation Loss') plt.xlabel('Epoch') plt.ylabel('Loss') plt.legend() plt.title('Training vs Validation Loss (Overfitting Prevention)') plt.savefig('learning_curve.png') print("학습 곡선 저장: learning_curve.png")

🗣️ 실무에서 이렇게 말하세요

팀원:
"학습 정확도는 99%인데 테스트에서 75%밖에 안 나와요. 뭐가 문제일까요?"
ML 엔지니어:
"전형적인 과적합이네요. 학습 곡선 보니까 에포크 50 이후부터 검증 손실이 올라가고 있어요. 일단 드롭아웃 0.3 넣고, L2 regularization weight_decay=1e-4 추가하고, Early Stopping patience 10으로 걸어봅시다. 데이터가 충분하면 데이터 증강도 고려해볼게요."

⚠️ 흔한 실수 & 주의사항

학습 손실만 보고 모델 성능을 판단함
반드시 검증/테스트 손실을 함께 모니터링하고 학습 곡선을 시각화함
과적합 방지 기법을 한꺼번에 모두 적용함
하나씩 적용하며 효과를 확인하고, 과적합이 완화되면 멈춤
테스트 데이터로 하이퍼파라미터 튜닝을 함 (데이터 누수)
검증 데이터로 튜닝하고, 테스트 데이터는 최종 평가에만 사용

🔗 관련 용어

📚 더 배우기