정밀도와 재현율은 Positive 데이터 세트의 예측 성능에 좀 더 초점을 맞춘 평가 지표
# 정밀도
- Positive 예측 성능을 더욱 정밀하게 측정하기 위한 평가 지표로, 양성 예측도라고도 불림
- 예측을 Positive로 한 대상 중에 실제 값도 Positive로 일치한 데이터 비율
- 사이킷런의 API는 다음과 같다
from sklearn.metrics import precision_score
# 재현율
- 실제 값이 Positive인 대상 중에 예측도 Positive로 일치한 데이터 비율
- 민감도 또는 TPR(True Positive Rate)라고도 불림
- 사이킷런의 API는 다음과 같다
from sklearn.metrics import recall_score
🔍 정밀도와 재현율은 언제 중요할까?
- 재현율이 중요 지표인 경우는 실제 양성인 데이터를 음성으로 잘못 판단하게 되면 업무상 큰 지장이 생기는 경우이다
- 예시 1) 암 판단 모델에서 암 양성 환자를 음성으로 잘못 판단하게 되면 큰일이 난다! 🤕
- 예시 2) 금융 사기 적발 모델도, 금융사기가 맞는데 아닌 것으로 잘못 판단하면 큰 손실이 발생! 🤑
- 정밀도가 중요한 경우는 실제 음성인 데이터를 양성으로 잘못 판단하게 되면 업무상 큰 영향이 생기는 경우이다
- 예 : 스팸메일 여부(스팸으로 예측했는데, 실제 스팸이 아닌 경우 메일을 받을 수 없음)
- 보통은 재현율이 정밀도보다 상대적으로 중요한 업무가 많다
🔍 정밀도와 재현율, 둘 중 하나만 써야 하나? 👉 No!
- 두 경우 모두, TP를 높이는 데 동일하게 초점을 맞춤
- 재현율은 FN(실제 양성, 예측 음성)을 낮추는데 초점
- 정밀도는 FP(실제 음성, 예측 양성)을 낮추는데 초점
- 따라서 재현율과 정밀도는 서로 보완적인 지표가 되어, 분류 성능 평가에 함께 사용됨
- 가장 좋은 성능 평가 결과 ▶︎ 정밀도와 재현율 모두 높은 수치를 얻는 것
- 둘 중 한 쪽만 매우 높게 나타난다면 바람직하지 않음
🧑🏻💻 예제
- 분류 평가 지표를 모두 호출하는 함수 작성
from sklearn.metrics import accuracy_score, precision_score, recall_score, confusion_matrix
# 📍 여러가지 평가지표를 한번에 호출하는 함수
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)
print('오차 행렬')
print(confusion)
print('정확도:{0:.4f}, 정밀도:{1:.4f}, 재현율:{2:.4f}'.format(accuracy, precision, recall))
- 타이타닉 데이터로 예측 및 평가 수행
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
titanic_df = pd.read_csv('train.csv')
y_titanic_df = titanic_df['Survived']
x_titanic_df = titanic_df.drop('Survived', axis = 1)
x_titanic_df = transform_features(x_titanic_df)
X_train, X_test, y_train, y_test = train_test_split(x_titanic_df, y_titanic_df, test_size = 0.2, random_state=11)
#solver의 기본값은 lbfgs(데이터 크고, 다중분류일때 적합), liblinear(작은데이터셋의 이진분류에 적합)
lr_clf = LogisticRegression(solver = 'liblinear')
lr_clf.fit(X_train, y_train)
pred = lr_clf.predict(X_test)
get_clf_eval(y_test, pred)
🔍 정밀도와 재현율의 트레이드오프(Trade-off)
- 정밀도와 재현율이 특별히 강조돼야 할 경우 분류의 결정 임곗값을 조정해 정밀도/재현율 수치를 높일 수 있다
- 하지만, 두 지표는 상호 보완적이라 한 쪽을 강제로 높이면, 한쪽이 떨어지기 쉽다
- 일반적으로 이진분류에서는 임곗값을 0.5(50%)로 정하고 이 값보다 확률이 크면 Positive, 작으면 Negative로 분류한다
🧑🏻💻 개별 데이터 별로 예측 확률을 반환하는 predict_proba( )
- 학습이 완료된 사이킷런 Classifier 객체에서 호출 가능
- 테스트 피처 데이터 세트를 피라미터로 입력하주면, 테스트 피처 레코드의 개별 클래서 예측 확률을 반환
- 이진 분류에서 predict_proba()를 수행해 반환되는 ndarray는,
- 첫 번째 칼럼이 클래스 값 0에 대한 예측 확률
- 두 번째 칼럼이 클래스 값 1에 대한 예측 확률
pred_proba = lr_clf.predict_proba(X_test)
pred = lr_clf.predict(X_test)
print('pred_proba() 결과 shape: {0}'.format(pred_proba.shape))
print('\npred_proba array에서 앞 3개만 샘플로 추출: \n', pred_proba[:3])
# 예측 확률 array와 예측 결괏값 array를 병합해 예측 확률과 결괏값을 한번에 확인
pred_proba_result = np.concatenate([pred_proba, pred.reshape(-1, 1)], axis = 1)
print('\n두 개의 class 중, 더 큰 확률을 클래스 값으로 예측 \n', pred_proba_result[:3])
🧑🏻💻 정밀도와 재현율 관계를 보여주는 precision_recall_curve( )
입력 파라미터 | y_true : 실제 클래스값 배열 (배열크기 = 데이터 건수) probas_pred : positive 칼럼의 예측 확률 배열 (배열크기 = 데이터 건수) |
반환 값 | 정밀도 : 임곗값 별 정밀도 값을 배열로 반환 재현율 : 임곗값 별 재현율 값을 배열로 반환 임곗값 |
- 활용 예시 및 결과 : 임곗값이 낮을수록, 많은 양성 예측으로 인해 재현율 값이 극도로 높아지고, 정밀도 값이 극도로 낮아진다
- 그래프에서 두 선이 만나는 정도의 구간이 임곗값으로 적합하다 (두 개 수치의 상호 보완!)
from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
def precision_recall_curve_plot(y_test, pred_proba_c1):
# threshold ndarray와 이 threshold에 따른 정밀도, 재현율 ndarray 추출.
precisions, recalls, thresholds = precision_recall_curve( y_test, pred_proba_c1)
# X축을 threshold값으로, Y축은 정밀도, 재현율 값으로 각각 Plot 수행. 정밀도는 점선으로 표시
plt.figure(figsize=(8,6))
threshold_boundary = thresholds.shape[0]
plt.plot(thresholds, precisions[0:threshold_boundary], linestyle='--', label='precision')
plt.plot(thresholds, recalls[0:threshold_boundary],label='recall')
# threshold 값 X 축의 Scale을 0.1 단위로 변경
start, end = plt.xlim()
plt.xticks(np.round(np.arange(start, end, 0.1),2))
# x축, y축 label과 legend, 그리고 grid 설정
plt.xlabel('Threshold value')
plt.ylabel('Precision and Recall value')
plt.legend()
plt.grid()
plt.show()
# 함수 적용
precision_recall_curve_plot(y_test, lr_clf.predict_proba(X_test)[:,1])
👉 결국, 임곗값에 따라 정밀도와 재현율의 수치가 달라지는데,
이 둘을 적절하게 조합하여 분류의 종합적인 성능평가에 사용될 수 있는 지표가 필요해진다.
정답은?
F1 스코어로, 다음 포스팅에 이어진다
728x90
'Machine Learning > scikit-learn' 카테고리의 다른 글
결정 트리 실습 - 사용자 행동 인식 데이터 분류 예제 (0) | 2023.08.21 |
---|---|
[분류 알고리즘(앙상블)] 결정 트리(Decision Tree) (1) | 2023.08.21 |
[분류_성능 평가 지표] 정확도와 오차 행렬(이진 분류) (0) | 2023.08.18 |
[GridSearchCV] 교차 검증 & 하이퍼 파라미터 튜닝을 한 번에 (0) | 2023.08.17 |
[교차 검증] Stratified K 폴드 (0) | 2023.08.17 |