4. F1 score

F1 score는 정밀도와 재현율을 결합한 지표이다. F1 score는 정밀도와 재현율이 어느 한쪽으로 치우치지 않는 수치를 나타낼 때 상대적으로 높은 값을 가진다.

 

이전에 학습한 로지스틱 회귀 기반 타이타닉 생존자 모델을 이용하여 F1 score를 구해보았다.

from sklearn.metrics import f1_score
f1 = f1_score(y_test, pred)
print('F1 스코어:{0:.4f}'.format(f1))

threshold를 변화시키면서 F1 score를 구해볼 것이고, 이전에 get_clf_eval() 함수에 F1 score를 구하는 로직을 추가하였다. 그리고 이전에 get_eval_by_threshold() 함수를 이용해 임계값 0.4 ~ 0.6별로 평가 지표를 구할것이다.

def get_clf_eval(y_test, pred):
    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 score 추가
    f1 = f1_score(y_test, pred)
    print('오차 행렬')
    print(confusion)
    print('정확도:{0:.4f}, 정밀도:{1:.4f}, 재현율:{2:.4f}, F1:{3:.4f}'.format(accuracy, precision, recall, f1))
    
thresholds = [0.4, 0.45, 0.5, 0.55, 0.6]
pred_proba = lr_clf.predict_proba(X_test)
get_eval_by_threshold(y_test, pred_proba[:,1].reshape(-1,1), thresholds)

F1 score는 threshold가 0.6일 때 가장 좋은 값을 보인다. 하지만 임계값이 0.6인 경우에는 재현율이 크게 감소하니 주의해야 한다.

 

 

5. ROC 곡선과 AUC

ROC 곡선은 FPR(False Positive Rate)이 변할 때 TPR(True Positive Rate)이 어떻게 변하는지를 나타내는 곡선이다. FPR을 x축으로, TPR을 y축으로 잡으면 FPR의 변화에 따른 TPR의 변화가 곡선 형태로 나타남

 

분류의 성능 지표로 사용되는 것은 ROC 곡선 면적에 기반한 AUC 값으로 결정한다. AUC(Area Under Curve)값은 ROC 곡선 밑의 면적을 구한 것으로 일반적으로 1에 가까울수록 좋은 수치이다.

→ROC 곡선이 가운데 직선에 가까울수록 면적이 작기 때문에 성능이 떨어지는 것이며, 멀어질수록 면적이 크기 때문에 성능이 뛰어난 것

 

-TPR은 True Positive Rate의 약자이며, 이는 재현율을 나타낸다.(실제 Positive를 맞게 예측한 비율)

따라서 TPR은 TP / (FN+TP)이다. TPR, 즉 재현율은 민감도로도 불림

-FPR은 실제 Negative를 잘못 예측한 비율을 나타낸다. 

즉, 실제는 Negative인데 Positive로 잘못 예측한 비율이다. 

따라서 FPR은 FP / (FP+TN)이다.

 

ROC 곡선은 FPR을 0부터 1까지 변경하면서 TPR의 변화 값을 구해 그리는데, Threshold(분류 결정 임계값)을 변경함으로서 수행할 수 있음

●Threshold를 1로 하면 FPR은 0임

→임계값을 1로 하면 Positive 예측 기준이 매우 높기 때문에 아예 Positive로 예측하지 않아서 FP 값이 0이 되므로 FPR은 0이 됨

●Threshold를 0으로 하면 FPR은 1임

→임계값을 0으로 하면 Positive 예측 기준이 매우 낮기 때문에 전부 Positive로 예측을 해서 아예 Negative 예측이 없음. 그래서 TN 값이 0이 되므로 FPR은 1이 됨

 

<ROC 곡선 및 AUC 스코어 API>

 

이전에 정밀도와 재현율에서 학습한 LogisticRegression 객체의 predict_proba() 결과를 다시 이용해 ROC 곡선과 AUC 값을 구해보자

from sklearn.metrics import roc_curve

# 레이블 값이 1일때의 예측 확률을 추출
pred_proba_class1 = lr_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))

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

# roc curve 시각화
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')
    # 가운데 랜덤 수준의 대각선 직선 그리기(AUC=0.5)
    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])

# AUC 값 구하기
from sklearn.metrics import roc_auc_score

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

 


오차행렬, 정확도, 정밀도, 재현율, F1 스코어, ROC AUC 값을 한번에 출력할 수 있는 함수 작성

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))

 

+ Recent posts