상세 컨텐츠

본문 제목

[ML] Classification - SMOTE

machine learning

by ~지우~ 2022. 12. 16. 09:16

본문

728x90

SMOTE

SMOTE는 불균형 데이터 세트를 사용할 때 발생하는 문제를 해결하는 머신러닝 기법이다. 불균형 데이터는 관측된 빈도가 범주형 변수의 서로 다른 가능한 값에 걸쳐 매우 다른 데이터이다.

아래 그림은 불균형 데이터의 예시이다.

위 그림으로 예를 들어보면, 30명의 웹사이트 방문자 중 20명은 스키어이고 10명은 등산가이다. 우리는 방문객의 구매 여부를 예측할 수 있는 기계 학습 모델을 구축하려고 한다. "안 산다"를 예측하는 모델은 30건 중 28건이 맞다. 이 모델은 93%의 정확도를 갖는다. 불균형 데이터를 사용하여, 우리는 실제로는 쓸모가 없지만 매우 정확하게 보이는 모델을 만들게된다.

이러한 불균형 데이터의 문제를 해결하기 위한 3가지 방법이 있다.

1. Undersampling
데이터 세트의 더 큰 부분에서 많은 데이터를 임의로 삭제합니다.
 장점
매우 단순하다
데이터 세트가 크고 불균형이 크지 않은 경우(예: 40% 대 60%), 이는 효과적일 수 있다.
 단점
실제 데이터를 삭제하는 것은 위험하다. (너무 많이 삭제하면 데이터 세트가 무의미해질 수 있다.)

 

 

2. Oversampling
데이터 세트에 가장 적게 있는 데이터의 복제를 만들고 해당 복제를 데이터 세트에 추가
단점
실제가 아닌 데이터를 생성해서 모델에 잘못된 정보를 도입한다.

 

 

3. Data Augmentation
정확한 복제품을 만드는 것보다, 약간 변화를 주어서 데이터를 추가

 

 

-SMOTE Algorithm

1. 소수 클래스에서 임의의 데이터 점 집합(즉, 특징 벡터)을 그린다.
2. 집합의 데이터 점에 대해 k개의 가장 가까운 이웃을 식별한다.
3. 이러한 k개의 이웃 중 하나를 선택하고 현재 데이터 포인트와 선택한 이웃 사이의 벡터(즉, 선 세그먼트)를 식별한다.
4. 벡터에 0과 1 사이의 난수를 곱한다.
5. 합성 데이터 포인트를 얻으려면 이를 현재 데이터 세트에 추가한다.
6. 선택한 세트의 각 데이터 포인트에 대해 2~5단계를 반복한다.

 

-Influence of SMOTE on Precision and Recall

 우리가 강한 계급 불균형을 가지고 있을 때, 우리는 한 계급에서 매우 적은 경우를 가지고 있고, 그 결과 모델은 그 계급을 거의 예측하지 못한다.
SMOTE를 사용하여 False Positive을 증가시키는 대가로 False Negative을 줄이기 위해 모델을 수정할 수 있다.
SMOTE를 사용한 결과는 일반적으로 정밀도가 떨어지는 대가로 recall이 증가한다.
이것은 우리가 소수 계층에 대한 예측을 더 추가할 것이라는 것을 의미한다. 

 

-SMOTE in Python

# Import the data import pandas as pd
data = pd.read_csv('https://raw.githubusercontent.com/JoosKor stanje/datasets/main/sales_data.csv’)
data.head()

# Show the class imbalance between buyers and non-buyers
data.pivot_table(index='buy', aggfunc='size').plot(kind='bar')

# Create a stratified train/test split. 
# Test set will be 30% of the data.
# Class distribution will be equal for train/test for the original data
from sklearn.model_selection import train_test_split 
train, test = train_test_split(data, test_size = 0.3,stratify=data.buy)
train.pivot_table(index='buy', aggfunc='size').plot(kind='bar', title='Verify that class distributuion in train is same as input data')

from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(test['buy'], preds).ravel()
print('True negatives: ', tn, '\nFalse positives: ', fp, '\nFalse negatives: ', fn, '\nTrue Positives: ', tp)

from sklearn.metrics import classification_report
print(classification_report(test['buy'], preds))

from imblearn.over_sampling import SMOTE
X_resampled, y_resampled = SMOTE().fit_resample(train[['time_on_page','pages_viewed', 'interest_ski', 'interest_climb']], train['buy'])

pd.Series(y_resampled).value_counts().plot(kind='bar', title='Class distribution after appying SMOTE', xlabel='buy’)

tn, fp, fn, tp = confusion_matrix(test['buy'], preds2).ravel()
print('True negatives: ', tn, '\nFalse positives: ', fp, '\nFalse negatives: ', fn, '\nTrue positives: ', tp)

print(classification_report(test['buy'], preds2))
728x90

관련글 더보기

댓글 영역