파이썬 머신러닝 완벽 가이드_ch3 평가_ ROC 곡선과 AUC

생계발자·2024년 4월 1일

파이썬 머신러닝 완벽 가이드

ROC 곡선과 AUC 스코어

  • 이진 분류의 예측 성능 측정에서 중요하게 사용되는 지표

ROC 곡선

  • FPR(False Positive Rate)이 변할 때 TPR(True Positive Rate)가 어떻게 변하는지를 나타내는 곡선

TPR 곡선

  • 재현율, 민감도라고 불리고 TNR은 이에 대응하는 지표로 특이성

FPR,TNR은 다음과 같이 구할 수 있다.

FPR = FP / (FP + TN) = 1 -TNR = 1 -  특이성
TNR = TN/ ( FP + TN ) 

임곗값을 1부터 0까지 변화 시키면서 FPR을 구하고 이 FPR 값의 변화에 따른 TPR을 구하는 것이 ROC 곡선이다.

사이킷런은 ROC 곡선을 구하기 위해 roc_curve() API를 제공한다.

입력 파라미터:

  • y_true: 실제 클래스값 array (array shape = [데이터 건수])
  • y_score: predict_proba()의 반환 값 array에서 Positive 칼럼의 예측 확률이 보통 사용됨. array.shape = [n_samples]

반환 값:

  • fpr: fpr 값을 array로 반환
  • tpr: tpr 값을 array로 반환
  • thresholds : threshold값 array
from sklearn.metrics import roc_curve

#레이블 값이 1일때의 예측 확률을 추출
pred_proba_class1 = Ir_clf.predict_proba(X_test)[:,1]

fprs, tprs, thresholds = roc_curve(y_test, pred_proba_class1)
#반환된 임곗값 배열에서 샘플로 데이터를 추출하되, 임곗값을 5 step으로 추출
#thresholds[0]은 max(예측확률)+1로 임의 설정됨. 이를 제외하기 위해 np.arange는 1부터 시작 
thr_index = np.arange(1, thresholds.shape[0],5)

print('샘플 추출을 위한 임곗값 배열의 index:', thr_index)
print('샘플 index로 추출한 임곗값:', np.round(thresholds[thr_index],2))

# 5step 단위로 추출된 임계값에 따른 TPR, FPR 값
print('샘플 임곗값별 FPR:', np.round(fprs[thr_index], 3))
print('샘플 임곗값별 TPR:', np.round(tprs[thr_index], 3))



[output]
샘플 추출을 위한 임곗값 배열의 index: [ 1  6 11 16 21 26 31 36 41 46]
샘플 index로 추출한 임곗값: [0.94 0.73 0.62 0.52 0.44 0.28 0.15 0.14 0.13 0.12]
샘플 임곗값별 FPR: [0.    0.008 0.025 0.076 0.127 0.254 0.576 0.61  0.746 0.847]
샘플 임곗값별 TPR: [0.016 0.492 0.705 0.738 0.803 0.885 0.902 0.951 0.967 1.   ]

임곗값이 1에 가까운 값에서 점점 작아지면서 FPR이 점점 커지고 TPR은 가파르게 커짐을 알 수 있다.

이를 ROC 곡선으로 시각화 해보자

def roc_curve_plot(y_test, pred_proba_c1):
    #임곗값에 따른 FPR, TPR값을 반환받음.
    fprs, tprs, thresholds = roc_curve(y_test, pred_proba_c1)
    #ROC 곡선을 그래프 곡선으로 그림
    plt.plot(fprs, tprs, label='ROC')
    #가운데 대각선 직선을 그림
    plt.plot([0,1], [0,1], 'k--', label='Random')
    
    #FPR X축의 Scale을 0.1 단위로 변경, X,Y축 명 설정 등
    start, end = plt.xlim()
    plt.xticks(np.round(np.arange(start,end,0.1),2))
    plt.xlim(0,1);plt.ylim(0,1)
    plt.xlabel('FPR(1-Specificity)');plt.ylabel('TPR(Recall)')
    plt.legend()
    
roc_curve_plot(y_test, pred_proba[:,1])

ROC 곡선 자체는 FPR, TPR 의 변화를 보는데 이용하며 분류의 성능 지표로 사용되는 것은 ROC 곡선 면적에 기반한 AUC값이다.

이는 일반적으로 1에 가까울수록 좋은 수치

AUC 수치가 커지려면 FPR이 작은 상태에서 얼마나 큰 TPR을 얻을 수 있느냐가 관건이다.

from sklearn.metrics import roc_auc_score

pred_proba = Ir_clf.predict_proba(X_test)[:,1]
roc_score = roc_auc_score(y_test, pred_proba)
print('ROC AUC 값:{0:.4f}'.format(roc_score))



[output]
ROC AUC 값:0.8987
  • 마지막으로 get_clf_eval() 함수에 roc_auc_score()를 이용해 ROC AUC값을 측정하는 로직을 추가
  • ROC AUC는 예측 확률값을 기반으로 계산되므로 get_clf_eval()함수의 인자로 받을 수 있도록 get_clf_eval(y_test, pred=None, pred_proba=None)으로 함수명을 변경
def get_clf_eval(y_test, pred=None, pred_proba=None):
    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 = roc_auc_score(y_test, pred_proba)
    print('오차 행렬')
    print(confusion)
    #ROC-AUC print 추가
    print('정확도:{0:.4f}, 정밀도:{1:.4f}, 재현율:{2:.4f}.\F1:{3:.4f}, AUC:[4:.4f]'.format(accuracy, precision, recall, f1, roc_auc))
profile
생(계를 위한) 개발자

0개의 댓글