TIL/머신러닝

11/28 월 머신러닝 "불균형 데이터 SMOTE" -2

monawa 2022. 11. 30.
728x90

SMOTE

실제로 데이터를 탐색해보면 불균형한 데이터가 매우 많습니다

EX)  불량품과 정상제품 / 1년중 눈이 오는 날과 오지않는날 / 10년간 지진이 발생한경우/ 암검진 대상중 암에 걸린환자와 아닌환자   

 

이렇듯 균형있게 분포되있는 분류문제가 더 드뭅니다 

이러한 불균형한 데이터를 해결하는 방법으로는Resampling 로서 under-sampling over-sampling이 있습니다

주요 골자는 두값의 비율을 비슷 하게 맞춰 줍니다

under-sampling over-sampling
 더 값이 많은 쪽에서 일부만 샘플링하여 비율을 맞춰주는 방법 더 값이 적은 쪽에서 값을 늘려 비율을 맞춰준 방법
구현이 쉽지만
전체 데이터가 줄어
머신러닝 모델 성능이 떨어질 우려가 있습니다
어떻게 없던 값을 만들어야 하는지에 대한 어려움이 있습니다

출처 : https://www.kaggle.com/rafjaa/resampling-strategies-for-imbalanced-datasets

실습

0804 credit_card_SMOTE

 

countplot으로 두클래스의 분포 비교확인

sns.countplot(data=df,x="Class")
countplot으로 두클래스의 분포 비교확인


독립변수(문제)와 종속변수(정답) 분리

 

input으로 들어갈 X와 기대값인 y를 분리합니다.

label_name = "Class"

X에는 예측할 값인 "Class"를 제외한 값이 들어가야 합니다.
X= df.drop(columns=label_name)

y에는 예측할 값인 "Class"만 들어가야 합니다.
y = df[label_name]

잘분리됬는지 확인합니다
X.shape, y.shape
((284807, 30), (284807,))

 

 

train_test_split

stratify=y

train_test_split을 이용하여  X와 y값을 학습용 데이터와 검증용 데이터로 나눕니다.
from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test에 값을 반환받습니다.
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size=0.2,random_state=42)

잘 나누어졌는지 확인해 봅니다 
X_train.shape, X_test.shape, y_train.shape, y_test.shape
((227845, 30), (56962, 30), (227845,), (56962,))
트레인과 테스트가 비슷한 비율로 되어있는지 확인
y_train.value_counts(1) ,y_test.value_counts(1)
(0    0.998271
 1    0.001729
 Name: Class, dtype: float64, 
 0    0.99828
 1    0.00172
 Name: Class, dtype: float64)

from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(random_state= 42)
model
모델은 만들고
학습시킨다
model.fit(X_train,y_train)

 

y_pred_proba = model.predict_proba(X_test)
print(y_pred_proba.shape)
y_pred_proba[:5]
  • predict_proba 는 확률 값을 예측합니다.
  • 각 클래스마다의 확률을 예측합니다.
  • 0, 1 일 때 각각의 확률을 의미합니다.
  • [0.5, 0.5], [0.3, 0.7], [0.7, 0.3]이렇게 나오기도 클래스가 여러 개 일 때 이런 확률을 사용해서 예측하기도 합니다. 
(56962, 2)
array([[0., 1.],
       [1., 0.],
       [1., 0.],
       [1., 0.],
       [1., 0.]])

 

 

확률이기떄문에 int 0과 1이 아닌 float로 예측했습니다

np.unique(y_pred_proba)
array([0., 1.])
 

 

정확도
(y_test == y_pred).mean()
0.9990519995786665
데이터가 많기 때문에 Cross validation을 하면 시간이 좀 오래 걸리게 됩니다
그러므로 Hold-Out-validation 으로 test 와 예측값을 비교합니다.

 

pd.crosstab(y_test, y_pred)

crosstab : 범주형 데이터 2개를 비교분석할 때 유용한 교차분석표 

 

혼동행렬 confusion_matrix

from sklearn.metrics import confusion_matrix

cf = confusion_matrix(y_test, y_pred)
cf
array([[56830,    34],
       [   20,    78]])
실제 결과 
예측된 결과    거짓 0 참 1
거짓 
0
TN
예측 거짓 / 실제 거짓 
아닌 것을 올바르게 틀리다고 예측함
FP
예측 참 / 실제 거짓
1종오류 (남자가 임신)
아닌 것을 올바르지 않게 맞다고 예측함

1
FN 
예측 거짓 /실제 참
2종오류
맞는 것을 올바르지 않게 틀리다고 예측함
TP
예측 참 / 실제 참 
맞는 것을 올바르게 맞다고 예측함

 

classification_report(분류 성능평가) 
from sklearn.metrics import classification_report

print(classification_report(y_test, y_pred))
               precision    recall  f1-score   support

           0       1.00      1.00      1.00     56864
           1       0.70      0.80      0.74        98

    accuracy                           1.00     56962
   macro avg       0.85      0.90      0.87     56962
weighted avg       1.00      1.00      1.00     56962

precision  정밀도

예측모델이 Negative요소로 잘못 분류되도 상관이 없을때 주로 사용하는 측정값이다

recall 재현율

 Negative요소를 고려하기때문에 특정 클래스가 예측모델이 Negative로 잘못분류되면 안되는 상황에서 주로 사용된다

f1-score 정밀도와 재현율의 가중평균

accuracy 정확도

 

 

이때 신용사기를 측정하기위한 지표로서는 precision,recall 중에서 recall이 적정합니다 

(실제 Positive 양성인 데이터 예측을 Negative 음성으로 잘못 판단하면 업무상 큰 영향이 발생하는 경우)

#  precision_score, recall_score
from sklearn.metrics import precision_score, recall_score
precision_score(y_test, y_pred), recall_score(y_test, y_pred)

 

(0.6964285714285714, 0.7959183673469388)

 


언더 셈플링

y.value_counts()

0    284315
1       492
Name: Class, dtype: int64

1 인데이터가 492개 이기 때문에 0인 데이터를 랜덤하게 492개 추출하면 언더샘플링 입니다.

df_0 = df[df["Class"] == 0].sample(492)
df_1 = df[df["Class"] == 1]
df_0.shape, df_1.shape
((492, 31), (492, 31))

 

df_under=pd.concat([df_0,df_1])
df_under["Class"].value_counts()
0    492
1    492
Name: Class, dtype: int64

 

오버 샘플링

SMOTE는 Synthetic Minority Over-sampling Technique의 약자로 합성 소수자 오버샘플링 기법입니다.
from imblearn.over_sampling import SMOTE

sm = SMOTE(random_state=42)
X_resample, y_resample = sm.fit_resample(X, y)

smote를 하여  X_resample, y_resample를 새로 만듭니다 

y.value_counts()

0    284315
1       492
Name: Class, dtype: int64

기존  y값의 구성수 

y_resample.value_counts()

0    284315
1    284315
Name: Class, dtype: int64

오버 샘플링을 한후 값의 수

 

데이터 분리 

resample X와 y값을 학습용 데이터와 검증용 데이터로 나눕니다.(train_test_split)
X_train, X_test, y_train, y_test = train_test_split(
    X_resample, y_resample,
    test_size=0.2, random_state=42,
    stratify=y_resample)
    
X_train, X_test, y_train, y_test에 값을 반환받습니다.
X_train.shape, X_test.shape, y_train.shape, y_test.shape

resample X와 y값을 학습용 데이터와 검증용 데이터로 나눕니다.(train_test_split)

random_state는 난수 값을 고정하는 역할을 하는 파라미터입니다.
 
X_train, X_test, y_train, y_test에 값을 반환받습니다.
 

 

DecisionTreeClassifier

model = DecisionTreeClassifier()
model​
 
 
model.fit(X_train, y_train)​
 
y_pred_over = model.predict(X_test)
y_pred_over[:5]
 
array([1, 1, 0, 1, 1])
 
 
SMOTE를 적용 전과 후를 비교해보기 위해서 해당 실습을 진행하고 있습니다!!
 
 
np.unique(y_pred_over)​
 
array([0, 1])​
 
 
예측 결과의 고유한 값의 개수를 포함하는 Series를 반환합니다.
(y_test == y_pred_over).mean()​
 
정확도 : 0.9986722473313051
 
classification_report
print(classification_report(y_test, y_pred_over))
 
반올림한 결과로 100프로로 나왔습니다  이는 밑에 컨퓨전메트릭스로 틀린값이 있는걸 확인할수잇습니다 
 
 
confusion_matrix(y_test, y_pred_over)
 
 
f1_score(y_test, y_pred_over)
0.9982865427705285
 
# precision 예측값 기준 => 1종 오류
# recall 실제값 기준 => 2종 오류
precision_score(y_test, y_pred_over), recall_score(y_test, y_pred_over)

 

(0.9975940430613607, 0.9989800045723933)
 
 
precision_score(y_test, y_pred), 
recall_score(y_test, y_pred)
precision_score(y_test, y_pred_over), 
recall_score(y_test, y_pred_over)
(0.6964285714285714, 0.7959183673469388) (0.9975940430613607, 0.9989800045723933)
  • SMOTE 를 사용한 오버샘플링 데이터로 모델을 만들어 예측한 결과를 비교했습니다.
  • 샘플링을 사용하지 않고 데이터를 나눠 학습했을 때와 비교해서 f1_score, precision, recall 값이 모두 높아졌음을 알 수 있습니다.
  • 정답 클래스가 불균형하면 학습을 제대로 하기 어렵기 때문에 오버샘플링이나 언더샘플링으로 정답 클래스를 비슷하게 만들어 주면 좀 더 나은 성능을 냅니다.

 
 
 
 
기타 알게된점

코랩에 파일 업로드해서 불러올떄

zip은 완전히다 업로드되어야 로드가 가능합니다

csv 는 행기반으로 저장되어 있기 때문에 일부만 업로드 되더라도 불러올 수 있습니다.

이떄 얼마나 업로드 됬는지 확인하는 방법이 저 오른쪽에 있는 오렌지색 원으로 업로드현황을 확인할수있습니다

 

아니면 구글드라이브에 업로드후 경로 불러오면 매번 올릴필요 없습니다

 


오답노트

확률값으로 예측한 결과가 아래와 같은 형태일 때 가장 큰 값을 갖는 인덱스를 반환하는 것은 무엇일까요?

np.argmax(y_pred, axis=1)

이는 딥러닝에도 사용합니다 !

 

단층 퍼셉트론으로 구현하지 못하는 아래 그림과 같은 논리회로를 무엇이라고 하는지 골라주세요.

XOR 게이트

 

XOR 문제를 해결한 방법?

다중 퍼셉트론


 

참고자료 :

멋쟁이 사자처럼 AI School 7기 수업내용

https://jaeyung1001.tistory.com/252

728x90

댓글