📚 Imbalanced Dataset
✔ 데이터 불균형 : 이진 분류 문제에서 특정 클래스의 관측치가 상대적으로 더 많은 경우.
이러한 경우에는 majority에 대해서는 예측을 잘 진행할 수 있으나, minority class에 대해서는 예측 성능이 떨어진다.
✔ 예시 : fraud detection, 질병 예측, 신용불량자 예측, 기기 고장 예측, spam detection
→ 이러한 task는 minority class를 정확하게 예측하는 것이 더 중요하다. 하지만 대부분의 데이터에는 majority class의 샘플이 훨씬 많다.
📌사용하는 평가 지표
데이터 불균형이 심할 경우에 평가 지표로 accuracy를 사용하는 것은 바람직하지 않다. 전체 데이터에서 majority class가 90%인 경우에, 모두 majority class로 분류하기만 해도 accuracy=90%를 달성할 수 있다.
따라서 minority class에 대한 precision, recall, AUC 지표를 살펴보는 것이 중요하다.
데이터 불균형을 해결할 수 있는 방법들은 크게 1.resampling 2. cost sensitive learning이 있다.
📚 데이터 불균형 해소 : Resampling 방법
① minority class에 대한 데이터를 더 많이 수집한다.
→ 현실적으로 어려운 경우가 많다...
② Under Sampling
• majority class 샘플을 삭제해서 개수를 맞추는 방법
• 데이터가 줄어들기 때문에 정보 손실 발생
• 데이터가 많은 경우에 사용할 수 있다.
③ Over Sampling
• 일반적으로 더 많이 사용된다.
• 데이터가 많지 않은 경우에 사용
• overfitting 가능성이 증가한다.
특히 오버샘플링 방법으로 SMOTE가 많이 사용된다. 대표적인 SMOTE 기법들을 살펴보자면 다음과 같다.
✅ SMOTE : Synthetic Minority Oversampling Technique
학습 데이터의 minority class의 정보를 활용해서 KNN기반으로 새로운 데이터 샘플을 생성하는 방법.
📌작동방식
1.임의로 minority class 샘플 하나를 선택한다.
2. minority class 중에서 해당 관측치와 유사도가 가장 큰 관측치 K 개를 선택한다.
3. 관측치들 간의 직선의 거리(difference)를 계산한다.
4. 랜덤하게 선택된 0~1 사이의 값을 곱한다
5. 이를 이용해서 직선 위에서 새로운 data point를 생성한다.
📌한계점
1. 새로운 데이터 포인트가 기존의 minority class 관측치들 사이의 직선 위에서만 생성된다. 따라서 실제 데이터의 특성을 온전하게 반영하지 못한다.
2. 데이터 샘플들의 노이즈가 증가할 수 있다.
빨간색이 소수 클래스일 때 SMOTE는 직선 상에서 새로운 데이터를 생성한다. 이런 경우에, 붉은색의 decision boundary 아래에서 생성되는 데이터 포인트는 확실하게 빨간색 클래스라고 볼 수 있다.
반면, decision boundary 위에 있는 경우에는 majority class 샘플들과도 유사하기 때문에, 데이터의 특성에 majority/minority의 특성이 혼합된다.
📌Example
import imblearn
from sklearn.datasets import make_classification
# 임의 데이터 생성
X, y = make_classification(n_samples=10000, n_features=2, n_redundant=0,
n_clusters_per_class=1, weights=[0.99], flip_y=0, random_state=1) #99가 0값을 가지도록 생성
#클래스 수 파악
from collections import Counter
counter = Counter(y)
print(counter)
임의의 불균형 데이터셋을 생성하고 각 클래스의 수를 확인한다.
import matplotlib.pyplot as plt
from numpy import where
for label, _ in counter.items():
row_ix = where(y == label)[0]
plt.scatter(X[row_ix, 0], X[row_ix, 1], label=str(label))
plt.legend()
plt.show()
불균형 데이터셋을 시각화한 결과
from imblearn.over_sampling import SMOTE
smt = SMOTE()
X_new, y_new = smt.fit_resample(X, y)
#비율 확인
counter = Counter(y_new)
print(counter)
#시각화
for label, _ in counter.items():
row_ix = where(y_new == label)[0]
plt.scatter(X_new[row_ix, 0], X_new[row_ix, 1], label=str(label))
plt.legend()
plt.show()
SMOTE를 사용하면 기본적으로 각 클래스의 비율을 1대1로 맞추는 것을 확인할 수 있다. 시각화 결과를 살펴보면 직선 형태가 나타나는 것을 알 수 있다. 이는 SMOTE가 기본적으로 minority class point간의 직선의 거리 상에서 새로운 synthetic point를 생성하기 때문이다.
✅ Border-line SMOTE
Han, H., Wang, W. Y., & Mao, B. H. (2005, August). Borderline-SMOTE: a new over-sampling method in imbalanced data sets learning. In International conference on intelligent computing (pp. 878-887). Springer, Berlin, Heidelberg.
모든 minority data point가 아니라 Border-line 근처에 있는 관측치들에 대해서 집중적으로 오버샘플링을 실시하는 방법. border line 근처에 있을수록 상대적으로 분류하기가 힘들기 때문에 이러한 데이터 샘플을 추가로 생성하고 학습하여 모델의 성능을 향상시키는 방법.
1. minority class 관측치들에 대해서 class 구분 없이 모두 nearest neighbor를 뽑아냄
2. nearest neighbor 중에서 50% 이상이 majority class인 경우에 이 관측치들을 Danger set(분류하기 어려운 샘플들)이라고 함
3. Danger set에 존재하는 minority class points에 대하여 다시 neareste neighbor를 계산한다.
4. 아래 식을 이용해서 synthetic point 생성
📌Example
from imblearn.over_sampling import BorderlineSMOTE
bdsmt = BorderlineSMOTE()
X_border, y_border = bdsmt.fit_resample(X, y)
#비율 카운트
counter = Counter(y_border)
print(counter)
#시각화
for label, _ in counter.items():
row_ix = where(y_new == label)[0]
plt.scatter(X_border[row_ix, 0], X_border[row_ix, 1], label=str(label))
plt.legend()
plt.show()
✅ ADASYN : Adaptive Synthetic Sampling
He, H., Bai, Y., Garcia, E. A., & Li, S. (2008, June). ADASYN: Adaptive synthetic sampling approach for imbalanced learning. In 2008 IEEE international joint conference on neural networks (IEEE world congress on computational intelligence) (pp. 1322-1328). IEEE.
Minority class 관측치에 대해서 주변에 majority class 관측치가 많을 수록 더 많이 oversampling 하는 방법. Border-line SMOTE는 보더라인에 가까우면 동일하게 샘플링을 많이 하지만, ADASYN은 주변 majority class(즉, 거리)에 따라서 샘플링 수가 달라진다.
→ Minority class 관측치에 대해서 주변에 majority class 관측치가 많을 수록 분류가 더 어려운 관측치라고 간주
위 그림에서 빨간색이 소수 클래스일 때, 1/2/3번 각각의 샘플의 주변을 살펴봤을 때, 파란색(다수 클래스)이 많은 관측치는 3번이다. 3번은 소수/다수를 분류하기 어려운 관측치이기 때문에, 이를 더 잘 학습하기 위해서 3번에 대해서 샘플링을 더 많이 실시한다.
Boder line, ADASYN 방식 모두 기본 SMOTE와 동일하게 원본 데이터에서 minority 클래스를 증가시킴으로써 데이터의 노이즈가 증가한다는 단점이 있다는 것은 동일하므로 학습 시 유의해야 한다.
📌Example
from imblearn.over_sampling import ADASYN
adasyn = ADASYN()
X_ads, y_ads = adasyn.fit_resample(X, y)
counter = Counter(y_ads)
print(counter)
for label, _ in counter.items():
row_ix = where(y_ads == label)[0]
pyplot.scatter(X_ads[row_ix, 0], X_ads[row_ix, 1], label=str(label))
pyplot.legend()
pyplot.show()
📚 데이터 불균형 해소 : Cost sensitive training (=Penalized Model)
데이터 불균형 문제를 해결하기 위해서 비용함수를 계산할 때 소수 클래스에 대해서 더 큰 가중치를 부여해서 학습할 수 있다.
위와 같이 일반적인 이진 분류의 크로스 엔트로피 비용함수가 있을 때,
w1, w0이라는 가중치를 각각의 클래스에 대해서 곱할 수 있다. 만약 1이 소수 클래스인 경우에는 W1 값을 크게 해서 가중치를 부여하면, 소수 클래스를 더 잘 학습할 수 있다.
가중치의 값은 하이퍼 파라미터이기 때문에 이리저리 테스트를 해봐야 하지만, 일반적으로 majority : minority 비율의 역수를 사용한다.
✅ 코드 예시
weights = {0:1.0, 1:2.0}
lr_cost_sensitive = LogisticRegression(penalty='none', class_weight=weights)
lr_cost_sensitive.fit(X_train1, y_train1)
로지스틱 회귀로 이진분류를 진행한다고 할 때, 모델을 정의하면서 weights 파라미터를 추가할 수 있다.
📚 Reference
이상엽, 연세대학교 언론홍보영상학부 부교수, 22-1학기 기계학습 이론과 실습
https:// github.com / minoue -xx/Oversampling-Imbalanced-Data
'머신러닝, 딥러닝 > 머신러닝' 카테고리의 다른 글
영화리뷰 감성분석 (Sentiment Analysis) (0) | 2022.05.15 |
---|---|
TF-IDF (Term Frequency - Inverse Document Frequency) (0) | 2022.05.15 |
[머신러닝] 하이퍼 파라미터 튜닝, Cross validation (0) | 2022.04.18 |
[머신러닝] Confusion Matrix, ROC Curve (0) | 2022.04.11 |
[머신러닝] Logistic Regression (0) | 2022.04.11 |
댓글