
머신러닝 프로젝트를 수행하다 보면 데이터 불균형(Data Imbalance) 문제에 직면하는 경우가 매우 많습니다. 예를 들어 신용카드 부정 결제 탐지(Fraud Detection)의 경우, 정상 결제는 99.9%인 반면 부정 결제는 0.1% 미만인 경우가 허다합니다. 이 상태에서 모델을 학습시키면 모델은 단순히 모든 결제를 '정상'으로 예측해버리는 정확도의 함정에 빠지게 됩니다. 본 포스팅에서는 이러한 수치적 불균형을 극복하고 진정한 모델의 성능을 끌어올리기 위한 실무적인 해결 전략 7가지를 제시합니다.
1. 데이터 불균형이 모델 학습에 치명적인 3가지 이유
데이터의 양적 차이가 모델의 내부 로직을 어떻게 왜곡하는지 이해하는 것이 문제 해결의 시작입니다.
① 정확도 역설(Accuracy Paradox)의 발생
다수 클래스(Majority Class)가 99%인 데이터셋에서 모델이 아무런 학습 없이 "모두 다수 클래스다"라고만 답해도 정확도는 99%가 나옵니다. 하지만 우리가 정말 찾고 싶어 하는 소수 클래스(Minority Class)에 대한 예측력은 0%가 됩니다. 이는 비즈니스 관점에서 치명적인 손실을 초래합니다.
② 결정 경계(Decision Boundary)의 편향 해결
서포트 벡터 머신(SVM)이나 로지스틱 회귀와 같은 알고리즘은 손실 함수를 최소화하는 방향으로 경계를 설정합니다. 데이터가 불균형하면 경계선이 다수 클래스 쪽으로 밀려나게 되어, 소수 클래스를 단순한 노이즈로 간주하고 무시하는 경향이 생깁니다.
③ 평가 지표의 왜곡과 신뢰도 저하
불균형 데이터에서는 'Accuracy'라는 지표가 더 이상 의미를 갖지 못합니다. Precision(정밀도), Recall(재현율), F1-Score, 그리고 ROC-AUC와 같은 대안 지표를 사용해야 하며, 이를 해결하기 위한 데이터 전처리가 필수적으로 동반되어야 합니다.
2. 불균형 데이터 해결 기법별 핵심 차이 비교
불균형 문제를 해결하는 방식은 크게 데이터 수준, 알고리즘 수준, 평가 수준으로 나뉩니다. 아래 표를 통해 각각의 차이를 비교해 보세요.
| 해결 전략 | 주요 방법론 | 장점 | 단점 및 주의사항 |
|---|---|---|---|
| Over-sampling | SMOTE, ADASYN | 정보 손실이 없음, 소수 클래스 강조 | 과적합(Overfitting) 위험 존재 |
| Under-sampling | Random Under-sampling | 학습 속도 향상, 메모리 절약 | 중요한 정보 유실 가능성 높음 |
| Cost-sensitive | Class Weight 조정 | 데이터 변경 없이 모델링 가능 | 하이퍼파라미터 튜닝이 까다로움 |
| Metric Change | F1-Score, PR Curve | 실질적인 비즈니스 가치 평가 | 학습 자체를 개선하지는 않음 |
3. 개발자를 위한 실무 불균형 해결 Python Example 7선
imbalanced-learn 라이브러리와 scikit-learn을 활용하여 실무에서 즉시 적용 가능한 파이썬 코드 예제입니다.
Example 1: SMOTE를 활용한 합성 오버샘플링 해결
from imblearn.over_sampling import SMOTE
from collections import Counter
from sklearn.datasets import make_classification
# 1. 불균형 데이터 생성 (소수 클래스 10%)
X, y = make_classification(n_samples=1000, weights=[0.9, 0.1], random_state=42)
print(f"Original shape: {Counter(y)}")
# 2. SMOTE 적용
sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X, y)
print(f"Resampled shape: {Counter(y_res)}")
Example 2: Random Under-sampling을 통한 데이터 다이어트 방법
from imblearn.under_sampling import RandomUnderSampler
# 다수 클래스를 소수 클래스 개수에 맞춰 무작위 삭제
rus = RandomUnderSampler(random_state=42)
X_under, y_under = rus.fit_resample(X, y)
print(f"Under-sampled shape: {Counter(y_under)}")
Example 3: 모델 수준의 해결 - Class Weight 가중치 부여
from sklearn.ensemble import RandomForestClassifier
# 'balanced' 옵션은 클래스 빈도에 반비례하게 가중치를 자동 계산함
rf = RandomForestClassifier(class_weight='balanced', random_state=42)
rf.fit(X, y)
print("모델이 소수 클래스에 더 높은 가중치를 부여하여 학습 중입니다.")
Example 4: ADASYN(Adaptive Synthetic)으로 밀도 기반 오버샘플링
from imblearn.over_sampling import ADASYN
# 학습하기 어려운(데이터가 적은 곳에 위치한) 샘플 주변에 더 많은 데이터를 생성
ada = ADASYN(random_state=42)
X_ada, y_ada = ada.fit_resample(X, y)
print(f"ADASYN shape: {Counter(y_ada)}")
Example 5: 분류 임계값(Threshold) 이동을 통한 해결 전략
import numpy as np
# 예측 확률값 추출
y_probs = rf.predict_proba(X)[:, 1]
# 기본값 0.5가 아닌 0.3으로 낮춰 소수 클래스 탐지율(Recall) 향상
custom_threshold = 0.3
y_pred_custom = (y_probs >= custom_threshold).astype(int)
Example 6: Tomek Links를 활용한 클래스 경계 정제
from imblearn.under_sampling import TomekLinks
# 서로 다른 클래스끼리 아주 가깝게 붙어있는 노이즈 성 데이터를 제거하여 경계 명확화
tl = TomekLinks()
X_tl, y_tl = tl.fit_resample(X, y)
print(f"Tomek Links applied shape: {Counter(y_tl)}")
Example 7: 정밀도-재현율 곡선(PR Curve) 시각화 및 평가
import matplotlib.pyplot as plt
from sklearn.metrics import precision_recall_curve
precision, recall, _ = precision_recall_curve(y, y_probs)
plt.plot(recall, precision, marker='.', label='Random Forest')
plt.xlabel('Recall')
plt.ylabel('Precision')
plt.title('Precision-Recall Curve for Imbalanced Data')
plt.show()
4. 결론: 어떤 해결 방법을 선택해야 하는가?
데이터 불균형 해결의 황금률은 없습니다. 하지만 실무적인 가이드라인은 존재합니다. 데이터가 수만 건 이하로 적다면 정보 유실을 막기 위해 SMOTE와 같은 오버샘플링이 유리합니다. 반면 데이터가 수백만 건 이상으로 크다면 학습 속도를 위해 Under-sampling이나 모델의 Class Weight 조정이 훨씬 효율적입니다. 가장 중요한 것은 전처리 후 반드시 F1-Score나 ROC-AUC를 통해 성능을 검증하는 것입니다. 오늘 소개한 7가지 해결 방법을 조합하여 데이터 특성에 최적화된 파이프라인을 구축해 보시기 바랍니다.
5. 내용 출처 및 참고 문헌
- imbalanced-learn Documentation: "User Guide for Imbalanced Data" (imbalanced-learn.org)
- Scikit-learn User Guide: "Classification - Cost-sensitive learning"
- "SMOTE: Synthetic Minority Over-sampling Technique" by Chawla et al. (Journal of Artificial Intelligence Research)
- "Learning from Imbalanced Data" by Haibo He and Edwardo A. Garcia
'Artificial Intelligence > 60. Python' 카테고리의 다른 글
| [PYTHON] 모델 성능 예측의 핵심 : 훈련 데이터와 테스트 데이터를 나누는 3가지 방법과 해결 전략 (0) | 2026.04.07 |
|---|---|
| [PYTHON] Monkey Patching의 위험성 3가지 해결 방법과 유닛 테스트 활용의 차이 (0) | 2026.04.07 |
| [PYTHON] 라이브러리 개발을 위한 pyproject.toml 표준 활용 방법 5가지와 해결 전략의 차이 (0) | 2026.04.07 |
| [PYTHON] 객체 지향의 설계도 추상 클래스 활용 방법 4가지와 인터페이스 차이 해결 전략 (0) | 2026.04.07 |
| [PYTHON] 클래스 내부 인스턴스화 방법 3가지와 의존성 해결 및 합성 차이 (0) | 2026.04.07 |