층화 표본 추출 및 보정
세그먼트별로 표본을 추출하고 라벨이 지정된 검증 세트로 보정합니다
층화 표본 추출 및 보정은(는) CoddyKit의 무료 Claude Architect 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Claude Architect 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.
이 강의의 일부는 아직 번역되지 않았으며 영어로 표시됩니다.
Why Aggregate Accuracy Lies
You ship a Claude extraction pipeline and report 97% accuracy. Leadership approves full automation. Three weeks later, every refund invoice with a foreign-currency line is wrong.
The headline number was real — but it was an average. Aggregate accuracy can hide catastrophic failure on a specific document type or a specific field, because the common cases drown out the rare ones.
This lesson is about the discipline that keeps you honest before you automate: stratified sampling to measure where you actually fail, and calibration on labeled validation sets so your confidence scores mean something.
The Core Rule
Memorize the exam-level principle from the oversight domain:
Aggregate accuracy can hide poor performance on a specific document type or field. Use stratified random sampling plus field-level confidence calibrated on labeled validation sets before automating.
Two moves, in order:
- Stratify, then sample — partition the population into segments, sample within each, so rare-but-critical slices are actually measured.
- Calibrate confidence — make the model's per-field confidence correspond to real-world correctness, proven against ground-truth labels.
Skip either step and you are guessing, not governing.
Why Random Sampling Isn't Enough
Plain random sampling oversamples whatever is common. If 95% of your invoices are simple single-currency receipts, a random sample of 200 will be ~190 easy cases and maybe a handful of the hard foreign-currency ones — too few to detect a 40% error rate on that slice.
Stratified sampling fixes this: define segments that matter (document type, language, vendor, field presence), then draw a sample from each segment. Now the rare slice is measured with enough statistical power to fail loudly if it's broken.
You measure the population you're worried about, not the population that happens to be biggest.
Choosing Your Strata
Good strata isolate the dimensions where behavior plausibly diverges. For a structured-extraction pipeline (Scenario 6), useful segments include:
- Document type — invoice vs. receipt vs. statement.
- Field — totals, dates, currency, line items. Field-level matters because
97%overall can mask60%on the currency field. - Edge conditions — multi-page docs, scanned/low-quality, multilingual, or records where an optional field is absent.
That last one ties to a schema rule: never mark a possibly-absent field as required, or the model fabricates it. Stratify by presence/absence so you catch fabrication.
Drawing a Stratified Sample
Concretely, group your validation pool by segment and pull a fixed quota from each — enough per stratum to trust the per-stratum metric, not proportional to the population.
import random
from collections import defaultdict
# Each record carries the dimensions we stratify on.
def segment_key(rec):
return (rec["doc_type"], rec["has_currency_line"], rec["is_multilingual"])
buckets = defaultdict(list)
for rec in validation_pool:
buckets[segment_key(rec)].append(rec)
# Fixed quota per stratum -> rare slices get real coverage,
# not just a couple of incidental samples.
PER_STRATUM = 40
sample = []
for key, recs in buckets.items():
random.shuffle(recs)
sample.extend(recs[:PER_STRATUM])
print({k: min(len(v), PER_STRATUM) for k, v in buckets.items()})Field-Level Confidence, Not Just a Verdict
To calibrate, the model has to emit a confidence per field, not one blanket score. Force structured output so confidence is a typed field you can audit — not prose you parse.
Use tool_choice to guarantee the model returns the schema. "any" forces it to call some tool; {"type":"tool","name":"X"} forces a specific one. A JSON Schema eliminates syntax errors and enforces required fields.
extract_tool = {
"name": "emit_extraction",
"description": "Return extracted fields, each with a per-field confidence in [0,1].",
"input_schema": {
"type": "object",
"properties": {
"fields": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"value": {"type": "string"},
"confidence": {"type": "number"}
},
"required": ["name", "value", "confidence"]
}
}
},
"required": ["fields"]
}
}
resp = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
tools=[extract_tool],
tool_choice={"type": "tool", "name": "emit_extraction"},
messages=[{"role": "user", "content": invoice_text}],
)What Calibration Actually Means
A model is calibrated when its stated confidence matches observed accuracy: of all fields it labels 0.90 confident, about 90% should be correct against ground truth.
Raw model confidence is usually over-confident — it says 0.95 but is right 70% of the time. You can't trust an auto-accept threshold built on uncalibrated scores; you'd auto-approve wrong data.
Calibration requires labeled validation sets: human-verified ground truth for your stratified sample. There is no shortcut — the model's self-rated confidence alone is exactly the kind of signal the exam tells you NOT to trust for automated decisions.
Measuring Calibration with Labels
Bucket predictions by stated confidence, then compare each bucket's stated confidence to its actual accuracy on the labeled set. The gap is your calibration error — and you compute it per stratum so a well-calibrated 'easy' slice can't mask a broken 'hard' one.
from collections import defaultdict
# preds: list of {stratum, confidence, predicted, ground_truth}
bins = defaultdict(lambda: {"n": 0, "correct": 0, "conf_sum": 0.0})
for p in preds:
b = round(p["confidence"], 1) # 0.0..1.0 buckets
key = (p["stratum"], b)
bins[key]["n"] += 1
bins[key]["conf_sum"] += p["confidence"]
bins[key]["correct"] += int(p["predicted"] == p["ground_truth"])
for (stratum, b), s in sorted(bins.items()):
stated = s["conf_sum"] / s["n"]
actual = s["correct"] / s["n"]
print(stratum, b, f"stated={stated:.2f} actual={actual:.2f} gap={stated-actual:+.2f}")Setting Auto-Accept Thresholds Per Segment
Once calibrated, derive a confidence threshold for each stratum that meets your accuracy bar — say, auto-accept only where calibrated accuracy ≥ 99%. The threshold will differ by segment: easy single-currency invoices might auto-accept at 0.85, while foreign-currency lines need 0.98 — or stay human-reviewed entirely.
This is the bridge from measurement to oversight: low-confidence or low-accuracy strata route to a human; high-confidence calibrated strata automate. A single global threshold would either over-trust the hard slice or needlessly gate the easy one.
Self-Correction Strengthens the Signal
Confidence improves when the model can cross-check itself. For numeric extraction, have it emit both a calculated_total (sum of line items) and the stated_total printed on the document, then flag any discrepancy. A mismatch is a hard, deterministic signal — far more reliable than a self-rated confidence number.
Pair this with provenance: keep each claim's source (doc name, quote, page) so a flagged field can be traced and verified, not just re-guessed.
verify_schema = {
"name": "emit_totals",
"description": "Extract both the computed and printed total so discrepancies are detectable.",
"input_schema": {
"type": "object",
"properties": {
"line_items": {"type": "array", "items": {"type": "number"}},
"calculated_total": {"type": "number"},
"stated_total": {"type": "number"},
"source_quote": {"type": "string"}
},
"required": ["calculated_total", "stated_total", "source_quote"]
}
}
# Deterministic check beats trusting a self-rated score:
# discrepancy = abs(out['calculated_total'] - out['stated_total']) > 0.01Run the Audit Off the Critical Path
Stratified calibration audits are large, non-blocking jobs — exactly what the Message Batches API is for: 50% cheaper, up to a 24-hour window, no latency SLA. Run your overnight calibration sweep as a batch; correlate results with custom_id and re-submit only the failures.
The boundary matters for the exam: never use the Batch API for blocking or time-sensitive checks (it has no latency SLA and does not support multi-turn tool calling). A pre-merge gate or a live extraction stays on the synchronous API; the periodic audit goes to batch.
requests = [
{
"custom_id": f"val-{rec['id']}",
"params": {
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"tools": [extract_tool],
"tool_choice": {"type": "tool", "name": "emit_extraction"},
"messages": [{"role": "user", "content": rec["text"]}],
},
}
for rec in stratified_sample
]
batch = client.messages.batches.create(requests=requests)
# Overnight audit: no latency SLA, 50% cheaper. NOT for pre-merge gates.Quick Check: Approving Automation
Apply the rule to a real go/no-go decision.
Recap: Measure Before You Trust
Key takeaways for the exam and for production:
- Aggregate accuracy hides per-type and per-field failure — never automate on a headline average alone.
- Stratified random sampling partitions by the dimensions that matter (doc type, field, edge conditions) and samples each, giving rare slices real statistical power.
- Calibration aligns stated confidence with observed accuracy, proven on a labeled validation set; raw model confidence is over-confident and self-rated scores are not a trustworthy automation signal.
- Set auto-accept thresholds per segment; automate calibrated high-accuracy strata, route the rest to humans.
- Strengthen the signal with self-correction (calculated vs. stated total) and provenance; run the heavy calibration audit on the Batch API — never on a blocking, time-sensitive path.
자주 묻는 질문
“층화 표본 추출 및 보정” 강의는 무료인가요?
네 — “층화 표본 추출 및 보정” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Claude Architect 강의 전체를 잠금 해제할 수 있습니다. Claude Architect 강의에는 총 4개의 강의가 포함되어 있습니다.
“층화 표본 추출 및 보정”에서 뭘 배우나요?
세그먼트별로 표본을 추출하고 라벨이 지정된 검증 세트로 보정합니다 브라우저에서 직접 실행하는 실습 코드로 Claude Architect을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
Claude Architect을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 Claude Architect은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“층화 표본 추출 및 보정” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 Claude Architect 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 Claude Architect 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- 주장과 출처 매핑
- 충돌하는 데이터와 날짜
- 집계 지표가 실패를 숨기는 경우
- 층화 표본 추출 및 보정