불균형 데이터 처리
- 불균형 데이터: 클래스 간 데이터 포인트 수가 현저히 차이 나는 데이터셋
- 분류 문제에서 주로 발생
- 모델이 다수 클래스에 치우쳐 학습하면 소수 클래스의 예측 성능이 저하됨
- 정확도(accuracy) 같은 평가 지표가 모델 성능을 잘 나타내지 않을 수 있음
- 예: 사기 거래 탐지
- 100,000개의 거래 데이터 중 100개만 사기 거래라면 클래스 비율은 999:1
- 모든 거래를 정상 거래로 예측해도 99.9%의 정확도를 가짐
- 리샘플링(resampling)
- 불균형 데이터에 대한 일반적인 대처
- 데이터를 복제하거나 합성해 늘리는 오버샘플링
- 데이터를 삭제해 줄이는 언더샘플링
실습 준비
pip install imbalanced-learn
실습 데이터
from sklearn.datasets import make_classification
X, y = make_classification(
n_samples=1000,
n_features=2,
n_informative=2,
n_redundant=0,
n_repeated=0,
n_classes=2,
n_clusters_per_class=1,
weights=[0.02, 0.98],
class_sep=1.0,
flip_y=0.0,
random_state=0,
)
시각화
import matplotlib.pyplot as plt
plt.scatter(X[:, 0], X[:, 1], alpha=0.5, c=y)

선형 판별 분석
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
lda = LinearDiscriminantAnalysis()
lda.fit(X, y)
lda.score(X, y)
결과 시각화
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(
np.linspace(x_min, x_max, 200),
np.linspace(y_min, y_max, 200),
)
Z = lda.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.scatter(X[:, 0], X[:, 1], alpha=0.5, c=y, edgecolor="k")
plt.contourf(
xx,
yy,
Z,
alpha=0.3,
levels=np.linspace(Z.min(), Z.max(), 3),
zorder=-1,
)

오버샘플링
- 오버샘플링(oversampling): 소수 클래스의 데이터를 복제하거나 합성해 늘림
- 소수 클래스의 분류 성능이 향상
- 정보가 손실되지 않음
- 과적합 위험
- 훈련 시간 증가
랜덤 오버샘플링
from imblearn.over_sampling import RandomOverSampler
sampler = RandomOverSampler(random_state=0)
X_resampled, y_resampled = sampler.fit_resample(X, y)
lda = LinearDiscriminantAnalysis()
lda.fit(X_resampled, y_resampled)
plt.scatter(
X_resampled[:, 0],
X_resampled[:, 1],
alpha=0.5,
c=y_resampled,
edgecolor="k",
)

SMOTE
- SMOTE: Synthetic Minority Over-sampling Technique
- 랜덤 오버샘플링은 과적합 우려가 있음
- 가까운 두 사례에서 0에서 1 사이의 랜덤한 비율로 내분하는 새로운 점을 합성

SMOTE 실습
from imblearn.over_sampling import SMOTE
sampler = SMOTE(random_state=0)
X_resampled, y_resampled = sampler.fit_resample(X, y)

ADASYN
- ADASYN: Adaptive Synthetic
- SMOTE처럼 모든 데이터를 고르게 증가시키는 대신, 경계선 근방의 데이터를 더 많이 증가시킴
from imblearn.over_sampling import ADASYN
sampler = ADASYN(random_state=0)
X_resampled, y_resampled = sampler.fit_resample(X, y)

언더샘플링
- 언더샘플링(undersampling): 다수 클래스의 데이터를 삭제해 줄임
- 다수 클래스의 분류 성능이 하락할 수 있음
- 정보가 손실됨
- 과적합 위험이 낮음
- 훈련 시간 감소
랜덤 언더샘플링
from imblearn.under_sampling import RandomUnderSampler
rus = RandomUnderSampler(random_state=0)
X_resampled, y_resampled = rus.fit_resample(X, y)

NearMiss
from imblearn.under_sampling import NearMiss
sampler = NearMiss()
X_resampled, y_resampled = sampler.fit_resample(X, y)

Tomek Links
from imblearn.under_sampling import TomekLinks
sampler = TomekLinks()
X_resampled, y_resampled = sampler.fit_resample(X, y)

