Precision? Recall? 쉽게 알아보자!
-
date_range 28/04/2020 10:23 perm_identity 박상민 infosortInterpretable-Machine-Learninglabel
Introduction
분류 문제(Classification)에서 가장 일반적으로 사용되는 평가 척도는 정확도(Accuracy)입니다. 일반적으로 사용되는 이유는 매우 직관적이라는 장점 때문입니다. 그러나, 재현률(Recall), 정밀도(Precision)과 같은 평가 척도는 들어본적이 있지만 대략적으로 아는 경우가 많아 이를 설명하고자 합니니다. 사실 제가 헷깔려서 정리했습니다. 다음과 같은 오차 행렬(Confusion Matrix)이 존재한다고 가정하고 설명하겠습니다.
여기에서 정확도는 실제, 예측에서 모두 동일한 결과를 보인 값에서 전체 관측값의 수를 나누면 된다고 말할 수 있습니다. 수식으로 표현하자면 다음과 같습니다.
\[Accuracy =(TN+TP)/(TN+FP+FN+TP)\]그런데, 개인적으로 수식을 통해 이해하는 방법으로 정밀도(Precision), 민감도(Recall)을 설명하게 되면 이해가 잘 가지 않더라구요… 따라서 우리는 예시를 들어 위에서 등장한 오차행렬을 박살내보겠습니다.
Case Study with COVID-19
Accuracy
최근 코로나19 사태에 대한 관심이 매우 높습니다. 상황을 한 번 만들어보죠. 저는 경기도 고양시에 살고 있으니, 고양시를 기준으로 예를 들어보겠습니다. 지금부터 나오는 예시는 모두 사실과 다른 내용입니다.
현재, 인천국제공항을 통해 입국한 고양시민은 모두 킨텍스라는 곳에서 코로나 19 검사를 받아야합니다. 2020년 4월 28일 인천국제공항에서 킨텍스로 이동하여 코로나 19 검사를 받은 사람은 10명입니다. 진단 키트를 이용하여 검사 후, 며칠 뒤 확진자를 가려낸 결과, 70%라는 정확도(Accuracy)를 보인다는 것을 알 수 있었습니다. 진단 키트가 ‘정확하게’ 진단한 경우가 10건 중 7건이기 때문입니다.
그러면 ‘이 진단 키트는 70% 정확하다’라고 말할 수 있을까요? 사실, 이런 진단 키트의 정확성을 따질 때에는 정확도(Accuracy)만 이용하는 것은 그다지 좋은 방법이 아닙니다. 확진자를 정확하게 진단하는 것도 중요하지만, 확진자를 비확진자로 잘못 분류할 확률도 따져야 합니다. 만약, 확진자를 비확진자로 잘못 분류하여 슈퍼 전파자가 된다면… 뒷 내용은 생략하겠습니다. 이와 같은 평가 척도를 Recall(재현율)이라고 부릅니다.
Recall
재현율(Recall)은 실제로 양성인 시민을 확진자로 분류할 확률입니다. 수식은 간단합니다.
\[Recall=TP/(TP+FN)\]위 오차 행렬에서 재현율을 구하면 6/(1+6) = 0.857이 나옵니다. 이를 해석해보자면, ‘코로나 19에 실제로 감염된 시민은 7명인데, 진단 키트가 그 중 6명은 잡아냈다‘라고 이해할 수 있습니다. 따라서 재현율 측면에서 이 진단 키트의 정확성은 85.7%라고 볼 수 있습니다.
Precision
정밀도(Precision)은 확진자로 분류된 사람들 중 실제 양성 시민일 확률입니다. 역시 수식은 간단합니다.
\[Precision=TP/(FP+TP)\]위 오차 행렬에서 정밀도를 구하면 6/(2 + 6) = 0.75가 나옵니다. 이를 해석해보자면, ‘진단 키트가 확진자로 판정한 시민은 8명인데, 그 중 6명만 실제로 감염된 사람이다’라고 이해할 수 있습니다. 따라서, 정밀도 측면에서 이 진단 키트의 정확성은 75%라고 볼 수 있습니다.
Recall과 Precision을 Python으로 계산한 코드는 다음과 같습니다.
import numpy as np
import pandas as pd
from sklearn.metrics import confusion_matrix
truth = np.array([0,1,1,1,1,1,1,0,1,0])
prediction = np.array([0,1,1,1,1,1,1,1,0,1])
mat = confusion_matrix(truth, prediction)
tn = mat[0][0]
fp = mat[0][1]
fn = mat[1][0]
tp = mat[1][1]
print("True Negative:", tn) # False를 False라고 분류
print("False Positive:", fp) # False를 True라고 분류
print("False Negative:", fn) # True를 False라고 분류
print("True Positive:", tp) # True를 True라고 분류
acc = (truth == prediction).sum()/len(truth) * 100
print('Accuracy: ', round(acc,2), '%')
precision = tp / (tp + fp) # True를 True라고 분류 / True라고 분류
# 환자로 분류한 사람들 중 실제 환자일 확률
print("Precision: ", precision)
recall = tp / (tp + fn) # True를 True라고 분류 / 실제 True
print("Recall: ", recall)
# 실제 환자를 환자로 분류할 확률
Recall vs Precision
그렇다면, 코로나 19 진단 키트에 대한 정확성은 어떤 지표를 이용해야 할까요? 먼저 Precision을 평가 지표로 사용한다고 가정하겠습니다. 진단 키트가 확진자로 판정한 시민 8명을 모두 격리 시설에 격리했습니다. 여기서 실제로 감염되지 않은 2명은 피해를 받겠지만, 결과적으로 모든 확진자 격리를성공했다는 것을 알 수 있습니다.
Recall을 평가 지표를 사용한다면 이야기 조금 달라집니다. 실제 감염자 중 진단 키트가 확진자로 판정한 6명을 모두 격리 시설에 격리했습니다. 여기서 치명적인 문제가 발생합니다. 진단 키트가 확진자로 판정하지 못한 1명은 격리되지 않고 그대로 집으로 가서 사회 생활을 할 것입니다. 물론, 2주간의 자가 격리를 해야하겠지만 이를 어기고 사회생활을 수행하게 되면 어떻게 될까요? 슈퍼 전파자가 될 수도 있는 매우 위험한 상황이 발생할 것입니다.
So What?
결과적으로, 코로나 19 진단 키트를 평가하는 방법은 정확도(Accuracy)만을 사용해서는 안된다는 것을 알 수 있습니다. 따라서 진단 키트의 평가 지표는 Recall = 1.0이라는 조건 하(적어도 감염된 시민 만큼은 진단키트가 확진자로 분류한다는 조건)에서 Precision을 측정하는 것이 바람직할 것입니다. 여기서 ‘적어도’라는 의미는 Recall이 1이 되기 위한 최소 조건입니다. 감염된 시민만 모두 확진자로 분류한다면, 비감염 시민을 어떻게 분류하던 Recall은 무조건 1이 될 것입니다. 또한, 진단 키트가 완벽하게 감염자와 비감염자를 분류해낸다면, Recall과 Precision은 모두 1이 될것입니다. 이 진단 키트는 완벽한 진단 키트라고 말할 수 있죠. 반면, 모든 환자를 양성이라고 판정한 진단키트는 Recall이 1이되겠지만, Precision은 떨어질 것입니다.
Evaluation
F1-Score
A 진단 키트와 B 진단 키트가 존재한다고 가정합니다. A 진단 키트와 B 진단 키트 중 무엇이 더 좋은 성능을 보이는 키트일까요? 두 키트는 모두 Recall = 1.0이라는 조건을 만족하고 A 진단 키트는 Precision이 0.7, B 진단 키트는 Precision이 0.6이라고 하겠습니다. 물론, Recall이 같다는 조건으로 인하여 Precision만을 이용해 키트를 비교하는 방법이 가장 편한 방법이지만, 여기에선 F1-Score에 대해 소개하고자 합니다. F1-Score의 수식은 다음과 같습니다.
\[F1=2 \times \frac{Precision \times Recall}{Precision + Recall}\]위 수식을 이용하여 A 진단 키트와 B 진단 키트를 비교해보면, A_F1 = 0.823, B_F1 = 0.75가 나오게 됩니다. 따라서 A 진단 키트가 더 좋은 성능을 보이는 진단 키트라고 볼 수 있습니다.
Precision Recall Trade - Off
앞서 진단키트가 감염된 시민을 모두 확진자로 비감염 시민을 비확진자로 분류했다면 이는 최고의 진단키트가 될 것이라 언급했습니다. 이 경우, Precision과 Recall은 모두 1이 될 것이라고 말했었죠. 그러나 대부분의 실제 상황에선 데이터에 노이즈가 존재하여 완벽하게 분류하기 어렵습니다.
일반적으로 머신러닝에서 분류기(Classifier)는 결정 함수(Decision Function)을 사용하여 각 관측값의 점수를 계산합니다. 우리는 이미 앞에서 진단 키트를 예시로 들었기 때문에, 여기서는 진단 키트가 분류기라고 가정하겠습니다. 각 관측값의 점수와 임곗값(Threshold)를 비교하여, 보다 크면 관측값을 양성으로 판정하고(확진자로 판정) 보다 작다면 관측값을 음성으로 판정(비확진자로 판정)합니다.
결정 함수에 임곗값이니 벌써 머리가 아파… 보다 쉽게 이해하기 위해서 아래 그림을 통해 설명하겠습니다. 분류기를 통해 관측값(여기에서는 검사받은 시민)에 대한 점수를 계산했습니다. 먼저 중간의 임곗값을 이용하여 정밀도를 계산합니다. 임곗값보다 크다면 양성으로 판정을 하기 때문에, 거짓 양성(False Positive)는 1이 존재합니다. 따라서 Precision 수식을 적용하게되면 4/5 = 0.8이 나오게 됩니다. 다시, 재현율을 계산해보겠습니다. 전체 감염자 수는 7이 되고 임곗값보다 큰 경우 양성 판정을 하기 때문에 4/7 = 0.57이 됩니다. 나머지 임곗값에 대한 정밀도와 재현율은 직접 구해보세요 :)
이 그림을 통해 확인해본 결과, 임계값에 따라 정밀도와 재현율이 어느정도 반비례한다는 것을 알 수 있습니다. 이를 정밀도 - 재현율 Trade-off 관계 라고 부릅니다.