본문 바로가기
개념정리/머신러닝

머신러닝 - 피마 인디언 당뇨병 예측

by 화영쌤 2023. 5. 17.
728x90

「 피마 인디언 당뇨병(Pima Indian Diabetes) 데이터 세트를 이용해 당뇨병 여부를 판단하는 머신러닝 예측 모델을 수립 」


▷ 함수 생성하기

# 관련 모듈 import 하기
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

# 함수 설정하기
def get_clf_eval(y_test,pred=None,pred_proba=None):
    from sklearn.metrics import accuracy_score,precision_score,recall_score,confusion_matrix,f1_score,roc_auc_score
    confusion = confusion_matrix(y_test,pred)
    accuracy = accuracy_score(y_test,pred)
    precision = precision_score(y_test,pred)
    recall = recall_score(y_test,pred)
    f1 = f1_score(y_test,pred)
    roc_auc = roc_auc_score(y_test,pred_proba)
    print('오차행렬')
    print(confusion)
    print(f'정확도 : {accuracy:.4f} 정밀도 : {precision:.4f} 재현율 : {recall:.4f} F1 : {f1:.4f} AUC : {roc_auc:.4f}')

def get_eval_by_threshold(y_test,pred_proba,thresholds):
    from sklearn.preprocessing import Binarizer
    for threshold in thresholds:
        pred = Binarizer(threshold=threshold).fit_transform(pred_proba)
        print('임계값 : ',threshold)
        get_clf_eval(y_test,pred,pred_proba)

def roc_curve_plot(y_test,pred_proba):
    from sklearn.metrics import precision_recall_curve
    fprs,tprs,thresholds = roc_curve(y_test,pred_proba)
    plt.plot(fprs,tprs,label='ROC')
    # k는 black을 뜻함
    plt.plot([0,1],[0,1],'k--',label='Random')
    start,end = plt.xlim()
    plt.xticks(np.round(np.arange(start,end,0.1),2))
    plt.xlim(0,1)
    plt.ylim(0,1)
    plt.legend()
    plt.show()
    
def precision_recall_curve_plot(y_test,pred_proba):
    # threshold ndarray 와 이 threshold에 따른 정밀도, 재현율 ndarray 추출하기
    precisions,recalls,thresholds = precision_recall_curve(y_test,pred_proba)
    plt.figure(figsize=(8,6))
    threshold_boundary = thresholds.shape[0]
    # x축을 threshold 값으로, y축은 정밀도 값으로 plot 수행, 정밀도는 점선으로 표시 
    plt.plot(thresholds,
             precisions[0:threshold_boundary],
             linestyle='--',
             label='precision')
    # x축을 threshold 값으로, y축은 재현율 값으로 plot 수행
    plt.plot(thresholds,
             recalls[0:threshold_boundary],
             label='recall')
    # threshold 값 x축의 scale을 0.1 단위로 변경
    start,end = plt.xlim()
    plt.xticks(np.round(np.arange(start,end,0.1),2))
    # 범례 설정하기
    plt.legend()
    # 눈금 설정하기
    plt.grid()
    plt.show()

▷ 로지스틱 회귀 평가하기

( 정확도 : 77.2 % , 정밀도 : 72 % , 재현율 : 57.4% , F1 : 63.9 % , AUC : 79.2% )

# 데이터 불러오기
df = pd.read_csv('diabetes.csv')

# 피처 데이터 세트 : x, 레이블 데이터 세트 : y 를 추출
y=df['Outcome']
x=df.drop(columns='Outcome')

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)

 

+ 시각화 하기

pred_proba = lr_clf.predict_proba(x_test)[:,1]
precision_recall_curve_plot(y_test,pred_proba)


▷데이터 전처리

# 0값을 검사할 피처 명 리스트
zero_features = ['Glucose','BloodPressure','SkinThickness','Insulin','BMI']

# 전체 데이터 건수
total_count = df['Glucose'].count()

# zero_features 리스트 내부에 저장된 개별 피처들에 대해서 0값을 평균 값으로 대체
mean_zero_features = df[zero_features].mean()
df[zero_features]=df[zero_features].replace(0,mean_zero_features)

▷ 데이터 전처리 후 로지스틱 회귀 평가하기

( 정확도 : 77.9 % , 정밀도 : 72.7 % , 재현율 : 59.6% , F1 : 65.3% , AUC : 84.4% )

# 피처 데이터 세트 : x, 레이블 데이터 세트 : y 를 추출
y=df['Outcome']
x=df.drop(columns='Outcome')

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(solver='liblinear')

# 로지스틱 회귀로 학습하기
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)

 

+ 시각화 하기

precision_recall_curve_plot(y_test,pred_proba)