SMOTE
실제로 데이터를 탐색해보면 불균형한 데이터가 매우 많습니다
EX) 불량품과 정상제품 / 1년중 눈이 오는 날과 오지않는날 / 10년간 지진이 발생한경우/ 암검진 대상중 암에 걸린환자와 아닌환자
이렇듯 균형있게 분포되있는 분류문제가 더 드뭅니다
이러한 불균형한 데이터를 해결하는 방법으로는Resampling 로서 under-sampling과 over-sampling이 있습니다
주요 골자는 두값의 비율을 비슷 하게 맞춰 줍니다
under-sampling | over-sampling |
더 값이 많은 쪽에서 일부만 샘플링하여 비율을 맞춰주는 방법 | 더 값이 적은 쪽에서 값을 늘려 비율을 맞춰준 방법 |
구현이 쉽지만 전체 데이터가 줄어 머신러닝 모델 성능이 떨어질 우려가 있습니다 |
어떻게 없던 값을 만들어야 하는지에 대한 어려움이 있습니다 |
실습
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
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 예측 참 / 실제 참 맞는 것을 올바르게 맞다고 예측함 |
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
오버 샘플링
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)
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])
np.unique(y_pred_over)
array([0, 1])
(y_test == y_pred_over).mean()
print(classification_report(y_test, y_pred_over))
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기 수업내용
'TIL > 머신러닝' 카테고리의 다른 글
11/28 월 머신러닝 불균형 데이터 SMOTE -1 (혼동행렬) (0) | 2022.11.29 |
---|---|
11.23일 수업 TIL Gradient Boosting Machine (XGBoost, lightGBM,CatBoost ) (0) | 2022.11.26 |
11.24일 얕은복사,깊은복사 / 혼동행렬 (0) | 2022.11.24 |
11.22 오후 Learning rate ,bgd, SGD,모멘텀 (2) | 2022.11.22 |
11.22 오전 머신러닝 최적화 ,경사하강법 (1) | 2022.11.22 |
댓글