Entropy and surprise
Measure uncertainty in bits.
Create a free account Try part of it here
Why it matters
Some things are easy to predict. After "Thank you for your", the next word is fairly easy to guess: "help", "time", "order". A product code like "XK-7Q2" is not. Information theory puts a number on that difference. It measures uncertainty in units called bits. The same number explains why a zip program shrinks some files a lot and others hardly at all. Most important here, it's the base of the loss function every language model is trained with (cross-entropy, the next lesson). It also tells you how sure a model is about its next word.
What you'll be able to do
- Measure the surprise of an event in bits
- Compute the entropy of a distribution as its average surprise
- Explain why entropy is highest for uniform distributions and zero for certain ones
- Use entropy to describe how uncertain a model's prediction is
What it covers
- How surprising is an event?
- Entropy: the average surprise
- How sure is the model?
- Worked example: two lunch habits
- Entropy and compression
How surprising is an event?
A friend texts you: "The sun came up this morning." That tells you nothing new. You were sure it would. Then they text: "It snowed in the desert today." That's real news. You'd never have guessed it.
The rarer an event, the more you learn when it happens. Information theory turns this into a number called surprise. It's also called information content. It's measured in bits.
One bit is the news in a single yes/no answer, when both answers are equally likely. A fair coin is the classic case. Before the flip, you don't know. Afterward, you know one yes/no fact: heads or not. That's 1 bit.
The guessing game
Now play a game. A friend picks one of 8 cards, each equally likely. You may only ask yes/no questions. "Is it one of the first four?" cuts the choices in half. Halve three times and only one card is left. So finding out which card it was is worth 3 bits. Each halving is one bit.
That gives a rule of thumb. Count how many times you'd halve the choices to pin the event down:
- a 1-in-2 event: one halving, 1 bit;
- a 1-in-8 event: three halvings, 3 bits;
- a certain event: nothing to pin down, 0 bits.
You met this kind of counting in the exponentials and logarithms lesson. "How many 2s do I multiply to reach 8?" is . So for an event with probability , the surprise is:
The letter stands for information. Both forms give the same answer. Books usually write the second one, with the minus sign.
In plain words: flip the probability upside down, then ask "how many 2s multiply to make this?" A 1-in-8 event has surprise bits. For numbers between powers of 2, the answer isn't a whole number. A 1-in-52 event gives about 5.7. The rarer the event, the bigger the surprise.
| Event | Probability | Surprise |
|---|---|---|
| a certain event | 1 | 0 bits |
| a fair coin landing heads | 1/2 | 1 bit |
| a specific card from a deck | 1/52 | 5.7 bits |
| a 1-in-a-million event | 0.000001 | 19.9 bits |
A one-in-a-million event is only about 20 bits. Each extra bit halves the odds, so the numbers grow slowly. Here is the same table in Python:
import math def surprise(p): return math.log2(1 / p) # same as -log₂ p print("certain event: ", surprise(1)) print("fair coin heads: ", surprise(1 / 2)) print("one card from 52:", round(surprise(1 / 52), 1)) print("1 in a million: ", round(surprise(1 / 1_000_000), 1))
Surprises add up
Flip two fair coins. The chance of two heads is 1/2 × 1/2 = 1/4. Its surprise is bits. That's 1 bit for each coin, added together.
This is why surprise uses a logarithm. When two events are independent (one doesn't affect the other), their probabilities multiply. A logarithm turns multiplying into adding. So the surprises of independent events add up, like the news from two separate texts.
Go deeper Why the log makes surprises add
Say two independent events have probabilities and . The chance of both is . The log of a product is the sum of the logs:
Read it as: "the surprise of both events equals the surprise of the first plus the surprise of the second." With two coins: , which is 2 bits.
Base 2 gives the answer in bits. Other bases give other units. You'll meet one near the end.
import math p = 1 / 8 print(math.log2(1 / p))
Show the answer
3.0
Flip 1/8 upside down to get 8. Since 2 × 2 × 2 = 8, log₂ 8 = 3. A 1-in-8 event carries 3 bits of surprise: the three halvings of the card game. (Without the flip, math.log2(1 / 8) would print -3.0. That's why the other form has a minus sign.)
Entropy: the average surprise
Surprise is about one event. Entropy is about a whole situation: every outcome that could happen, with its probability. A list like that is a distribution.
Picture two towns. In a desert town, it's sunny 9 days in 10 and rains 1 day in 10. In a coin-flip town, sun and rain are equally likely.
In the desert town, most days bring almost no news. A sunny day has a surprise of , about 0.15 bits. A rainy day is a shock: , about 3.32 bits. But rain is rare. So on average, how much news does the weather bring?
Weight each surprise by how often it happens, then add:
- sunny: 0.9 × 0.152 = 0.137 bits;
- rainy: 0.1 × 3.322 = 0.332 bits;
- average: 0.137 + 0.332 = 0.469 bits per day.
The coin-flip town gets a full 1 bit every day. Its weather is harder to predict, so its entropy is higher.
That weighted average is the entropy. As a formula:
The letter stands for entropy. is the probability of outcome number . The big (sigma, a Greek capital S) means "add this up over every outcome". In Python, it's a for loop or a sum.
In plain words: for each outcome, multiply its probability by its surprise. Add up the results. The total is how many bits of news you get on average. That's how uncertain the situation is.
One small rule: an outcome with probability 0 never happens, so it adds nothing. Books say is treated as 0. The code below drops those outcomes with p[p > 0]. Then it multiplies each probability by its surprise, np.log2(1 / p), and adds the results.
import numpy as np def entropy(p): p = np.asarray(p, dtype=float) p = p[p > 0] return np.sum(p * np.log2(1 / p)) # same as -Σ p log₂ p print("fair coin: ", entropy([0.5, 0.5])) print("biased coin 90/10:", round(entropy([0.9, 0.1]), 3)) print("certain: ", entropy([1.0, 0.0])) print("fair 8-sided die: ", entropy([1 / 8] * 8))
The 90/10 coin gives 0.469 bits, the same as the desert town. The 8-sided die gives 3 bits, the same as the 8-card game. Three patterns show up:
- Entropy is zero when one outcome is certain. There's nothing to learn.
- It's largest when all outcomes are equally likely. Call the number of outcomes . Then the largest possible entropy is bits. The die has 8 sides, and .
- In between, the more lopsided the distribution, the lower the entropy.
Go deeper Why outcomes with probability 0 count as 0
The formula asks for , which doesn't exist. But look at what happens as a probability shrinks toward 0. At , the outcome's share is 0.001 × 9.97, about 0.01 bits. The smaller gets, the closer its share gets to 0. So treating it as exactly 0 is the natural choice. Code has to skip those outcomes, or NumPy returns nan ("not a number").
Show the answer
1.5 bits
Red: 0.5 × 1 bit = 0.5. Blue: 0.25 × 2 bits = 0.5. Green: also 0.5. The total is 1.5 bits. That's a little below the 1.58-bit maximum for 3 outcomes, because the spinner favors red.
Entropy of a next-word distribution. Push one score far above the others and entropy falls toward 0. Make the scores equal and it reaches the maximum, log₂ 4 = 2 bits.
Show the answer
[0.25, 0.25, 0.25, 0.25]
Equal odds are the most uncertain case. With 4 outcomes, that's log₂ 4 = 2 bits.
How sure is the model?
A language model predicts the next token (a word or a piece of a word). It gives a probability for every token it knows. That list is a distribution, so it has an entropy too.
After "The capital of France is", nearly all the probability sits on " Paris". The entropy is close to 0: the model is confident. After "My favorite color is", the probability spreads across many colors. The entropy is higher: the model is less sure, and rightly so.
import numpy as np def entropy(p): p = np.asarray(p, dtype=float) p = p[p > 0] return np.sum(p * np.log2(1 / p)) # same as -Σ p log₂ p capital = {"Paris": 0.96, "a": 0.02, "located": 0.01, "the": 0.01} color = {"blue": 0.28, "green": 0.2, "red": 0.17, "purple": 0.13, "black": 0.12, "yellow": 0.1} print("after 'The capital of France is':", round(entropy(list(capital.values())), 2), "bits") print("after 'My favorite color is': ", round(entropy(list(color.values())), 2), "bits")
The capital prompt scores about 0.3 bits. The color prompt scores about 2.5 bits. Six equally likely colors would give the maximum, , about 2.58 bits. So the model's color guess is close to a shrug.
This is useful in practice. High entropy on a factual question can signal that the model is unsure. That's a hint it might hallucinate: give a fluent answer that's made up. Some systems use entropy to decide when to fetch more context or ask a clarifying question.
Watch out: low entropy means confident, not correct. A model can put 96% on a wrong answer.
Worked example: two lunch habits
Sam eats lunch at four spots, each equally often. Alex eats at a favorite cafe 7 days in 10. On the other 3 days, Alex picks one of three other spots, evenly. Whose lunch is harder to predict, and by how much?
import math sam = [0.25, 0.25, 0.25, 0.25] # four spots, equally often alex = [0.7, 0.1, 0.1, 0.1] # a favorite cafe, plus three others for name, probs in [("Sam", sam), ("Alex", alex)]: h = sum(p * math.log2(1 / p) for p in probs) print(name, "entropy:", round(h, 2), "bits") print("Alex at the cafe: ", round(math.log2(1 / 0.7), 2), "bits of surprise") print("Alex anywhere else: ", round(math.log2(1 / 0.1), 2), "bits of surprise")
Sam's lunch has 2.0 bits of entropy. That's the maximum for four options, since . Alex's lunch has 1.36 bits, so it's easier to predict. A day at the cafe carries only 0.51 bits of surprise. A day anywhere else carries 3.32 bits, but those days are rare.
Think back to the guessing game. To learn Sam's spot, you need 2 yes/no questions every time. For Alex, ask "The cafe?" first. Seven days in 10, one question settles it. That plan averages 1.5 questions. No plan can average fewer questions than the entropy, 1.36.
Entropy and compression
Think about how you text. You type "lol" and "brb" for things you say all the time. You spell out rare words in full. Short codes for common things, longer codes for rare ones. Morse code works the same way: E, the most common letter in English, is a single dot.
Entropy sets the limit on this trick. On average, you can't record outcomes in fewer bits than the entropy of their distribution. Predictable data has low entropy, so it shrinks a lot when you zip it. Random data has high entropy, so it barely shrinks at all.
This links straight back to language models. A model that predicts text well can be used to compress text well. In a precise sense, a good predictor of text is a good compressor of text. A model's training loss is measured in the same units as entropy. You'll meet that loss, cross-entropy, in the next lesson.
Note: with natural logs (
np.log), entropy comes out in nats instead of bits. 1 nat is about 1.44 bits. Training code usually uses natural logs. The ideas are identical.
Show the answer
A server log where 99% of the lines say "OK"
The log is very predictable, so its entropy is low and it compresses well. Random bytes and encrypted data look like noise: high entropy, so they barely shrink.
Practice what you just read
- 4 code examples you can edit and run
- a practice exercise that checks your code
- a 5-question quiz
- 4 review cards for spaced repetition
Try a quiz question
What does an entropy of 0 mean for a model's next-token distribution?