사전 정밀도와 재현율
트레이드오프축

정밀도와 재현율

gabury1고친 사람 github-actions[bot]

정밀도와 재현율은 무언가를 골라내는 시스템의 실수를 두 방향에서 셉니다. 정밀도는 고른 것 가운데 맞은 것의 비율입니다. 재현율은 찾아야 할 것 가운데 건진 것의 비율입니다. 대개 한쪽이 오르면 다른 쪽이 내려가므로 어느 실수를 더 줄일지 정해야 합니다.

쉽고 빠른 이해

정밀도와 재현율은 골라내는 시스템을 두 방향에서 재는 한 쌍의 수입니다. 스팸 필터라면 정밀도는 스팸함에 넣은 메일 가운데 진짜 스팸의 비율입니다. 재현율은 진짜 스팸 가운데 스팸함에 넣은 메일의 비율입니다.

둘을 함께 보는 까닭은 한쪽만 보면 속기 때문입니다. 메일을 전부 스팸함에 넣어도 스팸은 하나도 안 놓칩니다. 가장 확실한 한 통만 넣어도 넣은 것은 전부 맞습니다.

두 수는 이렇게 맞섭니다.

  1. 필터가 메일마다 스팸일 가능성을 점수로 매깁니다
  2. 점수가 정해 둔 선을 넘는 메일만 스팸함에 넣습니다
  3. 선을 내리면 더 많이 넣습니다. 놓치는 스팸은 줄어듭니다. 잘못 넣는 메일은 늘어납니다

대가는 두 수 가운데 어느 쪽을 지킬지 정하는 일입니다. 놓치는 쪽이 더 비싼 일에서는 넓게 고릅니다. 잘못 고르는 쪽이 더 비싼 일에서는 좁게 고릅니다.

상세

어부가 그물을 넓게 던지면 잡으려던 물고기를 덜 놓칩니다. 그 대신 잡을 생각이 없던 물고기와 쓰레기도 함께 올라옵니다. 그물을 좁게 던지면 올라온 것은 거의 다 쓸모가 있습니다. 그 대신 빠져나간 물고기가 많습니다.

무언가를 골라내는 시스템도 이 두 방향 가운데 어느 쪽에 설지 정해야 합니다. 스팸 필터는 메일 가운데 스팸을 고릅니다. 검색 엔진은 문서 가운데 찾던 문서를 고릅니다. 알림은 서버의 흔들림 가운데 사람이 손써야 할 장애를 고릅니다.

이 문서는 두 방향을 한 축의 양 끝이라고 부릅니다. 적게 고르더라도 고른 것이 맞기를 바라는 끝이 「좁게 고르기」입니다. 헛것이 섞이더라도 빠짐없이 건지기를 바라는 끝이 「넓게 고르기」입니다.

좁게 고르기가 얼마나 이루어졌는지는 정밀도로 잽니다. 넓게 고르기가 얼마나 이루어졌는지는 재현율로 잽니다.

두 수가 세는 두 가지 실수

골라내는 시스템은 대상 하나하나에 「해당한다」 또는 「아니다」라는 판정을 내립니다. 「해당한다」는 판정을 양성, 「아니다」라는 판정을 음성이라고 부릅니다. 병원 검사에서 온 말입니다.

판정이 맞았으면 앞에 「참」을, 틀렸으면 「거짓」을 붙입니다. 맞게 고른 것은 참 양성입니다. 해당하지 않는 것을 잘못 고른 실수는 거짓 양성입니다. 해당하는 것을 놓친 실수는 거짓 음성입니다.

정밀도는 시스템이 고른 것 가운데 참 양성의 비율입니다. 식으로 쓰면 참 양성 수를 「참 양성 수 + 거짓 양성 수」로 나눈 값입니다. 잘못 고를수록 분모만 커져 이 수가 내려갑니다.

재현율은 정말 해당하는 것 가운데 참 양성의 비율입니다. 식으로 쓰면 참 양성 수를 「참 양성 수 + 거짓 음성 수」로 나눈 값입니다. 놓칠수록 분모만 커져 이 수가 내려갑니다.

두 수는 분자가 같고 분모만 다릅니다. 그래서 두 수는 서로 다른 실수를 하나씩 맡아 셉니다. 실수마다 깎이는 수와 그 실수를 줄이는 끝이 다릅니다.

실수 이름 깎이는 수 이 실수를 줄이는 끝
해당하지 않는 것을 골랐다 거짓 양성 정밀도 좁게 고르기
해당하는 것을 놓쳤다 거짓 음성 재현율 넓게 고르기

정밀도는 놓친 것을 모릅니다. 거짓 음성이 정밀도의 식 어디에도 없기 때문입니다. 거꾸로 재현율은 잘못 고른 것을 모릅니다.

그래서 한쪽 수만 보면 속습니다. 메일을 전부 스팸함에 넣는 필터는 스팸을 하나도 안 놓치니 재현율이 1입니다. 가장 확실한 한 통만 넣는 필터는 그 한 통이 스팸이면 정밀도가 1입니다. 두 필터 모두 쓸 수 없습니다.

판정 칸은 하나가 더 남습니다. 해당하지 않는 것을 맞게 안 고른 참 음성입니다. 스팸 필터라면 정상 메일을 받은편지함에 둔 경우입니다.

네 칸을 한 표에 늘어놓은 것이 혼동 행렬입니다. 행은 정말 해당하는지를, 열은 시스템이 골랐는지를 가릅니다.

고름 (양성) 안 고름 (음성)
정말 해당함 참 양성 거짓 음성
해당 안 함 거짓 양성 참 음성

정밀도의 분모는 「고름」 열의 두 칸입니다. 재현율의 분모는 「정말 해당함」 행의 두 칸입니다. 참 음성은 두 분모 어디에도 들지 않습니다. 다음 절의 정확도는 바로 이 칸 때문에 흐려집니다.

정확도 하나로 재면 안 보이는 것

판정이 맞은 것을 모두 세어 전체 수로 나눈 값이 정확도입니다. 혼동 행렬로 보면 참 양성과 참 음성을 더해 네 칸 전체로 나눈 값입니다. 수 하나로 끝나니 두 수를 따로 볼 필요가 없어 보입니다.

해당하는 것이 드물면 정확도는 두 실수를 가려 버립니다. 거래 천 건 가운데 사기가 한 건이라고 합시다.

모든 거래를 「정상」이라고 판정해도 정확도는 0.999입니다. 맞게 「정상」이라고 한 999건이 전부 참 음성으로 분자에 들어가기 때문입니다. 그런데 이 시스템의 재현율은 0입니다. 사기를 한 건도 못 잡았습니다.

「사기」와 「정상」처럼 판정이 가르는 갈래를 클래스라고 부릅니다. 한 클래스가 다른 클래스보다 훨씬 드문 상태가 클래스 불균형입니다. 골라내는 일은 대개 이 상태라서 정확도 대신 정밀도와 재현율을 봅니다.

두 수가 맞서는 까닭

많은 시스템은 대상마다 점수를 매긴 뒤 선 하나를 넘는 것만 고릅니다. 이 선이 임계값입니다. 스팸 필터라면 메일마다 스팸일 가능성을 0과 1 사이의 점수로 매깁니다. 그리고 점수가 임계값을 넘는 메일만 스팸함에 넣습니다.

두 수가 맞서는 까닭은 이 선 하나가 두 수를 함께 움직이기 때문입니다. 선을 내리면 더 많이 고릅니다. 점수가 애매하던 진짜 스팸이 걸려 재현율이 오릅니다. 같은 점수대에 있던 정상 메일도 함께 걸려 정밀도는 대개 내려갑니다.

점수가 애매한 구간에는 진짜와 헛것이 섞여 있습니다. 섞인 구간 안에 선을 긋는 한, 한쪽 실수를 줄이면 다른 쪽 실수가 늘어납니다.

짧은 코드로 보겠습니다. 메일 여섯 통에 필터가 매긴 점수와 정답을 나란히 적었습니다. labels 의 1은 진짜 스팸, 0은 정상 메일입니다. 함수 pr 은 임계값 t 를 받아 정밀도와 재현율을 차례로 돌려줍니다.

Python
scores = [0.95, 0.9, 0.8, 0.6, 0.4, 0.3]
labels = [1, 1, 0, 1, 0, 1]

def pr(t):
    picked = [y for s, y in zip(scores, labels) if s >= t]
    tp = sum(picked)
    return round(tp / len(picked), 2), tp / sum(labels)

pr(0.85)  # (1.0, 0.5)
pr(0.5)   # (0.75, 0.75)
pr(0.2)   # (0.67, 1.0)

picked 는 점수가 선을 넘은 메일의 정답만 모은 목록입니다. 그 안의 1을 더하면 참 양성 수가 됩니다. round 는 정밀도를 소수 둘째 자리까지 줄입니다.

선이 0.85면 두 통만 고릅니다. 둘 다 스팸이라 정밀도는 1입니다. 그러나 스팸 네 통 가운데 두 통을 놓쳐 재현율은 0.5입니다.

선을 0.2까지 내리면 여섯 통을 모두 고릅니다. 스팸을 하나도 안 놓쳐 재현율은 1이 됩니다. 대신 정상 메일 두 통이 섞여 정밀도는 0.67로 내려갑니다.

여섯 통을 점수 순으로 쌓고 세 선으로 가르면 섞인 구간이 보입니다. 층마다 제목에 그 선까지 골랐을 때의 두 수를 적었습니다.

flowchart TD
    subgraph L1["선 0.85까지 고름 · 정밀도 1.0 · 재현율 0.5"]
        M1["0.95 · 스팸"] --- M2["0.9 · 스팸"]
    end
    subgraph L2["선 0.5까지 고름 · 정밀도 0.75 · 재현율 0.75"]
        M3["0.8 · 정상 메일"] --- M4["0.6 · 스팸"]
    end
    subgraph L3["선 0.2까지 고름 · 정밀도 0.67 · 재현율 1.0"]
        M5["0.4 · 정상 메일"] --- M6["0.3 · 스팸"]
    end
    M2 --- M3
    M4 --- M5

맨 위 층은 스팸뿐입니다. 가운데와 아래 층에는 스팸과 정상 메일이 한 통씩 섞여 있습니다. 그래서 선을 한 층 내릴 때마다 스팸 한 통과 정상 메일 한 통을 함께 고르게 됩니다.

양 끝이 얻는 것과 내주는 것

두 끝은 서로 반대편을 내주고 얻습니다. 선을 두는 높이부터 잃는 것까지 두 끝이 하나하나 엇갈립니다.

좁게 고르기 넓게 고르기
임계값 높게 둔다 낮게 둔다
올라가는 수 정밀도 재현율
얻는 것 고른 결과를 믿고 바로 움직일 수 있다 찾아야 할 것을 덜 놓친다
내주는 것 점수가 애매한 진짜를 놓친다 헛것이 섞여 결과를 다시 확인하는 일이 는다
알림에서 생기는 일 놓친 장애를 사용자가 먼저 겪는다 장애가 아닌데 울리는 알림, 곧 거짓 경보에 지친 사람들이 알림을 흘려 본다

거짓 경보에 묻혀 알림을 흘려 보게 되는 상태를 알림 피로라고 부릅니다. 넓게 고르기 쪽으로 너무 간 알림에서 생깁니다.

두 끝이 내주는 것은 눈에 띄는 정도가 다릅니다. 잘못 고른 것은 결과 목록에 남아 누군가 보게 됩니다. 놓친 것은 목록에 없습니다. 정답을 따로 모아 세기 전에는 드러나지 않습니다.

끝을 정하는 조건

어느 끝이 맞는지는 틀렸을 때 치르는 값이 정합니다. 잘못 고른 것 하나와 놓친 것 하나 가운데 어느 쪽이 더 비싼지를 따집니다. 조건마다 택할 끝과 그 까닭이 갈립니다.

조건 택할 끝 까닭
놓친 하나가 잘못 고른 하나보다 비싸다 · 사기 거래 탐지 · 암 검진의 첫 검사 넓게 고르기 헛것은 나중에 확인하면 되지만 놓친 것은 다시 찾을 길이 없다
잘못 고른 하나가 놓친 하나보다 비싸다 · 스팸 필터 · 새벽에 사람을 깨우는 알림 좁게 고르기 중요한 메일이 스팸함으로 가거나 거짓 경보에 사람이 깬다
고른 것을 사람이 하나하나 확인한다 좁게 고르기 사람이 확인할 수 있는 양에 한도가 있다
뒤에 한 번 더 거르는 단계가 있다 넓게 고르기 헛것은 뒤 단계가 걸러 낸다. 앞에서 놓친 것은 뒤에서 살아나지 않는다
사용자가 결과의 위쪽 몇 건만 본다 · 검색 결과 첫 화면 좁게 고르기 위쪽에 헛것이 끼면 사용자가 바로 겪는다
빠진 하나가 결론을 바꾼다 · 소송에 낼 증거 문서 찾기 넓게 고르기 한 건만 빠져도 일이 틀어진다

조건 둘이 서로 다른 끝을 가리킬 때도 있습니다. 사기 거래는 놓치면 돈이 나갑니다. 정상 거래를 잘못 막으면 손님이 떠납니다. 그럴 때는 두 끝 사이의 한 점을 택하거나 일을 두 단계로 나눕니다.

두 끝 사이의 한 점을 택하는 방법

선을 어디에 둘지 정하려면 두 수를 하나의 기준으로 모아야 합니다. 흔히 쓰는 방법은 셋입니다.

첫째는 두 수를 수 하나로 합치는 것입니다. F1 점수는 두 수의 조화평균(Harmonic mean)입니다.

조화평균은 두 수 가운데 작은 쪽으로 크게 끌려 내려가는 평균입니다. 정밀도 1과 재현율 0.5를 보통으로 평균하면 0.75입니다. 조화평균은 약 0.67로 작은 쪽에 더 가깝습니다.

그래서 한쪽을 버리고 다른 쪽만 올린 선은 F1 점수가 낮게 나옵니다. 앞의 코드에 대 보면 선 0.85의 F1 점수가 방금 본 약 0.67입니다. 선 0.5는 0.75, 선 0.2는 0.8입니다. 이 기준으로는 선 0.2를 택합니다.

둘째는 한쪽에 무게를 더 주는 것입니다. F1 점수는 두 수를 같은 무게로 봅니다. F-베타 점수는 베타라는 수로 그 무게를 옮깁니다.

베타가 1보다 크면 재현율에, 1보다 작으면 정밀도에 무게가 실립니다. F1 점수의 1은 베타가 1이라는 뜻입니다.

셋째는 한쪽에 하한을 거는 것입니다. 「재현율은 0.95 아래로 내려가면 안 된다」처럼 한쪽 수의 조건을 먼저 정합니다. 그 조건을 지키는 선 가운데 다른 쪽 수가 가장 높은 선을 택합니다.

선을 조금씩 옮기며 두 수를 점으로 찍어 이으면 곡선이 하나 나옵니다. 이것이 정밀도-재현율 곡선입니다. 앞의 코드에서 선 셋이 낸 세 점만 찍어도 모양이 보입니다.

xychart-beta
    title "선 0.85 · 0.5 · 0.2 에서 찍은 세 점"
    x-axis "재현율" ["0.5", "0.75", "1.0"]
    y-axis "정밀도" 0 --> 1
    line [1.0, 0.75, 0.67]

오른쪽으로 갈수록 재현율이 오르고 정밀도가 내려갑니다. 이 곡선은 한 시스템이 설 수 있는 점을 모두 보여 줍니다. 위 세 방법은 이 곡선 위에서 한 점을 택하는 규칙입니다.

두 단계로 나눠 양 끝을 함께 얻는 구조

한 번의 판정으로는 양 끝을 다 얻을 수 없습니다. 대신 일을 두 단계로 나누면 두 끝을 차례로 맡길 수 있습니다. 앞 단계는 넓게 고릅니다. 뒤 단계는 앞 단계가 건진 후보 안에서 좁게 고릅니다.

flowchart TD
    A["전체 대상"] --> B["앞 단계 · 넓게 고르기"]
    B --> C["후보 · 헛것이 섞여 있다"]
    B -.-> X["앞 단계가 놓친 것 · 다시 안 돌아온다"]
    C --> D["뒤 단계 · 좁게 고르기"]
    D --> E["최종 결과"]

검진이 이 구조입니다. 첫 검사는 병을 덜 놓치도록 넓게 잡습니다. 첫 검사에서 양성이 나온 사람만 정밀 검사를 한 번 더 받습니다.

검색 엔진도 같습니다. 먼저 후보 문서를 넉넉히 뽑습니다. 그다음 후보의 순서를 다시 매겨 위쪽에 올릴 문서를 고릅니다.

이 구조에서 앞 단계는 재현율로 잽니다. 그림의 점선처럼 앞에서 놓친 것은 뒤 단계로 넘어가지 않습니다. 뒤 단계가 아무리 잘 골라도 되살릴 수 없습니다. 뒤 단계는 정밀도로 잽니다.

맞바꿈이 생기지 않는 경우

맞바꿈은 점수가 애매한 구간에 진짜와 헛것이 섞여 있어서 생깁니다. 섞인 구간이 없으면 어느 끝을 택할 일도 없습니다. 모든 진짜가 모든 헛것보다 높은 점수를 받으면 그 사이에 선을 그을 수 있습니다. 그 선에서는 정밀도와 재현율이 둘 다 1입니다.

점수를 더 잘 매기는 필터를 떠올려 봅시다. 앞의 코드에서 scores 는 손대지 않고 정답만 다시 늘어세우면 됩니다. 스팸 네 통이 위쪽 네 점수를 받습니다. 정상 메일 두 통은 아래쪽 두 점수를 받습니다.

Python
labels = [1, 1, 1, 1, 0, 0]
pr(0.5)   # (1.0, 1.0)

선을 0.5에 두면 스팸 네 통만 고릅니다. 정상 메일은 하나도 안 고릅니다. 두 수가 함께 1이 됩니다.

flowchart TD
    subgraph P["선 0.5 위 · 고름 · 정밀도 1.0 · 재현율 1.0"]
        N1["0.95 · 스팸"] --- N2["0.9 · 스팸"] --- N3["0.8 · 스팸"] --- N4["0.6 · 스팸"]
    end
    subgraph Q["선 0.5 아래 · 안 고름"]
        N5["0.4 · 정상 메일"] --- N6["0.3 · 정상 메일"]
    end
    N4 --- N5

앞의 층 그림과 견주면 섞인 층이 사라졌습니다. 선 위에는 스팸만, 선 아래에는 정상 메일만 있습니다.

그래서 두 수를 함께 올리는 길은 선을 옮기는 것이 아니라 점수를 고치는 것입니다. 점수가 진짜와 헛것을 더 잘 가르면 같은 재현율에서 정밀도가 더 높은 점을 택할 수 있게 됩니다.

관련 항목

두 수를 계산하는 판정 칸

혼동 행렬 · 참 양성 · 거짓 양성 · 거짓 음성 · 참 음성 · 오탐 · 미탐

이 축의 양 끝을 재는 지표

정밀도 · 재현율 · 특이도 · 상위 k 정밀도 · 상위 k 재현율 · 평균 정밀도

두 끝 사이의 한 점을 고르는 지표와 곡선

F1 점수 · F-베타 점수 · 조화평균 · 정밀도-재현율 곡선 · ROC 곡선 · AUC · 운영점

이 축 위의 점을 옮기는 판정 기준

임계값 · 분류 · 이진 분류 · 분류기 · 결정 경계 · 확률 보정

이 축에서 끝을 골라야 하는 시스템

스팸 필터 · 검색 · 검색 엔진 · 알림 · 이상 탐지 · 침입 탐지 시스템 · 사기 탐지 · 추천 시스템 · 표제어 추출

양 끝을 나눠 맡는 두 단계 구조

후보 생성 · 재순위화 · 캐스케이드 분류기 · 선별 검사

이 축을 흐리는 평가 문제

정확도 · 클래스 불균형 · 테스트 세트 · 데이터 누수 · 과적합

넓게 고르기에 치우치면 커지는 운영 부담

알림 피로 · 거짓 경보 · 온콜 · 페이지

나란히 놓이는 다른 맞바꿈 축

편향과 분산 · 시간과 공간 맞바꿈 · CAP · 지연과 처리량

다른 이름: precision and recall · precision-recall tradeoff · 정밀도-재현율 트레이드오프 · 정밀도 대 재현율