Majid Al-RaimiEvaluating language models with perplexity

ICS 582Lecture 03Part 04

Evaluating language models with perplexity

Extrinsic versus intrinsic evaluation, train, dev and test splits and contamination, and perplexity as the length-normalized inverse probability, read as a weighted branching factor.

Concepts
5
Slides
29-41
Reading
30 min
Understood
0/5 concepts

Why this part matters

Every language model paper you will read, from KenLM n-gram models to GPT-scale transformers, reports perplexity. On the exam you will be asked to compute it by hand and to explain why test data must stay unseen. In research, knowing when a perplexity comparison is invalid (leaked test data, a different vocabulary or tokenizer, a different boundary convention) is what separates a real gain from an artifact. In real systems, perplexity is the cheap signal you iterate on before paying for an end-to-end word error rate or BLEU run.

The part moves in five steps. First, what "better" even means for a language model and the two ways to measure it. Then the discipline of held-out data that makes any measurement honest. Then the definition of perplexity, derived from the probability of a test set, followed by the conventions you need to compute and compare it fairly. It ends with the most useful intuition for the number: an effective count of choices.

By the end you can

  1. Distinguish extrinsic from intrinsic evaluation and say when each is worth its cost.
  2. Explain the roles of training, dev and test sets, and how data contamination makes perplexity misleadingly low.
  3. Define perplexity as P(W)^(-1/N), expand it with the chain rule, and write the unigram and bigram forms.
  4. Compute perplexity by hand, in probability space and in log space, for a short sequence.
  5. State the conditions for a fair perplexity comparison: same test set, vocabulary, tokenization and boundary convention.
  6. Interpret perplexity as a weighted average branching factor, using the 3-color example.

Suppose you have two speech recognizers that are identical in every way except their Language model. The most convincing way to decide which LM is better is to run both systems on the same real audio and count how many words each gets wrong. Whichever has the lower word error rate has the better LM, for this task, on this data.

That is Extrinsic evaluation: you embed the model in an application and measure the application. SLP3 calls it "the only way to know if a particular improvement in the language model ... is really going to help the task at hand". Its weakness is cost. Every candidate model needs a full end-to-end run, and if you are trying twenty smoothing settings in an afternoon, twenty ASR decodes is not an option. Intrinsic evaluation trades realism for speed: it scores the model by itself, independent of any application. The standard intrinsic metric, for n-gram models and for neural LLMs alike, is Perplexity, which this part builds up step by step.

Extrinsic evaluationIntrinsic evaluation
What is measuredThe whole application with this LM plugged inThe LM alone, on held-out text
Typical metricWord error rate for ASR, BLEU or COMET for MTPerplexity
Cost per candidate modelA full end-to-end run of the systemOne pass of the LM over the test set
RealismThe only proof that the task improvedA proxy that usually, not always, tracks the task
When to use itBefore you claim a gain, and for final decisionsWhile iterating on many model variants
Extrinsic versus intrinsic evaluation of a language model

What "better" means: the Shannon game

To score a model by itself we need a definition of good that does not mention any application. The Shannon game supplies one. Cover the next word and ask the model to bet on it: "I always order pizza with cheese and ___". A good model spreads its bets over sensible continuations, say 0.1 on mushrooms, 0.1 on pepperoni, 0.01 on anchovies, a sliver on fried rice, and essentially nothing (10^-100 on the slide) on the word "and". Shannon ran the original version of this experiment in 1951 with letters rather than words, asking people to guess the next character of English text to estimate how predictable the language is. Contexts differ in how open they are: after "The 33rd President of the US was" almost all the probability belongs to one name, while after "I saw a" thousands of nouns are reasonable. The last concept of this part turns that difference into a number.

A Unigram model plays this game badly. It ignores the context entirely, so after "cheese and" it bets the same way it bets everywhere, heavily on frequent words like "the". The rule that falls out is simple: a better model is one that assigns a higher probability to the word that actually occurs. A perfect model would give each real next word probability 1. Applied to a whole held-out text, the better model gives the test text a higher probability, and perplexity is just a length-normalized way of reporting that probability.

Recall

You have twenty smoothing settings to try for a speech recognizer. Which evaluation do you use while iterating, which before claiming a gain, and why?

Intrinsic evaluation (perplexity on held-out text) while iterating, because it needs only one LM pass per variant. Extrinsic evaluation (word error rate of the full recognizer) before claiming a gain, because it is the only proof the task improved and perplexity gains do not always transfer.

You build a Bigram model and, by accident, five of your test sentences are also in the training corpus. Every bigram in those sentences now has a nonzero count, so the model assigns them a much higher probability than it would to genuinely new text, and the Perplexity drops. The model has not improved at all. It has simply seen the answers.

SLP3 names this precisely: if a test sentence is part of the training corpus, "we will mistakenly assign it an artificially high probability", a situation called training on the test set, or Data contamination, and it "causes huge inaccuracies in perplexity". The cure is to split the data into three disjoint parts with different jobs: a Training set, a Development set and a Test set.

Train, dev and test as three disjoint blocks. When test text leaks into training, the perplexity needle swings to a value that is too good to be true.

The three splits and how often you may look at each

Training set
Supplies the n-gram counts, so it decides every probability in the model. Look at it as often as you like.
Development set (devset)
Held out from training and used to tune hyperparameters such as an interpolation weight λ or the k of add-k smoothing. Look at it after every change; that is its job.
Test set
Held out from both, drawn from the target domain, large enough for a statistically significant comparison. Run it once, or a very few times, at the end.

The devset exists because models have knobs. Interpolation weights, the k of add-k smoothing and the discount in Kneser-Ney are all hyperparameters: they are not learned from counts, so they must be chosen by trying values and keeping the best. If you choose them by checking the test set, the test set has become part of training by another route. SLP3's rule is to do all testing on the devset "until the very end" and to run the test set "once, or a very few number of times".

Two further requirements make the test set meaningful. It should be drawn from the domain you care about: if the model will transcribe chemistry lectures or hotel booking requests, the test text should be chemistry lectures or booking requests, and the devset should look like the test set. And it should be large enough to give the statistical power to show a significant difference between two candidate models. A ten-sentence test set can make any two models look different by luck.

Quick check

For two weeks you pick interpolation weights by checking test-set perplexity after each change. What is the main problem?

The obvious intrinsic score is the probability the model assigns to the test set. It has one fatal flaw. The same Bigram model might give a 5-token sentence a probability around 10^-5 and a 50-token paragraph around 10^-50. Every extra token multiplies in another factor below 1, so raw probability mostly measures length, and two test sets of different sizes cannot be compared.

The running product of next-word probabilities for <s> i want english food </s> plunges on a log axis, while the per-token geometric mean (teal) stays near the top. Normalizing by length is what makes a comparable score.

Perplexity fixes this by taking the Nth root, which turns the product of N factors into a per-token average, and by inverting it so that the number grows as the model gets more surprised. For a test set W = w_1 ... w_N:

PP(W)=P(w1w2…wN)−1N=1P(w1w2…wN)N\begin{aligned} \mathrm{PP}(W) &= P(w_1 w_2 \ldots w_N)^{-\frac{1}{N}} \\ &= \sqrt[N]{\frac{1}{P(w_1 w_2 \ldots w_N)}} \end{aligned}
Perplexity: the inverse probability of the test set, normalized by the number of tokens (SLP3 Eq. 3.14)

Expanding the joint probability with the Chain rule of probability turns it into a product of next-word probabilities, so perplexity is the geometric mean of the inverse next-word probabilities:

PP(W)=∏i=1N1P(wi∣w1…wi−1)N\mathrm{PP}(W) = \sqrt[N]{\prod_{i=1}^{N} \frac{1}{P(w_i \mid w_1 \ldots w_{i-1})}}
Chain-rule form (SLP3 Eq. 3.15)

A specific model only changes what goes in the denominator. A Unigram model uses P(w_i); a bigram model, under the Markov assumption, uses P(w_i | w_(i-1)).

ModelEach factor inside the rootPerplexity
Unigram1 / P(w_i)PP(W) = (Π 1 / P(w_i))^(1/N)
Bigram1 / P(w_i | w_(i-1))PP(W) = (Π 1 / P(w_i | w_(i-1)))^(1/N)
Any model1 / P(w_i | w_1 ... w_(i-1))PP(W) = P(w_1 ... w_N)^(-1/N)
Perplexity for the unigram and bigram models (SLP3 Eq. 3.16 and 3.17)

Because the exponent is negative, lower perplexity means higher test probability. For a fixed test set N is fixed, and P^(-1/N) is strictly decreasing in P, so minimizing perplexity is exactly the same as maximizing the probability of the test set. The inversion is not arbitrary: it comes from the original definition of perplexity as two raised to a cross-entropy rate, which Part 10 develops.

A worked example with the Berkeley bigrams

Worked example

Perplexity of <s> i want english food </s>

  1. Multiply bigram probabilities

    Using the Berkeley Restaurant Project corpus estimates from SLP3: P(i | <s>) = 0.25, P(want | i) = 0.33, P(english | want) = 0.0011, P(food | english) = 0.5, P(</s> | food) = 0.68. The product is 0.25 × 0.33 × 0.0011 × 0.5 × 0.68 = 0.0000309 (SLP3 rounds it to 0.000031).
  2. Count N

    Five tokens were predicted: i, want, english, food and the end marker. The start marker is given, never predicted, so N = 5.
  3. Take the Nth root of the inverse

    PP = 0.0000309^(-1/5). In logs: log2 0.0000309 ≈ -14.98 bits, divided by 5 gives ≈ 3.00 bits per token, and 2^3.00 ≈ 7.98.
  4. Result

    PP ≈ 7.98. Per token, the model was about as uncertain as a fair choice among roughly 8 words, even though one factor (0.0011) was very small.

Compute it in log space

On a real test set of a million tokens the product underflows any floating-point type, so in practice you sum log probabilities instead, average them, and exponentiate once at the end:

PP(W)=2−1N∑i=1Nlog⁡2P(wi∣w1…wi−1)\mathrm{PP}(W) = 2^{-\frac{1}{N}\sum_{i=1}^{N} \log_2 P(w_i \mid w_1 \ldots w_{i-1})}
The same quantity, computed as two to the average number of bits of surprise per token

The exponent is the average number of bits the model needs per token, which is the bridge to cross-entropy in Part 10. The base does not matter as long as it matches: Hugging Face defines perplexity as "the exponentiated average negative log-likelihood of a sequence", using natural logs and exp, which gives the same number. The same documentation notes that perplexity is not well defined for masked models such as BERT, because they do not assign a left-to-right probability to the sequence.

Recall

Why is minimizing perplexity the same as maximizing test-set probability?

For a fixed test set, N is fixed and PP = P^(-1/N) is strictly decreasing in P. Any change that raises the test probability lowers the perplexity, and vice versa.

Recall

SLP3 exercise 3.12: training has 91 zeros and one each of the digits 1 to 9. The test set is 0 0 0 0 0 3 0 0 0 0. What is the unigram perplexity?

P(0) = 91/100 = 0.91 and P(3) = 0.01. With N = 10, PP = (0.91^9 × 0.01)^(-1/10) ≈ 1.73. The test set is mostly zeros, which the model predicts well, so the effective number of choices is far below 10.

Quick check

Why does perplexity take the Nth root of the inverse test-set probability?

Computing and comparing perplexity honestly

SLP3 trained Unigram, Bigram and Trigram models on 38 million words of Wall Street Journal text and measured Perplexity on a 1.5 million word test set. The results were 962, 170 and 109.

ModelPrevious words usedTest perplexity
Unigram0962
Bigram1170
Trigram2109
WSJ test perplexity by model order (SLP3 section 3.3)
Each extra word of context (teal chips) shortens the perplexity bar, drawn on a log scale: 962, then 170, then 109. The second word of context helps less than the first.

More context gives the model more information about the next word, so it is less surprised and its perplexity falls. Notice the diminishing return: the first word of context cuts perplexity by a factor of more than five, the second by about a third. The catch is data. A trigram model needs reliable counts for three-word sequences, and Sparsity grows fast with the order, so the gain holds only when the training set is large enough to estimate the longer n-grams. With too little data a higher order can be worse, which is the subject of Part 06.

Conventions that change the number

A real test corpus is many sentences, not one, so the model is run over the whole stream and the probability runs across sentence boundaries. If you use Sentence boundary tokens, they enter the count. SLP3 includes one token per sentence in N: the end marker </s>, but not the start marker <s>. The reason is that </s> is a genuine prediction (the model must decide where the sentence ends), while the step from </s> to the next <s> happens with probability almost 1, so counting it would add an almost-free token and flatter the score.

The deeper rule is that perplexity is a property of a model, a test set and a vocabulary together. SLP3 states that the perplexity of two language models "is only comparable if they use identical vocabularies". A model with a 10k-word vocabulary maps every rarer word to a single unknown token and then predicts that token easily, so its perplexity is lower on a task that is genuinely easier. In modern subword models the same applies to tokenization: Hugging Face warns that "the tokenization procedure has a direct impact on a model's perplexity". Even the evaluation procedure matters. GPT-2 large on WikiText-2 scores 19.44 with non-overlapping 1024-token windows and 16.44 with a sliding window of stride 512, because each token gets more context.

Perplexity is not the task

Lower perplexity often correlates with better downstream performance, which is why everyone uses it, but SLP3 is explicit that an intrinsic improvement "does not guarantee an (extrinsic) improvement". When the decision matters, confirm with the task metric: Extrinsic evaluation with word error rate for speech, BLEU or COMET for translation.

Recall

When using <s> and </s>, which one do you count in N, and why?

Count </s> but not <s>. </s> is a real prediction, the decision of where the sentence ends. <s> is never predicted: the transition from </s> to the next <s> has probability near 1, so counting it would distort perplexity (SLP3 footnote 2).

Recall

What do the WSJ results 962, 170 and 109 say, and what is the catch?

More context means the model is less surprised: a smaller effective branching factor. The catch is that higher orders need enough training data to estimate their counts reliably, otherwise sparsity erases the gain.

Recall

Give two reasons why a reported perplexity can be misleadingly low.

Test data leaked into training (contamination), or the model was tuned repeatedly on the test set. Also acceptable: a smaller vocabulary, a different tokenization or a more generous evaluation window, any of which makes the number not comparable with others.

Quick check

Team A reports perplexity 85 with a 10k-word vocabulary. Team B reports 120 with a 50k-word vocabulary on the same text. What follows?

Perplexity as a weighted branching factor

Take a toy language with three words, red, blue and green, where any word can follow any word. At every position there are three possible next words, so its Weighted branching factor is 3. Model A knows nothing and gives each word probability 1/3. On any test set of five words, PP_A = ((1/3)^5)^(-1/5) = 3. A uniform model's perplexity is exactly the number of choices.

Now Model B has learned that red is common: P(red) = 0.8, P(blue) = P(green) = 0.1. On the textbook Test set "red red red red blue", the probability is 0.8^4 × 0.1 = 0.04096 and PP_B = 0.04096^(-1/5) ≈ 1.89. Three words are still possible at every step, but the model is effectively choosing among fewer than two.

Three branches with equal weight at rest. Model B thickens red to 0.8 and thins blue and green to 0.1, and the effective number of branches shrinks from 3 to about 1.89 on the test set red red red red blue.

This is the intuition SLP3 offers: perplexity is the weighted average branching factor. The plain branching factor counts the possible next words. Perplexity weights them by how much probability the model puts on the words that actually occur, and reports the size of a uniform choice that would leave you equally uncertain. So the WSJ Trigram's 109 means that, on average, the model was as unsure as if it were picking uniformly from about 109 words at each step, out of a vocabulary of tens of thousands.

Worked example

One language, two models, two test sets

  1. Uniform model A

    Every factor is 1/3, so P(T) = (1/3)^5 and PP = 3 on any test set.
  2. Skewed model B on the textbook test set

    P(T) = 0.8^4 × 0.1 = 0.04096. In bits, log2 0.04096 ≈ -4.61, which is 0.922 bits per token, and 2^0.922 ≈ 1.89.
  3. Same model B on an all-blue test set

    P(T) = 0.1^5, so PP = (0.1^5)^(-1/5) = 10.
  4. Result

    3, 1.89 and 10. Skew helps only when it points at the words that actually occur; pointed the wrong way, it makes the model worse than knowing nothing.
ModelTest setP(T)Perplexity
A: uniform, 1/3 eachany 5 words(1/3)^5 ≈ 0.00413
B: red 0.8, blue 0.1, green 0.1red red red red blue0.8^4 × 0.1 = 0.04096≈ 1.89
B: red 0.8, blue 0.1, green 0.1blue blue blue blue blue0.1^5 = 0.0000110
The 3-color language under two models and two test sets

Recall

A uniform model over a vocabulary of V words is tested on any text. What is its perplexity?

Exactly V, since PP = ((1/V)^N)^(-1/N) = V. This is the plain branching factor, with no weighting.

Quick check

Model B has P(red) = 0.8 and P(blue) = P(green) = 0.1. What is its perplexity on the test set blue blue blue blue blue?

Recap

If you remember nothing else

  • Extrinsic evaluation (WER, BLEU/COMET inside a task) is the real test but costs a full run. Intrinsic evaluation with perplexity is cheap and fast for iterating.
  • Training counts, the devset tunes hyperparameters, the test set is touched once. Leaking or repeatedly tuning on test data makes perplexity look too good.
  • PP(W) = P(w_1...w_N)^(-1/N): the geometric mean of inverse next-word probabilities. Lower is better, and minimizing PP is maximizing test probability.
  • Compute it in log space: PP = 2^(-(1/N) Σ log2 P). A single zero probability makes PP infinite.
  • With boundary tokens, count </s> in N but not <s>, and keep the convention fixed across models.
  • WSJ, 38M training words, 1.5M test words: unigram 962, bigram 170, trigram 109. More context helps when there is enough data.
  • Perplexities are comparable only with identical vocabularies and tokenization. Lower PP usually, but not always, means better task performance.
  • Perplexity is a weighted branching factor: uniform over 3 colors gives 3. P(red) = 0.8 on red red red red blue gives about 1.89. The same model on all blue gives 10.

Sources