Evaluating a Fine-Tuned Model
Introduction
You've learned to train models (SFT, DPO, GRPO) and to combine them (merging). This lesson answers the question that decides whether any of it was worth doing: did the fine-tune actually make the model better — and can you prove it?
This is the discipline that separates a demo from a shipped model. The governing idea: a fine-tune is only as good as your ability to measure it. And the single most important rule — the one beginners miss — is that you never report a fine-tune's absolute score. You report the delta vs the base model, measured on the exact same held-out test. If the base + a good prompt does just as well, the fine-tune wasn't justified. By the end you'll evaluate across three dimensions, prove a result is real (not judge noise), and make a clean ship / don't-ship call.

The One Rule: Measure the Delta vs the Base
Everything in fine-tuning evaluation hangs on one principle: the fine-tune's value is the delta.
Score the base model and your candidate on the same contract — same held-out examples, same rubric, same judge — and the candidate's improvement over the base is the only number that matters. An absolute "87% accuracy" is meaningless on its own: maybe the base already scored 86% with a decent prompt, and you spent a week and a GPU to gain one point you could've gotten for free.
Two non-negotiables that make the delta trustworthy (both from L200 (Build a Fine-Tuning Dataset)):
- The eval harness exists before training. Define your pass/fail criteria upfront — not after you see the numbers (or you'll rationalize whatever you got).
- Strict train/eval isolation. The test set must have zero overlap with training data, or the score is inflated by memorization (the L199 contamination problem — you'll see it break the verdict in the lab).
With the delta as your north star, you evaluate it across three dimensions.
Dimension 1: Task Performance
First, did the model get better at the thing you fine-tuned it for? Measured on the held-out test, vs the base:
- Closed tasks (classification, extraction, structured output) → exact-match / accuracy / F1 — cheap, deterministic, unambiguous.
- Open-ended generation (summaries, chat, code-with-explanation) → there's no single right string, so use an LLM-as-judge with a rubric (score each output against explicit criteria) at scale, plus human spot-checks on 5–10% to confirm the judge is calibrated.
Report it as base X% → candidate Y%, and keep the slices: overall is fine, but break it down by input category (the L195 coverage map) — a fine-tune often helps the common cases and hurts the edge ones. The number you ship on is the delta, sliced where it matters.
Dimension 2: Win-Rate (Pairwise vs a Baseline)
For generation, a raw judge score ("7.2/10") is shaky — humans and LLMs are far more reliable at comparing two answers than scoring one (the same insight that powers DPO, L202). So the standard for open-ended quality is the pairwise win-rate:
- Put the candidate and a baseline (the base model, or a reference like GPT-class) head-to-head on each prompt; a judge picks win / lose / tie.
- Win-rate = (wins + ½·ties) / total. Above 50% beats the baseline. This is exactly what AlpacaEval 2.0 and MT-Bench report.
The trap: position bias. LLM judges tend to favor whichever answer comes first — so you run both orders (candidate-first and baseline-first) and average. Skip that and your win-rate is an artifact of ordering, not quality (you'll see this toggle in the lab). Watch the disagreements too: if task accuracy went up but win-rate didn't, the metric and human preference are telling you different things.
Dimension 3: Regression — Catastrophic Forgetting
This is the dimension people forget to measure — and it's the #1 silent regression in fine-tuning. When you sharpen a model on a narrow task, it often gets dumber on everything the task didn't exercise. That's catastrophic forgetting: the fine-tune wins on your benchmark while quietly losing general knowledge, reasoning, instruction-following, and safety behavior.
You only catch it if you look for it. Score a general-capability benchmark — MMLU (knowledge), GSM8K/ARC (reasoning), instruction-following, safety/refusals — on both the base and the candidate. If those drop, you have forgetting, even if your task metric soared. Build these regression slices into the harness so you catch it before shipping.
Causes & fixes (all from earlier lessons): too-high LR or too many epochs (L194) → use fewer; full fine-tuning is more destructive than LoRA (L192); gradient conflict between the task and general data accelerates forgetting. Mitigations: replay some general data in the mix, lower the LR, prefer LoRA/PEFT, or merge the fine-tune back toward the base (L204). The rule: a task win that comes with a capability loss is usually not worth shipping.
Is It Real? Statistical Rigor & Contamination
A delta on a screen isn't proof. Two checks decide whether your result is real:
1. Statistical significance. A +0.3-point lift on 50 examples is judge noise, not a win. Quantify the uncertainty: bootstrap the confidence interval — resample the per-example differences with replacement ~1,000 times — and ship on the lower bound of the CI, not the mean. A small eval set gives a wide CI that crosses zero (you can't rule out "no improvement"); a bigger eval set or a larger true lift tightens it above zero. (This is the Container-4 statistical-rigor discipline applied to fine-tuning.)
2. Contamination. If your test set overlaps the training data (or a public benchmark the model has seen), the score is inflated by memorization — it's a lie, not a measurement (L199 decontamination). Always confirm the eval is clean before you trust a single number.
Together: measure the delta, bound its uncertainty, and verify the test is clean. Only a lift whose CI lower bound is above zero on uncontaminated data counts as a win. You'll feel all of this — shrink the eval set and watch the CI swallow zero — in the lab.
In Code: The Eval Harness
The harness scores base and candidate on the same test, computes the delta, bootstraps the CI, and checks the general-capability slice — the whole discipline in one place:
import numpy as np
# Score BASE and CANDIDATE on the SAME held-out, decontaminated test (same judge/rubric).
base_scores = evaluate(base_model, test_set) # per-example: 1.0 / 0.0 (or judge score)
cand_scores = evaluate(candidate, test_set)
delta = cand_scores.mean() - base_scores.mean() # the fine-tune's VALUE is the delta
# BOOTSTRAP a 95% CI on the per-example difference - ship on the LOWER bound.
diff = cand_scores - base_scores
boot = [np.random.choice(diff, len(diff), replace=True).mean() for _ in range(1000)]
lo, hi = np.percentile(boot, [2.5, 97.5])
significant = lo > 0 # a +0.3 lift on 50 examples will NOT pass this
# REGRESSION slice - catch catastrophic forgetting on general capability.
gen_delta = evaluate(candidate, mmlu).mean() - evaluate(base_model, mmlu).mean()
ship = significant and gen_delta > -0.02 # real task lift AND no general-capability loss
# (For generation: also a pairwise win-rate vs baseline, judged in BOTH orders.)See It: The Fine-Tune Eval Lab
Make the ship call yourself. Set a task lift, then shrink the eval set and watch the bootstrap CI widen until it swallows zero — your +5pp is suddenly judge noise. Drag up the general-capability drop to trigger catastrophic forgetting (don't ship!). Flip on contamination and watch the verdict call your score a lie. Turn off position-bias correction and see the win-rate become unreliable. Only when the delta is real, uncontaminated, and regression-free does it say SHIP.

Four gates, one decision: real lift (CI lower bound > 0), clean test (no contamination), no forgetting (general capability held), and worth it (beats base + prompting). Miss any one and you don't ship.
Why This Matters
This is the lesson that keeps you honest — and keeps a fine-tune from quietly making your product worse. The history of fine-tuning is full of teams who celebrated a benchmark jump and shipped a model that had forgotten how to follow basic instructions, or whose "win" was judge noise on 40 examples, or whose eval was contaminated by the very data they trained on. Knowing how to measure the delta, bound it statistically, and check for regression is what lets you say — with evidence — "this fine-tune is better, ship it" or "this isn't worth it, the base does fine." That judgment is the whole point of post-training. Next, you put all of Section 4 (and the section before it) together: L206 (Hands-On: Fine-Tune a Small Model with LoRA) — train, and evaluate, a real model end to end.
🧪 Try It Yourself
Find all four ship-blockers in the Fine-Tune Eval Lab:
- The noise mirage. Set a +5pp lift with eval set N = 40. Does the bootstrap CI lower bound clear zero? Now raise N until it does. Why is "+5pp" meaningless without N?
- The silent loss. Set a big task lift but drag general-capability drop to −12pp. Why does the lab refuse to ship — and what is this failure called?
- The contaminated win. Turn on contamination with a healthy lift. Why is the impressive task number now a lie?
Bonus: your fine-tune scores 87% and the base scores 85% with a good prompt. In one sentence, should you ship the fine-tune — and what's the real question you should be asking?
Mental-Model Corrections
- "Report the fine-tune's accuracy." Report the delta vs the base on the same test — the absolute number alone tells you nothing about whether fine-tuning helped.
- "The task metric went up, so ship it." Not until you check general-capability regression (catastrophic forgetting) and statistical significance. A task win can hide a capability loss.
- "A higher score is a real improvement." A small lift on a small eval set is judge noise. Bootstrap the CI and ship on the lower bound.
- "An LLM judge is objective." It has position bias (favors the first answer), verbosity bias, and self-preference. Run both orders, and spot-check with humans.
- "Build the eval after training." Build it before — define pass/fail upfront and keep the test decontaminated, or you'll fool yourself.
Key Takeaways
- A fine-tune is only as good as your proof. Always measure the delta vs the base on the same held-out, decontaminated test (same rubric, same judge).
- Three dimensions: task performance (accuracy / LLM-as-judge), win-rate (pairwise vs baseline, both orders for position bias), and general-capability regression — catch catastrophic forgetting by scoring MMLU/GSM8K base-vs-candidate.
- Prove it's real: a small lift on a small set is judge noise — bootstrap the CI and ship on the lower bound, not the mean.
- Keep it clean: contamination inflates scores into a lie — decontaminate first (L199).
- The harness exists before training, with pass/fail criteria and regression slices built in.
Next: L206 — Hands-On: Fine-Tune a Small Model with LoRA — the capstone that trains and evaluates a real model end to end.