배치·순차 설정의 ML 불확실성 정량화: 컨포멀 예측에 e-value를 통합하면 무엇이 달라지는가
ML 모델을 프로덕션에 배포할 때 가장 곤혹스러운 순간 중 하나는 "이 예측, 얼마나 믿을 수 있나요?"라는 질문을 받는 때입니다. 정확도나 F1 점수는 과거의 성능을 요약할 뿐이고, 지금 이 순간 모델이 얼마나 확신하는지를 통계적으로 보증하기란 쉽지 않습니다. 컨포멀 예측(Conformal Prediction)은 이 문제를 정면으로 다루는 프레임워크로, 모델 구조나 데이터 분포에 대한 강한 가정 없이도 "이 예측 집합에 실제 정답이 들어 있을 확률은 95% 이상"이라는 통계적 보장을 제공합니다. 그런데 2025년 arXiv:2503.13050 "E-Values Expand the Scope of Conformal Prediction" 논문이 공개되면서, 기존 방식이 흔들리던 조건에서도 유효성을 지키는 방법이 체계적으로 제시되었습니다. 배치 수를 알 수 없는 순차 환경에서 p-value 기반 방식은 유효성 보장이 깨지지만, e-value는 임의 시점에서도 커버리지를 지킵니다.
이 글은 컨포멀 예측 개념을 한 번쯤 접해봤거나, 불확실성 추정의 필요성은 알지만 구현은 처음인 ML 엔지니어·백엔드 개발자를 대상으로 합니다. 이 글에서 다루는 내용: e-value의 핵심 원리, 배치·순차 설정에서의 파이썬 구현, 퍼지 예측 집합. 다루지 않는 내용: 베팅 함수의 최적 설계(논문 수준 이론), 온라인 컨포멀의 스텝 사이즈 이론(다음 글 예정). 마르코프 부등식, 슈퍼마팅게일 등 통계 용어가 등장하지만, 각 용어에 직관적 설명을 함께 달아두었습니다. 이론적 엄밀함보다 코드 실행에 집중하고 싶다면 박스 인용구 부분은 건너뛰어도 핵심 흐름을 따라가실 수 있습니다.
핵심 개념
컨포멀 예측 — 모델-무관 불확실성 보장
컨포멀 예측의 아이디어는 단순합니다. 새로운 입력 x에 대해 "후보 레이블 y가 기존 데이터와 얼마나 잘 어울리는가(conformity)"를 점수로 측정하고, 그 점수가 일정 기준 이상인 레이블들을 예측 집합으로 묶는 것입니다. 단 하나의 가정만 필요합니다.
교환 가능성(Exchangeability): 데이터 포인트들의 순서를 임의로 섞어도 결합 분포가 변하지 않는다는 조건입니다. i.i.d.보다 약한 조건으로, 컨포멀 예측의 유효성 보장은 이 가정 하나에만 의존합니다.
이 교환 가능성 하에서, 지정한 오류율 α에 대해 실제 레이블이 예측 집합에 포함될 확률을 1−α 이상으로 보장할 수 있습니다.
import numpy as np
from sklearn.ensemble import RandomForestClassifier
def split_conformal_predict(clf, cal_X, cal_y, test_X, alpha=0.05):
"""
Split Conformal Prediction (p-value 방식) 기본 구조.
보정 집합으로 비적합 점수를 계산하고
임계값 이상의 레이블을 예측 집합으로 반환합니다.
"""
# 소프트맥스 확률 기반 비적합 점수: 1 - 정답 클래스의 예측 확률
cal_probs = clf.predict_proba(cal_X)
cal_scores = 1 - cal_probs[np.arange(len(cal_y)), cal_y]
# (1-α) 분위수를 임계값으로 사용
n = len(cal_scores)
threshold = np.quantile(cal_scores, np.ceil((n + 1) * (1 - alpha)) / n)
# 테스트 데이터에 대해 임계값 이하인 레이블을 예측 집합으로 포함
test_probs = clf.predict_proba(test_X)
prediction_sets = []
for probs in test_probs:
scores = 1 - probs
pred_set = np.where(scores <= threshold)[0].tolist()
prediction_sets.append(pred_set)
return prediction_setse-value — 베팅 배율로 표현하는 증거의 강도
p-value가 "귀무가설이 참일 때 이 정도 극단적인 결과가 나올 확률"을 표현한다면, e-value는 "귀무가설에 반하는 증거의 크기"를 베팅 배율로 표현합니다. 수학적으로 e-value E는 귀무가설 H₀ 하에서 기댓값이 1 이하인 비음수 확률 변수입니다.
E[E | H₀] ≤ 1이 단순한 성질에서 강력한 세 가지 특성이 나옵니다.
| 특성 | 설명 | 실용적 의미 |
|---|---|---|
| 곱셈 합산 | 독립 e-value의 곱 E₁ × E₂ × ··· 도 유효한 e-value | 배치 결과를 단순 곱으로 결합 가능 |
| 애니타임 유효성 | 샘플 수를 사전에 정하지 않아도 임의 시점에서 보장 유지 | 순차 모니터링, 조기 종료 가능 |
| 퍼지 멤버십 표현 | 이진(0/1) 대신 [0,1] 범위의 연속값으로 레이블 포함 정도 표현 | 모호한 레이블 환경 처리 |
애니타임 유효성의 이론적 근거는 Ville의 부등식입니다.
Ville의 부등식 (직관): "아무리 많이 들여다봐도 잘못된 기각 확률이 α를 넘지 않는다." 수식으로는 비음수 슈퍼마팅게일 {Mₜ}에 대해 P(∃t: Mₜ ≥ 1/α) ≤ α가 성립합니다. e-value의 역수 누적 곱이 이 슈퍼마팅게일을 형성하기 때문에, 임의 시점에서 통계적 보장이 유지됩니다.
슈퍼마팅게일(Supermartingale): 시간에 따라 기댓값이 감소하거나 유지되는 확률 과정입니다. "앞으로 기대할 수 있는 값이 지금보다 크지 않은" 공정한 도박이라고 생각하면 됩니다. 귀무가설 하에서 e-value의 역수 누적 곱이 이 성질을 만족하기 때문에, 언제 관찰을 멈춰도 오류율이 α를 초과하지 않는다는 보장이 가능합니다.
컨포멀 e-예측 — e-value를 핵심 통계량으로
전통 방식에서 p-value 기반 비적합 점수를 사용했다면, 컨포멀 e-예측은 각 후보 레이블 y에 대해 보정 집합으로부터 e-value를 직접 계산합니다. 예측 집합은 e-value가 임계값(보통 1)을 초과하는 레이블들로 구성됩니다.
1/p_value 변환이 유효한 이유는 마르코프 부등식에 있습니다.
마르코프 부등식 (직관): "기댓값이 작은 확률 변수는 큰 값을 가질 확률도 작다." 비음수 확률 변수 E에 대해 P(E ≥ c) ≤ E[E]/c가 성립합니다. E = 1/p로 두면 귀무가설 하에서 E[E] ≤ 1이므로, P(E ≥ 1/α) ≤ α가 됩니다. 즉 e-value가 1/α 이상일 때 귀무가설을 기각해도 오류율이 α를 넘지 않는다는 보장이 생깁니다. 단,
E = 1/p는 유효하지만 최적이 아닙니다. 검출력을 높이려면 데이터 분포에 맞는 베팅 함수(betting function) 설계가 필요합니다.
컨포멀 e-예측이 기존 컨포멀 예측과 어떻게 다른지 정리하면 다음과 같습니다.
| 구분 | 전통 컨포멀 예측 (p-value) | 컨포멀 e-예측 (e-value) |
|---|---|---|
| 핵심 통계량 | p-value | e-value (베팅 배율) |
| 배치 수 미지 시 | union bound 필요 | 곱셈 합산으로 우회 |
| 순차 애니타임 유효성 | 제한적 | 본질적으로 지원 |
| 레이블 모호성 처리 | 이진(0/1)만 처리 | [0,1] 퍼지 멤버십 |
| 교차-컨포멀 이론 보장 | 과도한 무작위화 시 깨질 수 있음 | 이론적으로 보장 |
import numpy as np
from typing import List
def compute_conformal_evalue(cal_scores: np.ndarray, test_score: float) -> float:
"""
보정 집합의 비적합 점수와 테스트 점수로부터 e-value를 계산합니다.
직관: 테스트 점수가 보정 집합보다 얼마나 극단적인가를 '배율'로 표현합니다.
E = 1/p 변환은 마르코프 부등식으로 유효성이 보장되지만,
더 정교한 베팅 전략을 사용하면 검출력(power)이 향상됩니다.
"""
n = len(cal_scores)
# 테스트 점수보다 크거나 같은 보정 점수의 비율 → p-value
p_value = (np.sum(cal_scores >= test_score) + 1) / (n + 1)
return 1.0 / p_value
def conformal_evalue_predict(clf, cal_X: np.ndarray, cal_y: np.ndarray,
test_X: np.ndarray,
threshold: float = 1.0) -> List[List[int]]:
"""
e-value 기반 예측 집합 구성.
e-value > threshold인 레이블을 집합에 포함합니다.
"""
cal_probs = clf.predict_proba(cal_X)
test_probs_all = clf.predict_proba(test_X) # 배치 추론으로 사전 계산
n_classes = cal_probs.shape[1]
prediction_sets = []
for test_probs in test_probs_all:
pred_set = []
for y_candidate in range(n_classes):
cal_scores_y = 1 - cal_probs[cal_y == y_candidate, y_candidate]
test_score_y = 1 - test_probs[y_candidate]
if len(cal_scores_y) > 0:
e_val = compute_conformal_evalue(cal_scores_y, test_score_y)
if e_val > threshold:
pred_set.append(y_candidate)
prediction_sets.append(pred_set)
return prediction_sets실전 적용
예시 1: 배치 애니타임-유효 컨포멀 예측 (순차 배치 시나리오)
병원에서 신약 임상 데이터가 배치 단위로 순차 도착하는 상황을 생각해보겠습니다. 규제 기관은 몇 번째 병원까지 데이터가 들어올지 모르는 상태에서, 어느 시점이든 통계적으로 유효한 결론을 원합니다. 전통적인 union bound는 총 배치 수 K를 알아야 하지만, e-value의 곱셈 성질로 이를 우회할 수 있습니다.
import numpy as np
from dataclasses import dataclass, field
from typing import List, Tuple
from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# ── 데이터 준비 ──────────────────────────────────────────────────
X, y = make_classification(n_samples=2000, n_features=20, random_state=42)
X_train, X_temp, y_train, y_temp = train_test_split(
X, y, test_size=0.6, random_state=42
)
X_cal, X_test_all, y_cal, y_test_all = train_test_split(
X_temp, y_temp, test_size=0.5, random_state=42
)
clf = RandomForestClassifier(n_estimators=100, random_state=42)
clf.fit(X_train, y_train)
# 순차 배치 시뮬레이션 — 5개 병원에서 데이터가 순차 도착
n_batches = 5
batch_size = len(X_test_all) // n_batches
sequential_batches: List[Tuple[np.ndarray, np.ndarray]] = [
(
X_test_all[i * batch_size:(i + 1) * batch_size],
y_test_all[i * batch_size:(i + 1) * batch_size],
)
for i in range(n_batches)
]
# ── 배치 e-value 계산 ────────────────────────────────────────────
def compute_batch_evalue(clf, cal_X: np.ndarray, cal_y: np.ndarray,
batch_X: np.ndarray, batch_y: np.ndarray) -> float:
"""
배치 데이터로부터 배치 e-value를 계산합니다.
구현: 각 샘플의 e-value(= 1/p-value)의 기하평균을 사용합니다.
이론적으로 독립 e-value의 곱도 유효한 e-value이며,
기하평균은 배치 크기 차이를 보정한 샘플당 증거 강도입니다.
⚠️ 주의: arXiv:2503.13050의 배치 알고리즘은 베팅 함수(betting function)를
명시적으로 최적화합니다. 이 단순 구현은 이론적 보장은 유지하지만
검출력이 낮을 수 있습니다. 프로덕션 적용 전 원논문 확인을 권장합니다.
"""
cal_probs = clf.predict_proba(cal_X)
cal_scores = 1 - cal_probs[np.arange(len(cal_y)), cal_y]
batch_probs = clf.predict_proba(batch_X)
batch_scores = 1 - batch_probs[np.arange(len(batch_y)), batch_y]
n_cal = len(cal_scores)
p_values = np.array([
(np.sum(cal_scores >= s) + 1) / (n_cal + 1)
for s in batch_scores
])
# 각 샘플의 e-value 기하평균 (배치 크기 정규화)
individual_evalues = 1.0 / p_values
batch_evalue = float(np.exp(np.mean(np.log(individual_evalues))))
return batch_evalue
# ── 애니타임 모니터 ──────────────────────────────────────────────
@dataclass
class BatchEValueMonitor:
"""
배치 단위로 순차 도착하는 데이터에 대해
e-value를 누적 곱으로 관리하는 모니터.
언제든 검정을 수행할 수 있는 애니타임 유효성을 제공합니다.
"""
alpha: float = 0.05
cumulative_evalue: float = 1.0
batch_history: List[float] = field(default_factory=list)
def update(self, batch_evalue: float) -> dict:
"""
새 배치의 e-value로 누적값을 업데이트합니다.
귀무가설 기각 여부와 현재 유효 오류율을 반환합니다.
"""
self.cumulative_evalue *= batch_evalue
self.batch_history.append(batch_evalue)
# Markov 부등식: P(E_cumul ≥ 1/α) ≤ α
reject = self.cumulative_evalue >= (1.0 / self.alpha)
current_alpha = 1.0 / self.cumulative_evalue
return {
"batch_num": len(self.batch_history),
"batch_evalue": batch_evalue,
"cumulative_evalue": self.cumulative_evalue,
"reject_null": reject,
"current_effective_alpha": min(current_alpha, 1.0),
}
# ── 순차 실행 예시 ───────────────────────────────────────────────
monitor = BatchEValueMonitor(alpha=0.05)
for batch_X, batch_y in sequential_batches:
e_val = compute_batch_evalue(clf, X_cal, y_cal, batch_X, batch_y)
result = monitor.update(e_val)
print(f"배치 {result['batch_num']:2d} | "
f"e-value: {result['batch_evalue']:.3f} | "
f"누적: {result['cumulative_evalue']:.3f} | "
f"기각: {result['reject_null']}")
if result["reject_null"]:
print("→ 귀무가설 기각: 통계적으로 유의미한 효과 확인됨")
break # 이 시점 이후 추가 배치가 와도 이미 얻은 보장은 유효합니다배치 e-value 누적 과정 요약
| 단계 | 수행 내용 | 핵심 포인트 |
|---|---|---|
| 보정 집합 구성 | 초기 데이터로 비적합 점수 분포 확보 | 배치별 공유 또는 슬라이딩 윈도우 가능 |
| 배치 e-value 계산 | 각 배치의 p-value를 e-value로 변환 | 베팅 전략에 따라 검출력(power)이 달라짐 |
| 누적 곱 갱신 | E_cumul *= E_batch |
배치 수 K를 몰라도 유효성 유지 |
| 애니타임 검정 | E_cumul ≥ 1/α이면 기각 |
어느 시점에 멈춰도 α-수준 보장 |
예시 2: 퍼지 예측 집합 — 모호한 레이블 처리
방사선 이미지 판독에서 여러 전문가가 서로 다른 진단을 내리는 경우, 어떤 레이블이 "정답"인지 이진으로 정의하기 어렵습니다. 퍼지 예측 집합은 레이블 포함 여부를 [0, 1] 범위의 연속값으로 표현하여 이 모호성을 자연스럽게 수용합니다.
import numpy as np
from typing import List, Optional, Dict
def compute_fuzzy_membership(e_value: float, threshold: float = 1.0) -> float:
"""
e-value를 [0, 1] 범위의 퍼지 멤버십 값으로 변환합니다.
변환 공식: log(1 + (e_value - threshold)) / log(10)
- threshold 미만 → 0.0 (예측 집합 미포함)
- e_value = threshold + 9일 때 → 1.0 (포화 기준)
- log 스케일로 e-value가 커질수록 포화되는 형태 → 극단값 안정화
포화 기준(+9)은 "e-value가 threshold보다 9 높을 때 완전 포함"을 의미하는
임의 상수입니다. 엄격한 의료 진단처럼 빠른 포화가 필요하다면
np.log1p(4.0)으로 낮추고, 넓은 분포의 데이터라면 더 크게 설정할 수 있습니다.
"""
if e_value < threshold:
return 0.0
return min(1.0, np.log1p(e_value - threshold) / np.log1p(9.0))
def fuzzy_conformal_predict(clf, cal_X: np.ndarray, cal_y: np.ndarray,
test_X: np.ndarray,
ambiguous_labels: Optional[np.ndarray] = None
) -> List[Dict[int, float]]:
"""
퍼지 컨포멀 예측 집합을 구성합니다.
ambiguous_labels: (n_cal_samples, n_classes) 형태의 소프트 레이블 행렬.
각 셀은 해당 클래스에 대한 전문가 동의율(0~1)입니다.
None이면 하드 레이블을 원-핫으로 처리합니다.
반환: 각 테스트 샘플에 대한 {레이블: 멤버십 값} 딕셔너리 리스트
"""
cal_probs = clf.predict_proba(cal_X)
test_probs_all = clf.predict_proba(test_X) # 배치 추론으로 사전 계산
n_classes = cal_probs.shape[1]
if ambiguous_labels is None:
ambiguous_labels = np.eye(n_classes)[cal_y]
results = []
for test_probs in test_probs_all:
memberships: Dict[int, float] = {}
for y_candidate in range(n_classes):
soft_weights = ambiguous_labels[:, y_candidate]
cal_scores = 1 - cal_probs[:, y_candidate]
weighted_scores = cal_scores * soft_weights
valid_mask = soft_weights > 0
if valid_mask.sum() < 5: # 최소 샘플 수 보장
memberships[y_candidate] = 0.0
continue
test_score = 1 - test_probs[y_candidate]
e_val = compute_conformal_evalue(weighted_scores[valid_mask], test_score)
memberships[y_candidate] = compute_fuzzy_membership(e_val)
results.append(memberships)
return results
# ── 사용 예시: 3명의 전문가 레이블이 있는 의료 진단 ──────────────
n_classes = clf.n_classes_
n_experts = 3
# 전문가 레이블 시뮬레이션 — 실제로는 어노테이션 툴에서 가져옵니다
np.random.seed(42)
expert_labels = np.random.randint(0, n_classes, size=(len(y_cal), n_experts))
# 클래스별 소프트 레이블 행렬 구성
# ambiguous[i, c] = 샘플 i에 대해 클래스 c로 분류한 전문가 비율
ambiguous = np.zeros((len(y_cal), n_classes))
for c in range(n_classes):
ambiguous[:, c] = np.mean(expert_labels == c, axis=1)
# 각 행의 합 = 1.0 (클래스별 동의율의 합)
fuzzy_preds = fuzzy_conformal_predict(
clf, X_cal, y_cal, X_test_all[:10],
ambiguous_labels=ambiguous,
)
for i, memberships in enumerate(fuzzy_preds[:3]):
print(f"\n테스트 샘플 {i}:")
for label, membership in sorted(memberships.items(), key=lambda x: -x[1]):
bar = "█" * int(membership * 20)
print(f" 클래스 {label}: {membership:.3f} |{bar:<20}|")퍼지 예측 집합 구성 과정 요약
| 단계 | 수행 내용 | 핵심 포인트 |
|---|---|---|
| 소프트 레이블 행렬 구성 | 전문가 동의율로 (n_samples, n_classes) 행렬 생성 | 각 행의 합이 1이 되도록 정규화 |
| 가중 비적합 점수 계산 | 소프트 레이블 가중치를 비적합 점수에 반영 | 동의율이 낮은 클래스는 영향력이 줄어듦 |
| e-value 계산 | 가중 점수 분포로 e-value 산출 | 전문가 의견이 일치할수록 높은 e-value |
| 퍼지 멤버십 변환 | compute_fuzzy_membership으로 [0,1] 변환 |
포화 기준은 도메인에 맞게 조정 가능 |
장단점 분석
장점
| 항목 | 내용 | 언제 특히 유효한가 |
|---|---|---|
| 배치 수 미지 시 동시 보장 | e-value의 곱셈 합산으로 K를 알지 못해도 유효한 커버리지 제공 | 다기관 임상, 배치 A/B 테스트 |
| 애니타임 유효성 | Ville의 부등식에 의해 임의 시점에서 통계적 보장 유지 | 조기 종료 가능한 순차 실험 |
| 퍼지 예측 집합 | 이진 포함 여부 대신 [0,1] 연속값으로 레이블 모호성 수용 | 전문가 어노테이션 불일치 환경 |
| 조건부 예측기 설계 용이 | 입력 조건별 맞춤 예측 집합을 p-value 방식보다 손쉽게 구성 | 서브그룹별 보장이 필요한 경우 |
| 교차-컨포멀 유효성 | p-value 기반 교차-컨포멀이 과도한 무작위화 시 깨질 수 있는 반면, e-value 기반은 이론적으로 보장 | 데이터가 적어 교차 검증이 필요한 경우 |
| 모호한 레이블 처리 | 어노테이션 노이즈, 레이블 모호성 환경에서 유효한 커버리지 보장 | 의료 이미지, 감정 인식 등 |
단점 및 주의사항
| 항목 | 내용 | 대응 방안 |
|---|---|---|
| 교환 가능성 의존 | 강한 시간적 의존성(AR 프로세스)에서 가정 위반 | 슬라이딩 윈도우 재보정, 가중 컨포멀 적용 |
| 보수적 예측 집합 | 소규모 보정 집합에서 p-value 방식보다 예측 집합이 넓어질 수 있음 | 충분한 보정 데이터 확보(권장 n ≥ 200) |
| 계산 비용 | Full conformal은 후보 레이블마다 모델 재학습 필요 | Split conformal e-예측으로 계산량 절감 |
| 소프트웨어 미성숙 | MAPIE, crepes 등 주요 라이브러리에 기본 지원 없음 | 논문 저자 GitHub 코드 참조, 직접 구현 |
| 분포 이동 | 배치 간 분포 변화 시 보정 집합이 불일치할 수 있음 | 가중 e-value, 적응형 재보정 전략 활용 |
| 베팅 함수 설계 | E = 1/p는 유효하지만 검출력이 낮을 수 있음 |
도메인 지식 기반 베팅 함수 최적화 (arXiv:2503.13050 참조) |
실무에서 가장 흔한 실수
- 보정 집합과 학습 데이터를 분리하지 않는 경우 — 같은 데이터로 모델을 훈련하고 비적합 점수를 계산하면 커버리지 보장이 무효가 됩니다. 반드시 홀드아웃 보정 집합을 별도로 유지하는 것이 중요합니다.
- e-value를 단순 p-value의 역수로만 사용하는 경우 —
E = 1/p는 유효하지만 최적이 아닙니다. 검출력을 높이려면 데이터에 맞는 베팅 함수(betting function) 설계가 필요하며, 이를 생략하면 예측 집합이 불필요하게 넓어질 수 있습니다. - 배치 간 교환 가능성을 가정하면서 분포 이동을 무시하는 경우 — 배치마다 데이터 분포가 달라지는 환경(계절성 있는 시계열, 병원별 장비 차이 등)에서 검증 없이 누적 e-value를 신뢰하면 실제 커버리지가 보장값과 크게 달라질 수 있습니다.
마치며
e-value와 컨포멀 예측을 결합하면, 배치 수를 알 수 없는 순차 환경에서도 레이블이 모호한 실전 데이터에서도, 통계적으로 엄밀한 불확실성 보장을 지킬 수 있습니다. 이론적 기반은 2020년 Vovk의 연구에서 출발했고, 2025년 arXiv:2503.13050이 배치 애니타임-유효 예측, 퍼지 예측 집합, 모호한 ground truth 처리라는 세 가지 실용적 응용으로 빠르게 확장했습니다. 다음 글에서 다룰 온라인 컨포멀 예측은 이 배치 e-value 누적 개념과 자연스럽게 연결되므로, 이번 글의 BatchEValueMonitor 흐름을 익혀두시면 큰 도움이 됩니다.
지금 바로 시작해볼 수 있는 3단계입니다.
- 컨포멀 예측 기초 실습:
pip install mapie후 공식 문서의 분류 예제를 실행해보시면 split conformal의 커버리지 보장을 직접 확인해볼 수 있습니다. MAPIE는 e-value를 기본 지원하지 않지만, 비적합 점수 계산 구조를 파악하는 출발점으로 적합합니다. - e-value 직접 구현 실험: 이 글의
BatchEValueMonitor코드를make_classification데이터에 적용해보시면 좋습니다. 보정 집합 크기(100, 500, 1000)를 바꿔가며 예측 집합 크기와 실제 커버리지가 어떻게 달라지는지 아래 시각화 코드로 확인해볼 수 있습니다.
import matplotlib.pyplot as plt
cal_sizes = [100, 500, 1000]
coverages = []
for cal_size in cal_sizes:
cal_X_sub = X_cal[:cal_size]
cal_y_sub = y_cal[:cal_size]
pred_sets = conformal_evalue_predict(clf, cal_X_sub, cal_y_sub, X_test_all)
coverage = np.mean([
y_true in pred_set
for y_true, pred_set in zip(y_test_all, pred_sets)
])
coverages.append(coverage)
plt.figure(figsize=(8, 4))
plt.plot(cal_sizes, coverages, marker="o", label="실제 커버리지")
plt.axhline(y=0.95, color="red", linestyle="--", label="목표 커버리지 (95%)")
plt.xlabel("보정 집합 크기")
plt.ylabel("실제 커버리지")
plt.title("보정 집합 크기와 커버리지 관계")
plt.legend()
plt.tight_layout()
plt.show()- 원논문 읽기: arXiv:2503.13050 "E-Values Expand the Scope of Conformal Prediction"은 배치 설정 알고리즘을 수도코드로 명확하게 제시하고 있어, 실제 시스템에 통합하기 전 이론적 기반을 확인하기에 좋습니다.
다음 글: 온라인 컨포멀 예측(Online Conformal Prediction) — 스트리밍 데이터에서 감소하는 스텝 사이즈로 실시간 커버리지를 유지하는 방법. 이번 글에서 다룬 배치 e-value 누적 개념과 어떻게 연결되는지 함께 살펴볼 예정입니다.
참고 자료
입문용 — 처음 읽기에 적합한 자료
- A Gentle Introduction to Conformal Prediction | arXiv:2107.07511 — 컨포멀 예측을 처음 접하는 경우 시작점으로 적합합니다.
- MAPIE — scikit-learn-contrib | GitHub — p-value 기반 컨포멀 예측 구조를 코드로 파악할 수 있습니다.
- awesome-conformal-prediction | GitHub 큐레이션 — 논문·튜토리얼·라이브러리를 한곳에서 탐색할 수 있습니다.
핵심 — 이 글과 직접 연결되는 자료
- E-Values Expand the Scope of Conformal Prediction | arXiv:2503.13050 — 배치 애니타임-유효 예측, 퍼지 예측 집합의 원논문입니다.
- Conformal e-prediction — Vovk | ScienceDirect 2025 — 컨포멀 e-예측의 이론적 토대입니다.
- Fuzzy Prediction Sets: Conformal Prediction with E-values | arXiv:2509.13130 — 퍼지 예측 집합과 의사결정 이론의 연결을 다룹니다.
심화 학습