이번 시간에는 지금까지 다룬 다양한 평가 지표를 가지고
피마 인디언 당뇨병 예측을 진행해보고
성능을 평가해보도록 하겠습니다.
지금까지 배운걸 실제로 적용해보는 것이니
가벼운 마음으로 한번 쓱 보면 될 것 같습니다.
해당 내용은 '파이썬 머신러닝 완벽 가이드'를 정리한 내용입니다.
먼저 '피마 인디언 데이터셋'을 분석해보도록 하겠습니다.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, precision_score, recall_score, roc_auc_score
from sklearn.metrics import f1_score, confusion_matrix, precision_recall_curve, roc_curve
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
diabetes_data = pd.read_csv('diabetes.csv')
print(diabetes_data['Outcome'].value_counts())
diabetes_data.head(3)
0 500
1 268
Name: Outcome, dtype: int64
diabetes_data.info()
위와 같이 데이터셋에서는 Null 값이 따로 존재하지 않기 때문에 그대로 한번 학습을 진행해보도록 하겠습니다.
X = diabetes_data.iloc[:,:-1]
y = diabetes_data.iloc[:,-1]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.2, random_state = 156, stratify=y)
lr_clf=LogisticRegression()
lr_clf.fit(X_train , y_train)
pred = lr_clf.predict(X_test)
pred_proba = lr_clf.predict_proba(X_test)[:,1]
get_clf_eval(y_test , pred, pred_proba) # 이전에 사용한 함수를 그대로 사용했습니다.
오차 행렬
[[88 12]
[23 31]]
정확도: 0.7727, 정밀도: 0.7209, 재현율: 0.5741, F1: 0.6392, AUC:0.7919
Null 값 처리 없이 학습을 진행하였는데 재현율이 매우 안 좋은 것을 볼 수 있습니다.( 해당 데이터셋은 Negative가 60%에 달하기 때문에 재현율에 초점을 맞추도록 하겠습니다.)
따라서 데이터셋을 다시 확인해보도록 하겠습니다.
pred_proba_c1 = lr_clf.predict_proba(X_test)[:, 1]
precision_recall_curve_plot(y_test, pred_proba_c1)
ROC 곡선을 확인해보니 0.7 이후 급격하게 정밀도가 낮아짐을 알 수 있습니다.
diabetes_data.describe()
데이터셋을 다시 확인해보면 포도당 수치가 0라는 말도 안 되는 데이터 값이 존재함을 알 수 있습니다. 따라서 0 값을 평균으로 처리해주도록 하겠습니다.
# 0값을 검사할 피처명 리스트 객체 설정
zero_features = ['Glucose', 'BloodPressure','SkinThickness','Insulin','BMI']
# 전체 데이터 건수
total_count = diabetes_data['Glucose'].count()
# 피처별로 반복 하면서 데이터 값이 0 인 데이터 건수 추출하고, 퍼센트 계산
for feature in zero_features:
zero_count = diabetes_data[diabetes_data[feature] == 0][feature].count()
print('{0} 0 건수는 {1}, 퍼센트는 {2:.2f} %'.format(feature, zero_count, 100*zero_count/total_count))
Glucose 0 건수는 5, 퍼센트는 0.65 %
BloodPressure 0 건수는 35, 퍼센트는 4.56 %
SkinThickness 0 건수는 227, 퍼센트는 29.56 %
Insulin 0 건수는 374, 퍼센트는 48.70 %
BMI 0 건수는 11, 퍼센트는 1.43 %
# zero_features 리스트 내부에 저장된 개별 피처들에 대해서 0값을 평균 값으로 대체
diabetes_data[zero_features]=diabetes_data[zero_features].replace(0, diabetes_data[zero_features].mean())
X = diabetes_data.iloc[:, :-1]
y = diabetes_data.iloc[:, -1]
# StandardScaler 클래스를 이용해 피처 데이터 세트에 일괄적으로 스케일링 적용
scaler = StandardScaler( )
X_scaled = scaler.fit_transform(X)
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size = 0.2, random_state = 156, stratify=y)
# 로지스틱 회귀로 학습, 예측 및 평가 수행.
lr_clf = LogisticRegression()
lr_clf.fit(X_train , y_train)
pred = lr_clf.predict(X_test)
# roc_auc_score 수정에 따른 추가
pred_proba = lr_clf.predict_proba(X_test)[:, 1]
get_clf_eval(y_test , pred, pred_proba)
오차 행렬
[[90 10]
[21 33]]
정확도: 0.7987, 정밀도: 0.7674, 재현율: 0.6111, F1: 0.6804, AUC:0.8433
0 값을 처리해준 뒤 정규화를 한 후 다시 학습을 진행하니 전반적인 성능이 소폭 상승했음을 볼 수 있습니다. 이제 임계값을 조절해주도록 하겠습니다.
from sklearn.preprocessing import Binarizer
def get_eval_by_threshold(y_test , pred_proba_c1, thresholds):
# thresholds 리스트 객체내의 값을 차례로 iteration하면서 Evaluation 수행.
for custom_threshold in thresholds:
binarizer = Binarizer(threshold=custom_threshold).fit(pred_proba_c1)
custom_predict = binarizer.transform(pred_proba_c1)
print('임곗값:',custom_threshold)
# roc_auc_score 관련 수정
get_clf_eval(y_test , custom_predict, pred_proba_c1)
thresholds = [0.3 , 0.33 ,0.36,0.39, 0.42 , 0.45 ,0.48, 0.50]
pred_proba = lr_clf.predict_proba(X_test)
get_eval_by_threshold(y_test, pred_proba[:,1].reshape(-1,1), thresholds )
임곗값: 0.3
오차 행렬
[[67 33]
[11 43]]
정확도: 0.7143, 정밀도: 0.5658, 재현율: 0.7963, F1: 0.6615, AUC:0.8433
임곗값: 0.33
오차 행렬
[[72 28]
[12 42]]
정확도: 0.7403, 정밀도: 0.6000, 재현율: 0.7778, F1: 0.6774, AUC:0.8433
임곗값: 0.36
오차 행렬
[[76 24]
[15 39]]
정확도: 0.7468, 정밀도: 0.6190, 재현율: 0.7222, F1: 0.6667, AUC:0.8433
임곗값: 0.39
오차 행렬
[[78 22]
[16 38]]
정확도: 0.7532, 정밀도: 0.6333, 재현율: 0.7037, F1: 0.6667, AUC:0.8433
임곗값: 0.42
오차 행렬
[[84 16]
[18 36]]
정확도: 0.7792, 정밀도: 0.6923, 재현율: 0.6667, F1: 0.6792, AUC:0.8433
임곗값: 0.45
오차 행렬
[[85 15]
[18 36]]
정확도: 0.7857, 정밀도: 0.7059, 재현율: 0.6667, F1: 0.6857, AUC:0.8433
임곗값: 0.48
오차 행렬
[[88 12]
[19 35]]
정확도: 0.7987, 정밀도: 0.7447, 재현율: 0.6481, F1: 0.6931, AUC:0.8433
임곗값: 0.5
오차 행렬
[[90 10]
[21 33]]
정확도: 0.7987, 정밀도: 0.7674, 재현율: 0.6111, F1: 0.6804, AUC:0.8433
임계값이 0.48일 때, 성능이 가장 양호한 것 같습니다. 이를 이용하여 다시 학습 후 성능을 보겠습니다.
# 임곗값를 0.48로 설정한 Binarizer 생성
binarizer = Binarizer(threshold=0.48)
# 위에서 구한 lr_clf의 predict_proba() 예측 확률 array에서 1에 해당하는 컬럼값을 Binarizer변환.
pred_th_048 = binarizer.fit_transform(pred_proba[:, 1].reshape(-1,1))
# roc_auc_score 관련 수정
get_clf_eval(y_test , pred_th_048, pred_proba[:, 1])
오차 행렬
[[88 12]
[19 35]]
정확도: 0.7987, 정밀도: 0.7447, 재현율: 0.6481, F1: 0.6931, AUC:0.8433
처음과 비교했을 때 성능이 그래도 어느 정도 나아졌음을 알 수 있습니다.
이상으로 '평가'에 대한 모든 정리를 마무리하도록 하겠습니다.
다음 시간부터 이제 정말 본격적으로
머신러닝의 핵심 개념인
'분류' 알고리즘들에 대하여 다뤄보도록 하겠습니다.
'파이썬 머신러닝 완벽가이드' 카테고리의 다른 글
4.2 결정 트리 실습 - 사용자 행동 인식 데이터 세트 (0) | 2021.11.22 |
---|---|
4.1 분류(결정트리) (0) | 2021.11.22 |
3.2 평가(F1 스코어, ROC와 AUC) (0) | 2021.11.21 |
3.1 평가(정밀도/재현율) (0) | 2021.11.21 |
2.4 사이킷런으로 수행하는 타이타닉 생존자 예측 (0) | 2021.11.19 |