Eval study notes · Coding practice set

Which tool, when

Start here. The situation decides the tool, so this page goes situation first and mechanics second. It answers the three questions from the pilot video, when to use McNemar, when to use Wilson, and where the probability in a confidence interval comes from, and then gives one table for everything else.

Three different things called “p”

Most of the confusion in eval statistics comes from three unrelated numbers that all get called “p” or “probability”. Keep them in separate boxes.

p̂ (“p-hat”), the scoreThe fraction of questions the model got right. 360 correct out of 500 gives p̂ = 0.72. It is the thing you measured, and it is the “p” inside the standard-error formula.
The p-value, from a testComes out of a comparison, such as McNemar. It is the chance of seeing a gap at least this big if there were really no difference. Small means “hard to explain as luck”.
95%, the confidence levelA property of the method, chosen by you. If you rebuilt the benchmark many times and drew an interval each time, 95% of those intervals would contain the model’s true accuracy.

Where the probability in a confidence interval comes from

A confidence interval answers one question: how much would this score move if the benchmark had been written with different questions? Here is the 72% example from the video, step by step.

  1. Model each question as a coin. The model has some true accuracy p that you cannot see. Each question is a coin that lands “correct” with probability p. Which questions ended up in the benchmark is the randomness; that is what the interval is about.
  2. Estimate p with the score. You saw 360 of 500 correct, so p̂ = 0.72. This is the moment in the video where “the probability is the eval score”.
  3. Spread of one coin. A coin with probability 0.72 has variance p̂(1 − p̂) = 0.72 × 0.28 = 0.2016. It is largest at 50% and shrinks towards 0% or 100%, because a coin that almost always lands the same way barely varies.
  4. Spread of the average of 500 coins. Divide the variance by n: 0.2016 / 500 = 0.000403. Take the square root to get the standard error: 0.020, which is 2.0 percentage points.
  5. Turn it into an interval. Averages of many coins are roughly bell-shaped, and 95% of a bell lies within 1.96 standard errors of the centre. So 72.0 ± 1.96 × 2.0 gives 68.1% to 75.9%.
  6. Read it correctly. Last week’s 70.4 sits inside that range, so a single run cannot tell the two checkpoints apart. (To actually compare them, pair them: see McNemar below.)

The formula to remember is SE = √(p̂(1 − p̂)/n). The square root of n is why halving the error bar takes four times as many questions.

McNemar: when to use it

Use it when two versions of something answer the same questions, and each answer is right or wrong. Situations on an eval platform where this comes up:

Why it beats comparing two error bars. On the same questions, easy questions are easy for both models and hard ones are hard for both. Those cancel out of the difference. Only the questions where the two disagree carry evidence. McNemar is a coin-flip test on just those disagreements.

How to compute it. Count b = questions A got right and B got wrong, and c = the reverse. If the two models were equally good, each disagreement would be a fair coin. The exact test is a binomial test of b out of b + c at one half.

from scipy.stats import binomtest
b, c = 40, 55                        # A-only wins, B-only wins
binomtest(b, b + c, 0.5).pvalue      # 0.15

The paired interval on the difference is (c − b)/n ± 1.96·√(b + c − (c − b)²/n)/n. For the example that gives 3.0 ± 3.8 points, from −0.8 to +6.8. Report that interval first and the p-value second.

When it is not the right tool:

Situation Use instead
Different question sets (two benchmark versions, two user groups) Unpaired two-proportion test, or the Newcombe interval for the difference
Scores are not right/wrong (judge score 1 to 10, F1, BLEU) Paired t-test on per-question differences, or a paired bootstrap
Several samples per question (pass@1 averaged over 8 samples) Average per question first, then a paired bootstrap or paired t-test on those averages
Three or more systems Pairwise McNemar with a Holm correction (or Cochran’s Q as an overall test first)

One line for the interview: “On the same items I never compare two error bars. I look at the discordant pairs. McNemar is a sign test on the questions where the two disagree, and it is why the platform must store per-question results.”

Wilson interval: when to use it

Use it for a single pass rate whenever n is small or the rate is near 0% or 100%. In practice, use it by default: when the simple interval is fine, Wilson agrees with it.

Situations where the simple ±1.96·SE interval (the “Wald” interval) breaks:

Why Wald breaks. It assumes a symmetric bell around p̂, but near 0 or 1 the true distribution is lopsided and squashed against the wall. Wilson solves the problem the other way round. It asks which true values of p would make the observed score unsurprising, which keeps it inside 0 to 1 and gives it honest coverage.

from statsmodels.stats.proportion import proportion_confint
proportion_confint(1, 30, method="wilson")          # (0.006, 0.167)
proportion_confint(1, 30, method="beta")            # Clopper-Pearson, more conservative

If guaranteed coverage matters, as in a safety sign-off, use Clopper-Pearson (“exact”). It is a bit wider than Wilson.

Everything else: situation to tool

You have You want to know Reach for Read
One pass rate How precise is it? Wilson interval (Wald is fine for large n and mid-range scores) Ch 7
One score that is not a pass rate (mean judge score, F1, p95 latency) How precise is it? Bootstrap: resample questions, recompute, take the 2.5th and 97.5th percentiles Ch 7
Questions that come in groups (5 questions per passage, tasks per repo) How precise is it, honestly? Cluster bootstrap or clustered standard errors; resample the groups Ch 7
Two systems, same questions, right/wrong Is the gap real? McNemar, plus the paired interval on the difference Ch 8
Two systems, same questions, continuous scores Is the gap real? Paired t-test, paired bootstrap or permutation test Ch 8
Two systems, different questions Is the gap real? Two-proportion test or Newcombe interval Ch 8
A benchmark, before you run it Can it even detect a 2-point change? Minimum detectable effect ≈ 2.8 × SE of the difference Ch 9
k samples per problem What is pass@k? The unbiased estimator 1 − C(n−c, k)/C(n, k) Ch 9
Many benchmarks × checkpoints, or many slices Which movements are real? Holm for release gates; Benjamini-Hochberg for dashboards Ch 10
An LLM judge and some human labels Can I trust the judge? Cohen’s kappa plus the confusion matrix; human-human agreement as the ceiling Ch 11
Pairwise preference votes A ranking with error bars Bradley-Terry fit, with bootstrap rank ranges Ch 11
A score that looks too good Is the test set leaked? Contamination checks: n-gram overlap, perturbed or fresh versions Ch 12
Live users Did the change help? A/B test randomised by user, CUPED, no peeking without a sequential method Ch 12