Skip to main content
Fanout
Evaluating a Fine-Tune
Curriculum overview

How to Fine-Tune Models · lesson 05/5

Evaluating a Fine-Tune

Training loss tells you how well the model fits the training set, not whether the fine-tune is good. Evaluating a fine-tune means measuring the target task on held-out data and confirming that general ability did not regress along the way.

The idea

Answer two separate questions:

  • Did it learn the target task? Score a held-out set built the same way as the training data.
  • Did it forget anything else? Run a small general benchmark or a held-out slice of general instructions before and after training.

The minimum baseline is the base model with a prompted version of the same task. Comparing a fine-tune only to its own untrained self proves nothing about whether the fine-tune was worth the cost.

Setup decisions that make results trustworthy:

  • Keep three splits. Train on one, tune hyperparameters on validation, touch test once.
  • Split by source so near-duplicates cannot leak across the boundary.
  • Fix decoding. Greedy and sampled generations are not comparable; neither are different token limits.
  • Pick metrics that match the task: exact match or F1 for classification, pass rate on unit tests for code, a rubric-based human or LLM judge for open-ended answers, plus a format-validity rate.
  • Use enough items. A 50-item test with a two-point win is noise.

Scores alone hide failure modes, so read 20 to 50 outputs and group the mistakes. Catastrophic forgetting usually shows up as a generic-ability drop, and mixing a small fraction of general data into training is a common fix.

Worked example

Suppose 100 held-out classification items give the following confusion matrix:

Predicted positivePredicted negative
Actual positive426
Actual negative844

Precision is 42/50 = 0.84, recall is 42/48 = 0.875, and F1 is about 0.857. Now suppose the prompted base model scores 0.79 precision and 0.81 recall on the same items. The fine-tune is ahead, but 100 items is a small sample: the difference is well within noise, so collect more before shipping. Reading the eight false positives matters more than the third decimal — if they are all one class, the dataset balance is the real problem.

In code

@torch.no_grad()
def exact_match(model, tok, items, max_new_tokens=64):
    model.eval()
    correct = 0
    for item in items:
        prompt = tok.apply_chat_template(
            item["messages"][:-1], tokenize=False, add_generation_prompt=True
        )
        enc = tok(prompt, return_tensors="pt").to(model.device)
        out = model.generate(**enc, max_new_tokens=max_new_tokens, do_sample=False)
        pred = tok.decode(out[0][enc["input_ids"].shape[1]:], skip_special_tokens=True)
        correct += pred.strip() == item["answer"].strip()
    return correct / len(items)

Greedy decoding (do_sample=False) makes the run reproducible. Report the metric next to the count of items it was computed on.

Check yourself

  1. Training loss falls to nearly zero, yet the fine-tune is worse in production. Give two explanations.
  2. Why is the prompted base model the minimum baseline for a fine-tune?
  3. What is the difference between the validation set and the test set in a fine-tuning run?

Key takeaways

  • Evaluate the target task on held-out data and always compare against a prompted base model.
  • Check for regressions on general ability, because fine-tuning can forget.
  • A small test set makes small wins meaningless; report the sample size with every score.