분류 임계값 설정: 오탐·미탐 비용과 정밀도·재현율로 결정하기
분류 임계값 설정은 모델 점수를 0과 1로 바꾸는 사소한 후처리가 아니다. 같은 예측 확률을 사용하더라도 임계값에 따라 자동 차단, 사람 검토, 승인처럼 실제로 실행되는 행동과 그 비용이 달라진다. 기본값 0.5는 API가 제공하는 출발점일 뿐 업무에 가장 유리한 값이라는 보장은 없다.
이 글은 2026년 8월 5일 확인한 공식 문서와 고정된 합성 입력의 통제 비교를 바탕으로, 비용 행렬과 정밀도·재현율 제약에서 운영점을 고르는 절차를 설명한다. 합성 비교는 오류 비용과 양성률 변화의 효과를 분리해 보기 위한 계산이며, 실제 서비스나 HuntLab 모델의 운영 성능을 측정한 결과는 아니다.
임계값은 모델이 아니라 행동 정책에 속한다
predict_proba가 내놓는 확률이나 decision_function의 연속 점수는 모델이 사례를 어떻게 평가했는지 나타낸다. 임계값은 그 평가를 어느 지점에서 양성 행동으로 바꿀지 정하는 정책이다. scikit-learn도 확률을 학습하는 통계 문제와 구체적인 행동을 고르는 결정 문제를 구분한다.
따라서 첫 질문은 “정밀도와 재현율 중 무엇이 더 좋은가”가 아니다. 양성 판정 뒤에 무엇을 할지부터 정해야 한다. 자동 차단인지, 사람이 다시 검토할지, 알림만 보낼지에 따라 오탐(false positive, FP) 한 건과 미탐(false negative, FN) 한 건의 의미가 달라진다.
운영 정책을 쓰기 전에 다음 값을 문서화한다.
- FP와 FN 한 건이 만드는 금전·시간·안전·고객 경험 비용
- 양성 예측을 실제로 처리할 수 있는 용량
- 반드시 지켜야 할 최소 정밀도, 최소 재현율 또는 최대 FPR
- 양성 클래스와 라벨이 확정되는 시점
비용을 하나의 숫자로 합의할 수 있다면 총비용을 최소화할 수 있다. 비용 합의가 어렵지만 서비스 조건이 명확하다면 “정밀도 0.80 이상인 후보 중 재현율 최대”처럼 제약을 먼저 걸 수 있다. F1이나 정확도는 이런 운영 계약을 대신하지 못한다.
비용 행렬을 후보 임계값 표로 바꾼다
올바른 판정의 비용을 0으로 두고, 보정된 양성 확률을 p라고 하자. 양성으로 행동할 기대비용은 C_FP × (1-p), 음성으로 행동할 기대비용은 C_FN × p다. 이 단순한 조건에서는 다음 경계가 출발점이 된다.
p >= C_FP / (C_FP + C_FN)
FP 비용이 1이고 FN 비용이 5라면 이론 경계는 약 0.167이다. 다만 점수가 실제 사후확률로 보정됐고, 사례별 비용이 일정하며, 행동이 둘뿐이고, 현재 데이터 분포가 비용을 정한 시점과 맞아야 이 식을 그대로 해석할 수 있다. 점수가 0.1, 0.3처럼 이산적으로만 존재하면 실제 후보 중 최저비용점은 이론 경계와 다를 수 있다.
통제 비교에서는 0.9·0.7·0.5·0.3·0.1의 다섯 점수 구간에 각각 10개 사례를 두고, 구간별 관측 양성률이 점수와 일치하도록 구성했다. score >= threshold 규칙으로 계산한 결과는 다음과 같다.
| 임계값 | TP | FP | FN | TN | 정밀도 | 재현율 | 예측 양성률 | 비용: FP=1, FN=5 |
|---|---|---|---|---|---|---|---|---|
| 0.9 | 9 | 1 | 16 | 24 | 0.900 | 0.360 | 0.200 | 81 |
| 0.7 | 16 | 4 | 9 | 21 | 0.800 | 0.640 | 0.400 | 49 |
| 0.5 | 21 | 9 | 4 | 16 | 0.700 | 0.840 | 0.600 | 29 |
| 0.3 | 24 | 16 | 1 | 9 | 0.600 | 0.960 | 0.800 | 21 |
| 0.1 | 25 | 25 | 0 | 0 | 0.500 | 1.000 | 1.000 | 25 |
FN이 FP보다 다섯 배 비싼 조건에서는 임계값 0.3의 총비용 21이 가장 낮았다. 비용을 뒤집어 FP를 5, FN을 1로 두자 최저비용점은 임계값 0.9로 이동했고 비용은 21, 정밀도는 0.900, 재현율은 0.360이었다. 모델 점수는 그대로인데 업무 비용만 바꿔도 선택할 임계값이 달라진다.
비용 대신 정밀도 0.80 이상을 필수 조건으로 두면 이야기가 또 달라진다. 조건을 통과하는 후보 가운데 재현율이 가장 높은 값은 임계값 0.7이며 재현율은 0.640이다. 실무 후보표에는 혼동 행렬과 정밀도·재현율뿐 아니라 예측 양성 수, 총비용, 제약 통과 여부를 함께 둬야 하는 이유다.

PR 곡선은 후보를 보여줄 뿐 정책을 정하지 않는다
정밀도는 양성이라고 예측한 사례 중 실제 양성의 비율이고, 재현율은 실제 양성 중 찾아낸 비율이다. PR 곡선은 여러 임계값에서 가능한 두 값의 조합을 보여준다. 희소한 양성에 대한 예측 품질을 살펴볼 때 유용하지만, 어느 점의 비용이 더 낮은지 또는 검토 용량을 넘는지는 알려주지 않는다.
임계값을 높이면 보통 예측 양성이 줄어 재현율은 낮아지거나 같아진다. 정밀도는 대체로 높아질 수 있지만 반드시 단조 증가하지는 않는다. 제거되는 사례에 TP와 FP가 어떤 순서로 섞였는지에 따라 흔들릴 수 있기 때문이다. 곡선의 점을 실제 임계값, 예측 양성 수, 혼동 행렬과 다시 연결해야 한다.
PR의 기준선도 고정돼 있지 않다. 기준선은 양성 prevalence에 의존하므로 서로 다른 양성률에서 얻은 PR 면적을 그대로 비교하면 운영 차이를 모델 차이로 오해할 수 있다. average_precision_score로 계산한 AP와 사다리꼴 방식의 PR-AUC도 같은 값이 아닐 수 있으므로 보고서에는 사용한 구현을 명시한다.
F1 최대점 역시 자동 정답이 아니다. F1은 정밀도와 재현율의 조화평균이지만 TN을 사용하지 않고 FP와 FN의 실제 업무 비용도 입력받지 않는다. 비용을 모를 때 후보를 압축하는 보조 지표로는 쓸 수 있어도, 비대칭 오류 비용이나 검토 용량이 있는 서비스의 목적함수로 바로 채택해서는 안 된다.
비용 공식을 쓰려면 먼저 확률 보정을 확인한다
비용 경계식은 점수 0.8을 실제 사건 확률 80%처럼 읽을 수 있다는 전제에 기대고 있다. 보정된 분류기라면 0.8 근처로 예측한 사례들의 관측 양성률도 약 0.8이어야 한다. decision_function의 순위 점수를 확률로 간주해 같은 식에 넣으면 이 전제가 성립하지 않는다.
보정 상태는 reliability diagram에서 점수 구간별 평균 예측확률과 관측 양성률을 비교해 확인한다. Brier loss와 log loss도 함께 볼 수 있지만, Brier에는 보정 외의 요소도 포함되므로 값 하나만으로 보정 우위를 단정하지 않는다.
데이터 독립성도 중요하다. 모델 학습, 보정, 임계값 선택과 최종 평가는 다음 경계를 지켜야 한다.
- 모델은 학습 데이터에서 적합한다.
- 보정기는 모델이 보지 않은 데이터 또는 out-of-fold 예측에 적합한다.
- 임계값은 학습 데이터가 아닌 검증 예측에서 선택한다.
- 모델·보정기·임계값을 잠근 뒤 미사용 테스트에서 한 번 평가한다.
scikit-learn의 CalibratedClassifierCV는 교차검증으로 보정기를 학습한다. sigmoid는 작은 표본에서 상대적으로 안정적일 수 있지만 오차 형태 가정이 맞지 않을 수 있고, isotonic은 더 유연한 대신 작은 표본에서 과적합하기 쉽다. 각 fold의 학습·보정 부분에는 모든 클래스가 존재해야 한다.
검증 데이터에서 선택하고 테스트 데이터에서는 평가한다
임계값도 여러 후보 중 선택되는 값이므로 하이퍼파라미터와 같은 누출 위험이 있다. 테스트 점수를 확인하면서 임계값을 반복 수정하면 테스트 정보가 정책에 들어간다. 그 뒤의 테스트 지표는 더 이상 잠긴 파이프라인의 정직한 일반화 평가가 아니다.
데이터가 충분하다면 역할을 명확히 나눈다.
- train: 모델 파라미터를 학습한다.
- calibration/validation 또는 out-of-fold 예측: 보정기를 적합하고 비용·제약에 맞는 임계값을 선택한다.
- test: 잠긴 모델·보정기·임계값의 비용, 정밀도, 재현율, FPR, 예측 양성률을 한 번 보고한다.
- production: 지연 라벨이 쌓인 뒤 기간과 세그먼트별로 같은 지표와 보정 상태를 다시 평가한다.
무작위 분할이 언제나 안전한 것도 아니다. 시간에 의존하는 자료는 시간 인지 분할이 필요하고, 사용자·장비·기관 같은 그룹 구조가 있다면 같은 그룹이 학습과 평가 양쪽에 섞이지 않게 해야 한다. 미래 데이터가 과거의 임계값 선택에 들어가거나 같은 사용자의 레코드가 양쪽에 걸치면 성능이 부풀 수 있다.
다음 Python 코드는 공식 scikit-learn API에 근거한 후보 계산 골격이다. 조사 환경의 Python 3.8.2에는 scikit-learn이 설치돼 있지 않아 이 API 예제 자체는 로컬에서 실행하지 못했다.
import numpy as np
from sklearn.metrics import precision_recall_curve
# y_val과 p_val은 모델 학습에 쓰지 않은 검증 레이블과 보정 확률이다.
precision, recall, thresholds = precision_recall_curve(y_val, p_val)
# 마지막 precision/recall 원소에는 대응하는 threshold가 없다.
rows = []
for t, p, r in zip(thresholds, precision[:-1], recall[:-1]):
pred = p_val >= t
fp = np.sum((y_val == 0) & pred)
fn = np.sum((y_val == 1) & ~pred)
cost = c_fp * fp + c_fn * fn
rows.append((t, p, r, cost, pred.mean()))
feasible = [row for row in rows if row[1] >= min_precision]
chosen = max(feasible, key=lambda row: row[2])
TunedThresholdClassifierCV를 사용한다면 기본 metric에 맡기지 말고 업무 비용이나 올바른 pos_label을 반영한 scorer를 명시해야 한다. 공식 문서는 특히 cv="prefit"일 때 모델을 학습한 데이터와 임계값 조정 데이터를 같게 쓰지 말라고 경고한다.
양성률이 바뀌면 같은 임계값의 정밀도도 무너질 수 있다
운영 환경의 양성률, 즉 base rate가 바뀌면 임계값을 고를 때 보았던 정밀도가 유지되지 않을 수 있다. 순수한 prior shift를 가정해 TPR과 FPR이 그대로라면 정밀도는 다음처럼 prevalence에 의존한다.
precision = TPR × prevalence / (TPR × prevalence + FPR × (1-prevalence))
통제 비교에서 임계값 0.5의 재현율 0.840과 FPR 0.360을 유지한 채 prevalence만 0.500에서 0.100으로 낮췄다. 정밀도는 0.700에서 0.206으로 떨어졌다. 모델의 클래스별 판정률이 그대로여도 경보 가운데 실제 양성이 차지하는 비율은 크게 달라질 수 있다.
이 결과를 모든 분포 변화에 일반화해서는 안 된다. 비교는 양성 사례와 클래스별 판정률을 유지하고 음성 가중치만 아홉 배로 늘린 합성 조건이다. 실제 환경에는 표본 오차, 시간·그룹 상관, 라벨 지연뿐 아니라 P(X|Y) 또는 P(Y|X)까지 달라지는 covariate·concept shift가 있을 수 있다. prior 보정만으로 이런 변화를 해결할 수는 없다.
배포 후에는 다음 변화가 임계값 재검토 신호가 된다.
- 전체 및 핵심 세그먼트의 prevalence 변화
- 예측 양성률, 검토 큐 길이, FP 이의제기율 변화
- 지연 정답 기준 정밀도·재현율·FPR·총비용의 제약 이탈
- reliability diagram 또는 Brier·log loss 악화
- 데이터 수집 경로, 정책, 오류 비용이나 후속 행동의 변경
라벨 정의나 양성 판정 뒤의 행동 자체가 바뀌었다면 임계값만 다시 맞출 문제가 아니다. 예측 목표와 비용 행렬부터 다시 정의해야 한다.
채택 조건은 최저 점수보다 명시적인 운영 계약이다
임계값은 비용 행렬 또는 서비스 제약이 승인되고, 독립 검증에서 선택한 점이 미사용 테스트와 예상 운영 base rate에서도 조건을 만족할 때 채택한다. 임계값 근처의 표본 수와 신뢰구간도 확인해 작은 수치 차이를 확정적인 우위로 해석하지 않는다.
반대로 확률 보정 상태를 확인하지 못했거나, 테스트를 보며 값을 반복 조정했거나, 운영 양성률과 처리 용량이 검증 조건과 다르다면 채택을 보류해야 한다. prevalence, 보정, 처리 용량 또는 오류 비용이 바뀌면 재검토하며, F1이나 정확도가 좋아졌다는 이유만으로 운영점을 교체하지 않는다.
운영 비용과 최소 정밀도·재현율을 표로 적은 뒤 검증 데이터에서 임계값 후보를 계산해 보라. 그 표가 있어야 0.5를 유지하는 결정도, 다른 값으로 옮기는 결정도 재현 가능한 정책이 된다.
참고 링크
- scikit-learn: Tuning the decision threshold for class prediction
- scikit-learn: Probability calibration
- scikit-learn: Cross-validation
- scikit-learn: Precision-Recall
- Google for Developers: Thresholds and the confusion matrix
- Saito & Rehmsmeier (2015)
- Saerens, Latinne, Decaestecker (2002)
- Lipton, Elkan, Narayanaswamy (2014)