문턱값
실습 준비
import matplotlib.pyplot as plt
import numpy as np
from sklearn.metrics import (
accuracy_score,
f1_score,
precision_score,
recall_score,
roc_auc_score,
roc_curve,
)
문턱값 threshold
- 문턱값(threshold): 모델이 출력한 양성 확률을 양성 예측으로 바꾸는 기준
- 이 실습에서는 확률이 문턱값보다 크면 양성, 이하면 음성으로 분류
- 문턱값을 바꾸면 혼동 행렬의 FP, FN, TP, TN 구성이 달라짐
문턱값을 높일 때
- 문턱값을 높이면 양성이라고 예측하기가 더 어려워짐
- 양성 예측이 줄어들면서 양성 예측의 신뢰도, 즉 정밀도는 높아질 수 있음
- 반대로 실제 양성 중 일부를 놓치기 쉬워져 재현도는 낮아질 수 있음
문턱값을 낮출 때
- 문턱값을 낮추면 양성이라고 예측하기가 쉬워짐
- 더 많은 대상을 양성으로 잡기 때문에 재현도는 높아질 수 있음
- 그러나 위양성이 함께 늘어나면 정밀도는 낮아질 수 있음
문턱값을 바꿔가면서 지표 계산
- 여러 문턱값을 순회하면서 정확도, 정밀도, 재현도, 특이도, F1 점수를 계산
np.where(y_prob > threshold, 1, 0)로 문턱값별 예측값을 새로 만듦
ths = np.linspace(0.1, 0.9, 81)
accuracy = []
precision = []
recall = []
specificity = []
f1 = []
for threshold in ths:
y_pred = np.where(y_prob > threshold, 1, 0)
accuracy.append(accuracy_score(y_true, y_pred))
precision.append(precision_score(y_true, y_pred))
recall.append(recall_score(y_true, y_pred))
specificity.append(recall_score(y_true, y_pred, pos_label=0))
f1.append(f1_score(y_true, y_pred))
0.1부터 0.9까지 0.01 간격의 문턱값 81개를 확인.
시각화
- 문턱값이 높아지면 정밀도와 특이도는 높아지는 경향
- 문턱값이 낮아지면 재현도는 높아지는 경향
- 정확도나 F1처럼 여러 오류를 함께 반영하는 지표는 특정 구간에서 최대값을 가질 수 있음
plt.plot(ths, accuracy, label="Accuracy")
plt.plot(ths, precision, label="Precision")
plt.plot(ths, recall, label="Recall")
plt.plot(ths, specificity, label="Specificity")
plt.plot(ths, f1, label="F1 Score")
plt.xlabel("Threshold")
plt.legend()
plt.show()

F1이 가장 높은 문턱값 찾기
np.argmax(f1)로 F1 점수가 가장 큰 위치의 인덱스를 찾음- 해당 인덱스로 최적 문턱값과 최대 F1 점수를 확인
- 그래프에 빨간 점과 점선을 추가해 최고 F1 지점을 표시
best_index = np.argmax(f1) # 가장 큰 F1 점수의 인덱스
best_threshold = ths[best_index]
best_threshold # 최대 F1의 문턱값
실행 결과
np.float64(0.48)
best_f1 = f1[best_index]
best_f1 # 최대 F1 점수
실행 결과
0.7683049147442327
F1 점수가 가장 높은 문턱값은 0.48, 최대 F1 점수는 약 76.8%.
plt.plot(ths, f1)
plt.axvline(best_threshold, color="r", linestyle="--")
plt.plot(best_threshold, best_f1, "ro")
plt.xlabel("Threshold")
plt.ylabel("F1 Score")
plt.show()

ROC 곡선 Receiver operating characteristic Curve
- ROC 곡선(Receiver Operating Characteristic Curve)은 신호 이론에서 유래
- 가로축은
1 - 특이도, 즉 FPR(False Positive Rate) - 세로축은 재현도, 즉 TPR(True Positive Rate)
- 문턱값을 변화시키면서 특이도와 재현도의 변화를 곡선으로 표시
- 무작위로 예측할 경우
TPR = FPR인 대각선에 가까움 - AUC(Area Under the Curve)는 0~1 범위이며, 클수록 높은 성능을 의미

Python ROC 곡선
roc_curve()로 FPR, TPR, 문턱값을 계산roc_auc_score()로 ROC 곡선 아래 면적, 즉 AUC를 계산
fpr, tpr, roc_thresholds = roc_curve(y_true, y_prob)
plt.plot(fpr, tpr)
plt.plot([0, 1], [0, 1], linestyle="--")
plt.xlabel("False Positive Rate")
plt.ylabel("True Positive Rate")
plt.show()

roc_auc = roc_auc_score(y_true, y_prob)
roc_auc # ROC AUC
실행 결과
0.8270230000000001
ROC AUC는 약 0.827.