04. F1 스코어
F1 스코어는 정밀도와 재현율을 결합한 지표이다.
이는 정밀도와 재현율이 어느 한 쪽으로 치우치지 않는 수치를 나타낼 때 상대적으로 높은 값을 가진다.
F1 스코어의 공식은 다음과 같다.
사이킷런은 F1 스코어를 구하기 위해 f1_score() API를 제공한다.
이를 이용해 앞 게시글에서의 예제였던 타이타닉 생존자 모델의 F1 스코어를 구해보자
from sklearn.metrics import f1_score
f1 = f1_score(y_test, pred)
print('F1 스코어:{0:.4f}'.format(f1))
[output]
F1 스코어:0.7966
이번에는 타이타닉 생존자 예측에서 임곗값을 변화시키면서 F1 스코어를 포함한 평가 지표를 구해보자
이를 위해 앞에서 작성한 get_clf_eval 함수에 F1스코어를 구하는 로직을 추가한다.
그리고 앞에서 작성한 get_eval_threshold() 함수를 이용해 임곗값 0.4~0.6별로 정확도, 정밀도, 재현율, F1스코어를 알아보자
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 = Ir_clf.predict_proba(X_test)
get_eval_by_threshold(y_test, pred_proba[:,1].reshape(-1,1), thresholds)
[output]
임곗값: 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
F1 스코어는 임곗값이 0.6일 때 가장 좋은 값을 보여준다.
05. ROC 곡선과 AUC
ROC 곡선과 AUC 스코어는 이진 분류의 예측 성능 측정에서 중요하게 사용되는 지표이다.
ROC 곡선은 FPR(False Positive Rate)이 변할 때 TPR(True Positive Rate)가 어떻게 변하는지를 나타내는 곡선이다.
TPR은 재현율, 민감도라고 불리고 TNR은 이에 대응하는 지표로 특이성이라고 불린다.
TNR은 다음과 같이 구할 수 있다.
TNR = TN/ ( FP + TN )
FPR = FP / (FP + TN) = 1 -TNR = 1 - 특이성
임곗값을 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))
Ref) 파이썬 머신러닝 완벽가이드
'데이터 > 머신러닝' 카테고리의 다른 글
[Classification] Chapter 4 | 분류(01. 분류의 개요~02. 결정 트리) (0) | 2022.09.05 |
---|---|
[Evaluation] Chapter 3 | 평가 (06. 피마 인디언 당뇨병 예측) (0) | 2022.08.29 |
[Evaluation] Chapter 3 | 평가 (01. 정확도 ~ 03. 정밀도와 재현율) (0) | 2022.08.28 |
[Numpy, Pandas] Chapter 2 | 사이킷런으로 시작하는 머신러닝 (06. 사이킷런으로 수행하는 타이타닉 생존자 예측) (0) | 2022.08.25 |
[Data Preprocessing] Chapter 2 | 사이킷런으로 시작하는 머신러닝 (05. 데이터 전처리) (0) | 2022.08.25 |