머신러닝은 데이터 가공/변환, 모델 학습/예측, 그리고 평가(Evaluation)의 프로세스로 구성되어있습니다.
머신러닝 모델은 여러 가지 방법으로 예측 성능을 평가 할 수 있는데, 이 성능 평가 지표(Evaluation Metric)는 일반적으로 모델이 분류(Classification)이냐 회귀(Regression)이냐에 따라 다릅니다.
🎯 회귀와 분류의 성능평가지표들
지도학습 | Baseline (기준모델) | Evaluation Metric (성능평가지표) |
Regression (회귀) |
실제값과 예측값의 오차 평균값 | MAE , MSE, R^2 |
Classification (분류) |
Majority(최빈값) | Accuracy (정확도) Confusion Matrix (오차행렬) Precision (정밀도) Recall (재현율) F1 Score (F1스코어) ROC AUC |
분류는 이진 분류(2개의 label 결괏값)와 멀티 분류(여러개의 결괏값)으로 나눌 수 있는데 위 분류의 성능평가지표들은 특히, 이진 분류에서 중요하게 강조하는 지표들입니다. 분류의 평가 방법도 일반적으로는 실제 결과 데이터와 예측 결과 데이터가 얼마나 정확하고 오류가 적게 발생하는가에 기반하지만, 단순히 이러한 정확도(Accuracy)로만 판단했다가는 잘못된 평가 결과에 빠질 수 있습니다. 특히 이진 분류에서는 정확도보다는 다른 성능 평가 지표가 더 중요시되는 경우가 많습니다.
🎯 정확도만으로 평가가 충분하지 않은 이유
https://laptrinhx.com/confusion-matrix-accuracy-precision-recall-f1-score-2087412546/
만약 데이터셋의 label값이 불균형(unbalance)한 경우엔 정확도는 좋은 측정을 할 수 없다.
예를 들면 90명의 건강한사람과 10명의 환자가 있을 경우, 머신러닝이 모든 사람을 건강한 사람으로 예측할 경우에도 정확도는 90%가 된다.
정확도는 90%이지만, 이 모델은 환자 10명 모두가 건강하다고 분류되기 때문에 좋은 모델은 아니다.
이렇게 불균형한 데이터셋일 경우에는 정확도만으로 올바른 평가를 할 수 없게된다.
<불균형한 레이블 (Unbalanced label set) - titanic 예시>
https://colab.research.google.com/drive/1Yo2cvh8_hFcqZdPUfs8SpzPGhyfHZGeI
1. Confusion Matrix (오차행렬, 혼동행렬)
이진 분류에서 성능 지표로 잘 활용되는 Confusion Matrix는 학습된 분류 모델이 예측을 수행하면 얼마나 confusion(혼란)한지 함께 보여주는 지표이다. 즉, 이진 분류의 예측 오류가 얼마인지 뿐만아니라 어떠한 유형의 예측 오류가 발생하고 있는지를 함께 나타낸다.
C.M | 예측 클라스 (Predcited Class) | ||
실제 클라스 (Actual Class) |
Negative ( 0 ) | Positive ( 1 ) | |
Negative ( 0 ) | TN (True Negative) 0이라고 예측하고 실제 0일 경우 |
FP (False Positive) 1이라고 예측했지만 사실 0일 경우 |
|
Positive ( 1 ) | FN (False Negative) 0이라고 예측했지만 사실 1일 경우 |
TP (True Positive) 1이라고 예측하고 실제 1일 경우 |
TP, TN, FP, FN 값을 조합해 Classifier의 성능을 측정할 수 있는 주요 지표들을 알 수 있다.
바로 정확도(Accuracy), 정밀도(Precision), 재현율(Recall) 이다.
# train_test_split()
from sklearn.model_selection import train_test_split
target = df['Survived']
feature = df.drop('Survived',axis=1)
X_train, X_test,y_train, y_test = train_test_split(feature, target, test_size=0.2, random_state=10)
# Confusion Matrix
from sklearn.metrics import confusion_matrix
from sklearn.tree import DecisionTreeClassifier
dt_clf = DecisionTreeClassifier(random_state=10)
dt_clf.fit(X_train, y_train)
confusion_matrix(y_test,dt_clf.predict(X_test))
2. 정확도 (Accuracy)
정확도는 실제 데이터와 예측 데이터를 비교했을 때 얼마나 같은지를 판단하는 지표이다.
즉, 얼마나 올바르게 예측했는가에 대한 비율만으로 결정되어 직관적으로 모델 예측 성능을 나타낸다고 볼 수 있다.
(하지만 이진 분류의 경우 데이터 구성에 따라 모델의 성능을 왜곡할 수 있기 때문에 다른 평가지표와 함께 봐야한다.)
정확도는 오차행렬에서 True 값인 TN, TP 에 좌우된다.
▷ 정확도 평가지표의 좋지 못한 예 ex ) 적은 수의 결괏값에 Positive(1)를 설정하고 그렇지 않은 경우 Negative(0)
|
▷ 그 결과 |
🎃 결과적으로 정확도 지표는 비대칭한 데이터 세트에서 Positive에 대한 예측 정확도를 판단하지 못한 채 Nagative에 대한 예측 정확도만으로 분류의 정확도가 매우 높게 나타나는 수치적 판단 오류를 일으킨다.
3. 정밀도(Precision)와 재현율(Recall)
정밀도와 재현율은 Positive 데이터 세트의 예측 성능에 좀 더 초점을 맞춘 평가 지표이다.
- TP가 0이면 정밀도와 재현율 값이 모두 0이 된다.
- 재현율과 정밀도 모두 TP를 높이는 데 동일한 초점을 맞춘다.
✔ Precision : 예측을 Positive로 한 대상 중에 예측과 실제 값이 Positive로 일치한 데이터의 비율
(=양성 예측도 : Positive 예측 성능을 더욱 정밀하게 측정하기 위한 평가 지표)
- FP를 낮추는 데 초점을 맞춤
✔ Recall : 실제 값이 Positive인 대상 중에서 예측과 실제 값이 Positive로 일치한 데이터의 비율
(=민감도(Sensitivity) or TPR(True Positive Rate))
- FN를 낮추는 데 초점을 맞춤
※ 이진 분류 모델의 업무 특성에 따라서 정밀도와 재현율 중 어떤 평가 지표가 더 중요한지 다르다. 보통 재현율이 정밀도보다 상대적으로 중요한 업무가 많음. (중요한 지표를 고를 때, 역지사지를 생각해 볼 것)
상황 | 예시 | |
Precision(정밀도)이 더 중요 지표인 경우 |
실제 Negative 음성인 데이터 예측을 Positive 양성으로 잘못 판단하게 되면 업무상 큰 영향이 발생하는 경우 | 1) 스팸메일 여부를 판단하는 모델 실제 스팸메일(P)을 일반메일(N)로 분류하더라도 사용자가 불편함을 느끼는 정도이지만, 실제 일반메일(N)을 스팸메일(P)로 분류할 경우에는 메일을 아예 받지 못하게 돼 업무에 차질이 생긴다. |
Recall(재현율)이 더 중요 지표인 경우 |
실제 Positive 양성 데이터를 Negative로 잘못 판단하게 되면 업무상 큰 영향이 발생하는 경우 | 1) 암 판단 모델 실제 암 환자를 양성(P)이 아닌 음성(N)으로 잘못 판단할 경우 오류의 대가가 생명을 앗아갈 정도로 심각하기 때문 2) 보험 사기 적발 모델 실제 금융거래사기(P)를 정상거래(N)으로 잘못 판단하게 되면 회사에 미치는 손해가 크다. |
<특징 정리>
- 재현율과 정밀도 모두 TP를 높이는 데 동일한 초점을 맞춘다.
- 정밀도는 FP를 낮추는 데 초점을 맞춤
- 재현율은 FN를 낮추는 데 초점을 맞춤
이와 같은 특성 때문에 재현율과 정밀도는 서로 보완적인 지표로 분류의 성능을 평가하는 데 적용된다.
가장 좋은 성능평가는 재현율과 정밀도 모두 높은 수치를 얻는 것이며, 반면에 둘 중 어느 한 평가 지표만 매우 높고, 다른 수치는 매우 낮으면 바람직 하지 않은 결과이다.
<code>
2021/02/11 - [분석 연습] - 타이타닉 (분석연습) - 전처리 확인가능
df.head(3)
# 평가지표들 함수만들기
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
# 타이타닉 데이터 분할/학습/예측/평가
target = df['Survived']
features = df.drop('Survived', axis=1)
X_train, X_test,y_train, y_test = train_test_split(features, target,
test_size=0.2, random_state=10)
lr_clf = LogisticRegression()
lr_clf.fit(X_train, y_train)
pred = lr_clf.predict(X_test)
get_clf_eval(y_test, pred)
▶결론
정밀도와 재현율이 높지 않습니다. 수치를 올려야 할 것 같습니다.
4. 정밀도&재현율 Trade-off
: 둘의 상호 보완적인 특성 때문에 어느 한쪽을 강제로 높이면 다른 하나의 수치는 떨어지는 현상
정밀도 또는 재현율이 특별히 강조돼야 할 경우 분류의 결정 임곗값(Threshold)을 조정해 수치를 높일 수 있다.
일반적으로 이진 분류에서는 임곗값을 0.5 (50%)로 정하고 임곗값보다 확률이 크면 Positive, 작으면 Negative로 결정한다.
<code>
1) 임계값 이해를 위해 결정 확률(예측 확률) 확인하기.
* predict() : 예측 결과 클래스값
* predict_probba() : 예측 확률 결과
# 예측확률(prediction probability)
pred_proba = lr_clf.predict_proba(X_test)
pred = lr_clf.predict(X_test)
print('pred_proba()결과 Shape : {0}'.format(pred_proba.shape))
# 예측확률 array와 예측 결괏값 array를 병합(concatenate)하고 DF으로 예측 확률과 결괏값을 한눈에 확인
import numpy as np
pred_proba_result = np.concatenate([pred_proba, pred.reshape(-1,1)], axis=1)
data = pd.DataFrame(pred_proba_result)
data.rename(columns={0:'probability of Negative(0)',1 : 'probability of Positive(1)', 2:'predict'}, inplace=True)
data
위 예측확률의 임계점은 0.5 (50%)로 Probability of Positive(1) 기준으로 0.5 이상이면 Positive(1)로 예측하고 아니면 Negative(0)으로 예측한다. 우리는 사이킷런으로 분류 결정 임곗값을 조절해 정밀도와 재현율의 성능 수치를 상호 보완적으로 조정할 수 있다.
2) 임계값(Threshold) 조절해보기
# 테스트를 수행할 모든 임곗값을 리스트 객체로 저장.
thresholds = [0.4, 0.45, 0.50, 0.55, 0.60]
def get_eval_by_threshold(y_test, pred_proba_c1, thresholds):
# thresholds list 객체 내의 값을 차례로 iteration하면서 Evaluation 수행
for custom_threshold in thresholds:
binarizer = Binarizer(threshold=custom_threshold).fit(pred_proba_c1)
custom_predict = binarizer.transform(pred_proba_c1)
print("\n임곗값 :", custom_threshold)
get_clf_eval(y_test, custom_predict)
get_eval_by_threshold(y_test, pred_proba[:,1].reshape(-1,1), thresholds)
Threshold(임곗값)를 낮추니 정밀도는 떨어지고 재현율은 올랐다. 분류 결정 임곗값은 Positive 예측값을 결정하는 확률의 기준이 된다. (임곗값의 이상은 Positive 이하는 Negative이다.) 확률을 0.4부터 Positive로 예측을 더 너그럽게 하기 때문에 임곗값을 낮출수록 Positive True 값이 많아지게 된다.
임계값이 0.5인 오차행렬과 0.4인 오차행렬을 비교해보면, 임계값을 낮추니 Positive가 많아져 FP(0,1)와 TP(1,1)가 늘어났다. 반대로 Negative인 TN(0,0)과 FN(1,0)은 떨어졌다.
- TP가 47에서 49로 오름
- FP가 16에서 22로 오름 -> 재현율이 75%에서 79%로 오름
- TN가 101에서 95로 떨어짐
- FN이 15에서 13으로 떨어짐 -> 정밀도가 74%에서 69%로 떨어짐
🎯 재현율을 향상 시키면서 다른 수치를 어느 정도 감소하고 싶을 때 : 임곗값 0.45 선택 |
<그래프로 임계값에 따른 평가지표들 확인하기>
▶ 결론
- 임계값이 낮을수록 정밀도는 낮아지고 재현율은 높아진다.
- 임계값이 높을수록 정밀도는 높아지고 재현율은 낮아진다.
임계값을 이용해 정밀도, 재현율의 값들은 극단적인 수치 조작이 가능합니다. 따라서 정밀도 또는 재현율 중 하나만 스코어가 좋고 다른 하나는 스코어가 나쁜 분류는 성능이 좋지 않은 분류로 간주할 수 있습니다. 물론 분류가 정밀도 또는 재현율 중 하나에 상대적인 중요도를 부여해 각 예측 상황에 맞는 분류 알고리즘을 튜닝할 수 있지만, 그렇다고 정밀도/재현율 중 하나만 강조하는 상황이 되어서는 안됩니다. (예를들어, 암 예측 모델에서 재현율을 높인다고 걸핏하면 양성으로 판단할 경우 환자의 부담과 불평이 커지게 됩니다.) 정밀도와 재현율의 수치가 적절하게 조합돼 분류의 종합적인 성능 평가에 사용될 수 있는 평가 지표가 필요합니다. |
정밀도와 재현율의 종합적인 성능 평가에 사용될 수 있는 평가 지표는 다음 블로그에서 알아보겠습니다.
'머신러닝 (Machine Learning) > 분류(Classification) 분석' 카테고리의 다른 글
결정 트리의 과적합 (Overfitting) 시각화로 이해하기 (0) | 2021.02.14 |
---|---|
Decision Tree Graphviz (0) | 2021.02.14 |
결정 트리 (Decision Tree) (0) | 2021.02.13 |
분류의 평가(Evaluation) (2) F1 score , ROC AUC (0) | 2021.02.13 |
분류(Classification) (0) | 2021.02.04 |