본문 바로가기

파이썬 (Python)/머신러닝 (Machine Learning)

불균형자료 처리 (Imbalanced data)

머신러닝의 목적이 분류일 때, 클래스 비율의 차이가 너무 크면 majority에만 맞추려고 하는 문제가 생길 수 있다. 

이렇게 하면 과대적합의 문제가 생길 수 있다. 

 

이를 해결하기 위해 인위적으로 클래스의 비율을 맞추어 줄 수 있는데, 크게 과소표집과 과대표집 두 가지 방법이 있다.

- 일반적으로 과대표집이 과소표집보다 통계적으로 유용하다. 과소표집은 표본의 수를 줄이기 때문

 

1. 과소표집 (Undersampling)

: major 클래스의 표본을 임의로 제거하여 minor 클래스에 맞추어주기

 

2. 과대표집 (Oversampling)

: minor 클래스의 표본을 복제하여 major 클래스에 맞추기

 

(1) SMOTE (Synthetic Minority Oversampling Technique, 합성소수표집법)

예를 들어 설명해보도록 하겠다.

 

소수 클래스에 속하는 x가 20개 (x1~x20), 다수 클래스에 속하는 x가 100개 (x21~x120) 있다고 하자. 

 

소수 클래스에 속하는 xi 중 하나를 잡고 k-nearest neighbors 를 포함하는 set, Si를 생성한다.

예를 들어, x1를 잡고 k=5이면 x1을 포함하여 xi 5개가 포함되어 있는 set을 만들 수 있다.

 

해당 set인 Si에서 "랜덤으로" xk 하나를 뽑아 아래와 같은 식으로 새로운 관측치, x_syn를 생성한다.

더보기

x_syn = xi + lambda(xk - xi)

 

이 때, lambda 는 Uniform(0, 1)에서 "랜덤으로" 추출한 임의의 값이다. 이는 noise 역할을 한다고 생각하면 된다. 

 

이렇게 x1~x20 에 대해 5번씩 x_syn을 만들어주면 소수 클래스의 개수가 다수 클래스의 개수와 같아지므로 balanced data 가 만들어진다.

 

파이썬 코드는 다음과 같다.

X, y는 기존의 데이터이고 oversampling한 결과가 X_res, y_res 이다.

from imblearn.over_sampling import SMOTE
sm = SMOTE(random_state=42)
X_res, y_res = sm.fit_resample(X, y)

from collections import Counter
print('Resampled dataset shape %s' % Counter(y_res))

 

print의 결과는 ({클래스: 개수, 클래스: 개수, 클래스: 개수}) 로 나온다.

SMOTE 시행 이후 모든 데이터 값의 개수가 같음을 볼 수 있다.

 

(2) ADASYN (Adaptive Synthetic Sampling Method, 조절합성표집법)

SMOTE 와 거의 비슷하다.

 

xi에 대응하는 x_syn의 개수를 Si 안에 들어있는 다수 클래스의 표본 수(k-neighbors)에 비례하도록 추출한다는 차이만 있다.

 

파이썬 코드는 다음과 같다.

X, y는 기존의 데이터이고 oversampling한 결과가 X_syn, y_syn 이다.

from imblearn.over_sampling import ADASYN
ada=ADASYN(random_state=0)
X_syn,y_syn=ada.fit_resample(X,y)

from collections import Counter
print('Resampled dataset shape from ADASYN %s' % Counter(y_syn))

 

print의 결과는 마찬가지로 ({클래스: 개수, 클래스: 개수, 클래스: 개수}) 로 나온다.

단, ADASYN은 SMOTE와는 다르게 k-neighbors안에 있는 다수 클래스의 표본 수에 비례하도록 oversampling하기 때문에 클래스의 개수가 다를 수 있음에 유의하자.

 


+) SMOTE와 ADASYN을 동시에 불러올 수도 있다.

from imblearn.over_sampling import SMOTE, ADASYN

 



만일 toy example이 필요하다면 make_classification으로 아래와 같이 불균형데이터 X, y를 만들 수 있다.

from sklearn.datasets import make_classification
X, y = make_classification(n_classes=3, weights=[0.03, 0.07,0.9],n_features=10, 
                           n_clusters_per_class=1, n_samples=2000, random_state=10)