hyeonzzz's Tech Blog

[파머완 3장] 4. F1 스코어 5. ROC 곡선과 AUC 본문

Machine Learning

[파머완 3장] 4. F1 스코어 5. ROC 곡선과 AUC

hyeonzzz 2024. 1. 11. 16:20

4) F1 스코어

: 정밀도와 재현율을 결합한 지표

어느 한 쪽으로 치우치지 않는 수치를 나타낼 때 높은 값을 가진다

 

f1_score( ) : F1 스코어를 구함

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

 

 

임곗값을 변화시키면서 평가 지표 구하기

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 스코어 추가
    f1 = f1_score(y_test,pred)
    print('오차 행렬')
    print(confusion)
    # f1 score print 추가
    print('정확도: {0:.4f}, 정밀도: {1:.4f}, 재현율: {2:.4f}, F1:{3:.4f}'.format(accuracy, precision, recall, f1))

thresholds = [0.4 , 0.45 , 0.50 , 0.55 , 0.60]
pred_proba = lr_clf.predict_proba(X_test)
get_eval_by_threshold(y_test, pred_proba[:,1].reshape(-1,1), thresholds)
임곗값: 0.4
오차 행렬
[[97 21]
 [11 50]]
정확도: 0.8212, 정밀도: 0.7042, 재현율: 0.8197, F1:0.7576
임곗값: 0.45
오차 행렬
[[105  13]
 [ 13  48]]
정확도: 0.8547, 정밀도: 0.7869, 재현율: 0.7869, F1:0.7869
임곗값: 0.5
오차 행렬
[[108  10]
 [ 14  47]]
정확도: 0.8659, 정밀도: 0.8246, 재현율: 0.7705, F1:0.7966
임곗값: 0.55
오차 행렬
[[111   7]
 [ 16  45]]
정확도: 0.8715, 정밀도: 0.8654, 재현율: 0.7377, F1:0.7965
임곗값: 0.6
오차 행렬
[[113   5]
 [ 17  44]]
정확도: 0.8771, 정밀도: 0.8980, 재현율: 0.7213, F1:0.8000

 

 

5) ROC 곡선과 AUC

ROC 곡선 : FPR이 변할 때 TPR(재현율)이 어떻게 변하는지를 나타내는 곡선

  • TPR(재현율) : 실제 Positive가 정확히 예측돼야 하는 수준 (질병이 있는 사람은 질병이 있는 것으로 양성 판정)
  • TNR(특이성) : 실제 Negative가 정확히 예측돼야 하는 수준 (질병이 없는 사람은 질병이 없는 것으로 음성 판정)

TPR = TP/ ( FN + TP ) 

 

TNR = TN/ ( FP + TN )

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

 

ROC곡선은 FPR을 0부터 1까지 변경하면서 TPR의 변화 값을 구한다

 

  • 가운데 직선 : ROC 곡선의 최저 값
  • ROC 곡선이 가운데 직선에 가까울수록 성능이 떨어지는 것
  • ROC 곡선은 FPR을 0부터 1까지 변경하면서 TPR의 변화 값을 구한다
  • 임계값을 1로 지정하면 FPR이 0이 된다
  • 임계값을 0으로 지정하면 FPR이 1이 된다

 

roc_curve( ) : ROC 곡선을 구함

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], 3))
print('샘플 임곗값별 TPR: ', np.round(tprs[thr_index], 3))
샘플 추출을 위한 임곗값 배열의 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은 가파르게 커진다

 

 

AUC : ROC 곡선 밑의 면적을 구한 것. 일반적으로 1에 가까울수록 좋은 수치

  • AUC 커지려면 FPR이 작은 상태에서 얼마나 큰 TPR을 얻을 수 있느냐가 관건이다
  • 가운데 직선에서 멀어지고 직사각형에 가까운 곡선이 될수록 좋은 AUC 수치를 얻는다
  • 가운데 직선은 랜덤 수준의 이진 분류 AUC값으로 0.5이다
  • 보통의 분류는 0.5 이상의 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))
ROC AUC 값: 0.8987