Clustered Data and the Sampling Budget

One Bad Tool Call, Ten Bad Rows
Your agent eval grades 100 conversations, 10 turns each: 1,000 graded rows. The pass rate comes in at 70%, and the naive 95% confidence interval is
Tight. Shippable. Also wrong.
Turns within a conversation sink or swim together. One bad tool call on turn 2 poisons the next nine rows; a conversation that starts clean tends to stay clean. If the intraclass correlation is —half of the outcome variance lives between conversations—the design effect is
The effective sample size is , and the honest interval is pp. Your error bars were 2.3× too tight, and nobody lied. The rows just weren't independent.
This is the third post in the Error Bars for Evals strand. The first put a confidence interval on a single score; the second compared two models on the same questions. This one asks what happens when your rows arrive in clumps—and where the next thousand dollars of eval budget should go.
The Whole Idea in One Formula
Everything runs through the intraclass correlation : the share of outcome variance that lives between clusters rather than within them. means knowing one turn's outcome tells you nothing about its siblings. means a conversation passes or fails as a unit and the turns are photocopies.
Given and a common cluster size , Kish's design effect says how much clustering inflates the variance of your pass rate:
Two corollaries do all the practical work:
Anchor the formula at its edges:
- → no penalty, ever. One row per cluster is just an independent sample, whatever is.
- → no penalty, ever. Independent rows are independent rows, however you bundle them.
- The penalty is depth × stickiness. It grows with how deep each cluster goes () multiplied by how much the rows inside it move together (). Neither alone hurts you; the product does.
The Budget Identity
The second big idea decides how to spend. Fix a budget of rows— clusters, rows each—and expand the variance of the pooled pass rate:
Read it out loud. The first term has the full budget in its denominator: any spending shrinks it, depth or breadth alike. The second term has only . There is no in it anywhere—no amount of extra depth touches it. Once is meaningful, that second term becomes the floor under your precision, and deeper clusters stop buying you anything. Only more clusters do.
▶Where the two-term split comes from
Start from the design-effect form and split :
The between-cluster term is the variance of the cluster-quality lottery itself: with only conversations, you only get draws of "was this a good conversation," no matter how carefully you grade each one.
A Worked Example
Take the eval from the hook: conversations, turns, and a pilot estimate of . The same five steps appear in the practice exercise below.
Step 1 — count the rows. . This is the the dashboard reports.
Step 2 — the design effect. . Each conversation's ten turns carry the information of roughly two independent rows, not ten.
Step 3 — effective sample size. . A thousand rows doing the work of 182.
Step 4 — the bar-widening factor. . Every naive standard error in the report needs to stretch by 2.35× before you believe it.
Step 5 — spend the next budget. Leadership doubles your spend to 2,000 rows. Two ways to use it:
| Design | Rows | DEFF | |
|---|---|---|---|
| Today: 100 conversations × 10 turns | 1,000 | ||
| (a) 200 conversations × 10 turns | 2,000 | ||
| (b) 100 conversations × 20 turns | 2,000 |
Same money. Doubling depth bought almost nothing (182 → 190 effective samples); doubling clusters doubled the work done (182 → 364). The budget identity said this would happen: option (b) poured its entire raise into the term that can't reach.
Where Clusters Hide in LLM Evals
Conversations are the obvious case. They are not the only one.
| Cluster | Rows inside it | How it bites |
|---|---|---|
| Conversation | Graded turns | One early tool-call failure cascades through every later turn |
| Prompt | resamples (pass@k, best-of-, temperature sampling) | Ten generations of the same prompt mostly re-measure that prompt |
| Template | Instantiations with different entities/values | A broken template fails identically a hundred times |
| Document | Chunks, or questions about the same passage | A hard document drags down every question written against it |
| User | Sessions, requests | Power users overweight their own quirks in the average |
| Grader | Every item they grade | A rubric-happy grader clusters everything they touch |
Miller's "Adding Error Bars to Evals" treats exactly this structure—question groups drawn from a shared context—and recommends clustered standard errors whenever eval questions arrive in related bundles. The design effect itself is much older: it comes from Kish (1965), built for household surveys where interviewing one more person in the same village was cheap and one more village was expensive. Swap "village" for "conversation" and the arithmetic transfers unchanged.
Ways to Fool Yourself
1. Counting turns (or resamples) as independent . The dashboard says ; the statistics say . Any calculation that feeds the raw row count into —power analyses, CIs, significance tests—inherits the lie. The same applies to generations per prompt: pass@k evaluated on 100 prompts is 100 clusters, not observations.
2. Bootstrapping rows instead of clusters. The bootstrap is not automatically honest. Resample individual rows and every resampled dataset scrambles conversations together, silently preserving none of the within-cluster dependence—the interval that comes out is the naive one with extra steps. Resample whole clusters (keep every turn of each drawn conversation together) and the dependence survives into the replicates. Same estimator, one word different, very different interval.
3. Assuming is small without measuring it. Intuition about is poor and the penalty is linear in it. A pilot run and a one-way ANOVA give you an estimate in five lines: with the between-cluster mean square and the within, . Code in the field notes. Agent-style evals routinely land at to ; "it's probably about 0.1" is a hope, not a measurement.
4. Buying ten generations per prompt when the same money buys ten new prompts. Resampling feels rigorous—look how we averaged out the temperature noise. But if prompts differ more than resamples do (they almost always do), the tenth resample of prompt 17 is nearly free of new information while the eleventh prompt would have been full price. Sample in the direction of the variance.
5. Mixing cluster sizes and averaging carelessly. With unequal cluster sizes there are two different answers: pool all rows (big conversations count more) or average the cluster means (every conversation counts once). These are different estimands, and they genuinely differ when cluster size correlates with difficulty—long conversations are often long because they're going badly. Pick the one that matches the question you're asking, and state which one you picked.
Try It Yourself
The playground simulates the whole pipeline: each conversation draws a quality , each turn is a coin flip around it, and both intervals are computed from the same rows. The strip plot is the intuition generator—watch the rows go all-or-nothing as rises.
Each row is one conversation, each dot one graded turn — filled = pass, hollow = fail. Showing 24 of 100 conversations.
Two 95% intervals from the same simulated rows. The naive one pretends every row is independent; the cluster bootstrap resamples whole conversations.
At this ρ, the curve says go left: more clusters, less depth.
Experiments to try:
- "The multi-turn agent eval" — the hook's numbers. The implied tile bounces around the 182 we computed by hand; reshuffle a few times to watch it orbit the theory.
- "Actually independent" — set and the two intervals collapse onto each other: clustering is a fact about correlation, not about layout.
- "Deep and sticky" — 50 conversations × 20 turns at . A thousand rows, and the strip plot shows you the ~50 real observations.
- "Wide and shallow" vs "Deep and sticky" — same budget, same -ish, wildly different clustered SEs. The budget curve says why.
- "Bootstrap on fumes" — 20 conversations. Reshuffle a few times and watch the clustered interval itself jump around; below ~20 clusters the bootstrap is running on vapors.
- Hold at 0.5 and sweep from 1 to 20. The marker dot rides up the budget curve—every step right is precision you paid for and didn't get.
Your Turn
The worked example was mine; these numbers are yours. Each problem generates a fresh eval design, and the five steps mirror the walkthrough exactly. If you get stuck, help escalates gently—a nudge first, then the setup with your numbers plugged in, and only then the full answer.
Practice problem
Prompt Resampling
Field Notes
Estimating from a pilot. Run a slice of the eval—even 30 clusters will do—and fit the one-way ANOVA estimator. With equal cluster sizes , grand mean , and cluster means :
▶Compact Python: ICC from a pilot
import numpy as np
def icc_pilot(cluster_ids, outcomes):
"""One-way ANOVA intraclass correlation from (cluster_id, outcome) pairs."""
ids, y = np.asarray(cluster_ids), np.asarray(outcomes, dtype=float)
groups = [y[ids == c] for c in np.unique(ids)]
K, n = len(groups), len(y)
m_bar = n / K # average cluster size
grand = y.mean()
ms_b = sum(len(g) * (g.mean() - grand) ** 2 for g in groups) / (K - 1)
ms_w = sum(((g - g.mean()) ** 2).sum() for g in groups) / (n - K)
return (ms_b - ms_w) / (ms_b + (m_bar - 1) * ms_w)A small negative just means "indistinguishable from zero at this pilot size"—treat it as , not as an anti-correlation discovery.
When depth is the point. Everything above assumes the estimand is a population average over clusters. Sometimes it isn't. If you're measuring within-conversation degradation—does turn 15 fail more than turn 3?—then long conversations are the only place that signal lives, and cutting depth destroys the experiment. If pass@k is your metric, the resamples aren't a cluster inflating your variance; they're the estimand itself, and you need all of them per prompt (see Chen et al. 2021 for the unbiased estimator). The design effect punishes depth only when depth is redundant measurement of the same thing. First decide what the thing is.
What to report. , (or its distribution), from a pilot, and clustered standard errors—via the cluster bootstrap below or the analytic clustered SEs in Miller (2024). If your CI would embarrass you at instead of , the number to fix is .
Earlier in this strand. The mechanics of the basic CI live in Error Bars on Eval Scores; comparing two models on the same clustered questions is the subject of Paired Deltas. Clustering composes with both: cluster the bootstrap there the same way you cluster it here.
Code
▶Python: cluster bootstrap CI
import numpy as np
def cluster_bootstrap_ci(cluster_ids, outcomes, n_boot=2000, seed=0):
"""95% CI for the pooled mean, resampling whole clusters with replacement."""
rng = np.random.default_rng(seed)
ids, y = np.asarray(cluster_ids), np.asarray(outcomes, dtype=float)
groups = [y[ids == c] for c in np.unique(ids)]
K = len(groups)
stats = []
for _ in range(n_boot):
draw = rng.integers(0, K, size=K) # sample K clusters
sample = np.concatenate([groups[j] for j in draw])
stats.append(sample.mean()) # pool the rows
return np.percentile(stats, [2.5, 97.5])
# cluster_ids = conversation IDs, one per graded turn
# lo, hi = cluster_bootstrap_ci(df.conversation_id, df.passed)Two implementation notes. First, the resampling unit is the cluster: a drawn conversation brings all of its turns. Second, sample.mean() pools rows, so bigger clusters weigh more—swap in np.mean([g.mean() for ...]) if your estimand is the mean of cluster means (see fooling-yourself #5).
▶Python: design-effect arithmetic
import numpy as np
def design_effect(m, rho):
return 1 + (m - 1) * rho
def effective_n(K, m, rho):
return K * m / design_effect(m, rho)
# The worked example
print(design_effect(10, 0.5)) # 5.5
print(effective_n(100, 10, 0.5)) # 181.8
print(effective_n(200, 10, 0.5)) # 363.6 <- double the clusters
print(effective_n(100, 20, 0.5)) # 190.5 <- double the depthFurther Reading
- Miller, E. (2024). "Adding Error Bars to Evals: A Statistical Approach to Language Model Evaluations." arXiv:2411.00640. Section on clustered standard errors for question groups.
- Kish, L. (1965). Survey Sampling. Wiley. The origin of the design effect, built for exactly this trade-off.
- Cameron, A. C. & Miller, D. L. (2015). "A Practitioner's Guide to Cluster-Robust Inference." Journal of Human Resources 50(2). What to do when cluster counts are small or sizes are wild.