Source coding: compression is prediction
Before this lesson: lesson 01 (surprisal, entropy, the question game), lesson 02 (the chain rule, used for blocks of symbols), lesson 03 (KL divergence, Gibbs' inequality) and lesson 04 (, bits per byte). Time: about 70 minutes, plus the notebook.
Why this matters #
Lesson 01 called entropy "the average number of yes/no questions". This lesson makes that exact: entropy is the smallest average number of bits per symbol that any lossless code can reach. This turns log-loss into a physical quantity.
- Language models report losses in bits per byte (lesson 04). With arithmetic coding, that number is the size of the compressed text. Delétang et al. (2024) show that large language models are strong general-purpose compressors.
- Every compressor ends with an entropy coder: zip, gzip and PNG (Huffman coding), JPEG, zstd (Huffman and asymmetric numeral systems), learned image codecs (arithmetic coding with a neural model).
- Model compression: quantized weights are often entropy-coded, and the entropy of the quantized values is a lower bound on the bits per weight of such a code.
- Minimum description length (MDL) chooses between models by the total length of model plus data: a principled form of Occam's razor.
As in the whole track, is the natural log (nats) and gives bits. In this lesson all code lengths and entropies are in bits. We write for the KL divergence in bits ( in nats divided by ).
1. Predict first #
2. The picture #
Fixed length vs variable length #
Four symbols have probabilities . A fixed-length code () needs 2 bits per symbol. Now try a variable-length code: , , , . On average it needs
This is exactly the entropy bits. Look at the lengths: each one equals the surprisal of its symbol (, , ). This code is the question game of lesson 01: the bits are the answers to "is it ?", "is it ?", "is it ?".
Prefix-free codes decode instantly #
A code is prefix-free (also called a prefix code) when no codeword is the beginning of another codeword. Then you can read the bits from left to right and output a symbol as soon as a codeword is complete. You need no separators:
Step by step: the first bit is a codeword (), so output . The next bits , are not codewords, is (). The last three bits give .
The code tree and the budget #
Draw each codeword as a path in a binary tree: = go left, = go right. A code is prefix-free exactly when every codeword is a leaf: no codeword lies on the path to another one.
Now the key picture. Read a codeword of length as the binary fraction . All infinite bit strings that start with fill an interval of length in . For example, owns , an interval of length .
- Prefix-free means that these intervals do not overlap.
- The intervals lie inside , so their lengths add up to at most 1.
So a code has a budget of 1, and a codeword of length costs of it. Short codewords are expensive: a 1-bit codeword uses half of the budget. How should you spend the budget? Give each symbol a share close to its probability: , that is, . This is the whole theory in one line. Section 3 makes it exact.
Pick a symbol, then click a node of the tree to give that symbol this codeword. The bar below the tree shows the interval of each codeword in ; its length is the codeword's share of the budget (orange, the code's model). The blue bar shows the probabilities for comparison. Watch the Kraft sum and the average length against the entropy . Try "not prefix-free": two intervals overlap (yellow) and the code cannot be decoded instantly.
Is the code prefix-free?
is a prefix of , so after reading a you cannot know yet whether the symbol is complete. ( is not a codeword, so it does not matter that starts with .) The Kraft sum only says that some prefix code with lengths exists, for example . This code is still uniquely decodable (read it from the right end), but not instantly.
A binary prefix code has lengths . Can you add a fifth codeword without changing the other four?
. Any new codeword of length would need more budget, and the sum would exceed 1. In the tree, every leaf is taken. A code with Kraft sum 1 is called complete.
3. Definitions and main results #
Setup. A source takes values () with probabilities .
- A binary symbol code gives symbol a codeword , a string of bits of length .
- The expected length is bits per symbol.
- A code is uniquely decodable if every concatenation of codewords can be split in only one way.
- A code is prefix-free if no codeword is a prefix of another. Prefix-free codes are uniquely decodable, and they decode instantly.
- is the smallest expected length over all prefix codes.
- A code with is complete.
3.1 The Kraft inequality #
Theorem 1 (Kraft inequality). (a) The lengths of every binary prefix code satisfy . (b) Conversely, if positive integers satisfy , then there is a prefix code with these lengths.
Proof of (a), with the tree.
- Let . The bit strings of length are the leaves of the full binary tree of depth .
- The codeword has descendants among these leaves: the strings that start with .
- Prefix-free means that these sets of descendants are disjoint. (A string that starts with both and would make one of them a prefix of the other.)
- So . Divide by .
Proof of (b), with intervals.
- Sort the lengths: . Let , so . Kraft gives .
- Every term with is a whole multiple of , because . So is a multiple of , and its binary expansion ends after digits. Let be these digits.
- The binary fractions that start with form the interval . These intervals are laid end to end, so they do not overlap.
- If were a prefix of , the interval of would lie inside the interval of . Disjoint intervals rule this out.
Example. Lengths give . In binary these are , so the code is .
McMillan's theorem. Every uniquely decodable code also satisfies the Kraft inequality. So restricting to prefix codes loses nothing: for every uniquely decodable code there is a prefix code with the same lengths.
Proof of McMillan's theorem
Let for a uniquely decodable code, and let .
- Expand the power: . Each term belongs to one sequence of symbols, and the exponent is the length of its encoded bit string.
- Group the terms by this length , which lies between and . Let be the number of symbol sequences whose encoding has bits. Then .
- Unique decodability means that different symbol sequences give different bit strings. There are only bit strings of length , so .
- Hence for every .
- If , the left side grows exponentially in and the right side only linearly, which is impossible for large . So .
(MacKay, Information Theory, Inference, and Learning Algorithms, §5.2.)
3.2 The entropy bound (source coding theorem) #
Theorem 2 (entropy bound). Every prefix code (indeed every uniquely decodable code) has , with equality if and only if for all . There is a prefix code with . Hence
Why this is true (intuition). Every code "believes in" a distribution: the shares of the budget. Using a code is like using a model. By Gibbs' inequality (lesson 03), coding with any model other than costs extra bits. Integer lengths cost less than 1 extra bit because rounding up adds less than 1.
Proof.
- Let . Then by Kraft (or McMillan). Define . This is a probability distribution: the implicit distribution of the code.
- Write . Then
- by Gibbs' inequality, and because . So .
- Equality needs both terms to be 0: and . That is, for all (dyadic probabilities, powers of ).
- Upper bound. Take the Shannon lengths (round up). From we get , so , and Theorem 1(b) gives a prefix code with these lengths. From we get .
- is at most the length of this code, and at least by step 3.
Blocks of symbols. Code independent symbols at once, as one "super-symbol" from an alphabet with values. By the chain rule and independence (lesson 02), . Theorem 2 for the block gives . Divide by :
The rounding cost of less than 1 bit is now shared by symbols. So entropy is the best possible compression rate, and you can get as close to it as you like. This is Shannon's source coding theorem for lossless codes.
Move the slider to change the coin's probability of heads. The dots are the bits per flip of the best (Huffman) code for blocks of flips. They stay between the entropy (blue line) and the bound (magenta). Notice that the rate does not always go down when grows (for , is a little worse than ); only the bound does. At there is nothing to gain: bit already.
The cost of a wrong code. If the code is complete (), step 2 reads with . Every code is a model, and its excess length is the KL divergence from the true distribution to the code's implicit distribution. Section 3.5 comes back to this.
A source has entropy bits. What do you know about the best average length (bits per symbol) of a prefix code on blocks of 10 symbols?
For one block, , so per symbol . The range is the bound for one symbol at a time. No code goes below , so the last option is impossible.
3.3 The Huffman code #
Shannon lengths prove the bound, but they are not optimal. Huffman's algorithm (1952) finds the best prefix code for a known distribution.
The idea: the two least likely symbols should get the longest codewords, and these codewords should differ only in the last bit. Merging them reduces the problem to symbols.
Press Next merge to run Huffman's algorithm one step at a time. The two yellow nodes are the two smallest weights; they merge into a new node one level up. At the end, read each codeword along the path from the root (left = 0, right = 1). The table compares each length with the surprisal , and the readout compares with the entropy (blue). Edit the probabilities, or try the preset with ties.
Ties. For , the algorithm can break ties in different ways. One choice gives lengths , another gives . Both have bits, and bits. Ties can change the tree, even the set of lengths, but never the expected length.
Theorem 3 (Huffman is optimal). For a known distribution , no prefix code has a smaller expected length than the Huffman code. By McMillan's theorem, no uniquely decodable symbol code has either.
Proof of Theorem 3 (exchange and induction)
Order the symbols so that and are the two smallest probabilities.
- Swap. In an optimal code, implies . If not, swap the two codewords: changes by , which contradicts optimality.
- No lonely nodes. In the tree of an optimal code, every internal node has two children. If a node had only one child, delete that branch's bit from every codeword below it. The code stays prefix-free and gets shorter. So a longest codeword has a sibling, and that sibling is also a codeword of maximal length.
- Siblings. By steps 1–2, some optimal code gives symbols and codewords of maximal length. Exchanging codewords among leaves of maximal length does not change , so we may assume that and are siblings.
- Merge. Merge symbols and into one symbol with probability . This gives a source with symbols. A code for becomes a code for when the merged leaf gets two children. Then , because both symbols pay one extra bit. In the other direction, the optimal code of step 3 merges into a code for with the same relation. Together: .
- Induction on . Huffman's first step is exactly this merge, and the rest of Huffman builds a code for . For , Huffman gives , which is optimal. If Huffman is optimal for symbols, step 4 gives .
Consequences: Huffman codes are complete (Kraft sum 1), and , because .
Weaknesses.
- The extra bit. Lengths are whole numbers, so every symbol costs at least 1 bit. For a coin with , bits, but Huffman needs 1 bit per flip.
- A fixed distribution. If the probabilities depend on the context (the previous characters) or change over time, you need a new code for each context.
- Fix 1: blocks. The overhead drops below bit per symbol, but the alphabet grows like .
- Fix 2: arithmetic coding (next section).
Build a Huffman code for . What is its expected length?
Merge . Now the weights are : merge . Then . The lengths are , so bits. The value 1.846 bits is the entropy : a lower bound that Huffman cannot reach here, because the probabilities are not powers of . 2 bits is the fixed-length code.
3.4 Arithmetic coding #
Arithmetic coding removes the "extra bit per symbol". It codes a whole sequence as one number in .
- Start with the interval .
- For each symbol : split the current interval into pieces, one per possible symbol, with lengths proportional to the model's probabilities . Keep the piece of the symbol that actually comes.
- After symbols, the interval has width , by the chain rule of probability.
- Send the shortest binary fraction whose whole dyadic interval lies inside the final interval. This needs at most bits.
The decoder runs the same model: it splits the same way, sees which piece contains the received number, outputs that symbol, and repeats. It must also know (or the model has an end-of-message symbol).
Small example. Model , ; sequence .
| step | symbol | interval | width |
|---|---|---|---|
| 0 | — | 1 | |
| 1 | 0.8 | ||
| 2 | 0.64 | ||
| 3 | 0.128 | ||
| 4 | 0.1024 |
bits. The 5-bit fraction owns , which lies inside the final interval, so the codeword is : 5 bits, below the bound . For short sequences the "+2" matters; for long ones it does not. For this model needs 6 bits, the uniform model 8 bits, and the model needs 17 bits.
Add symbols with the buttons and watch the interval shrink. Each row zooms into the piece kept in the row above (yellow); the piece sizes are the model's probabilities . The readout gives the final width , the ideal length , and the real codeword. Switch the model: a model that predicts the sequence well keeps wide intervals and needs few bits. "Learns from counts" is an adaptive model that updates its probabilities after every symbol.
Any model works, as long as the decoder can run it too: fixed probabilities, counts that adapt as the data arrive, or a neural network that predicts the next token. Modern entropy coders such as asymmetric numeral systems (ANS) reach the same lengths and run faster.
3.5 Compression = prediction #
Put the pieces together.
- With a model , the ideal code length of is bits. Arithmetic coding reaches it for a whole sequence within 2 bits; Shannon lengths reach it within 1 bit per symbol.
- If the data come from , the expected ideal length is the cross-entropy (lesson 04):
A wrong model costs exactly extra bits per symbol. With Shannon lengths for : .
- Note the direction: the data come from , the code is designed for , and the cost is , not .
Drag the bar tops of the true distribution (blue) and the model (orange). The lower chart shows the average code length when the data come from and the code is built for : the entropy (blue), the extra cost of the wrong model (aqua), and the rounding cost of whole-number Shannon lengths (yellow). Set : the aqua part disappears.
Sequences and language models. A language model predicts each token from the earlier ones. By the chain rule of probability, , so
The code length of a text is the sum of the per-token losses in bits. So the training loss of a language model, converted to bits, is the length of the text after arithmetic coding with that model. Minimizing cross-entropy is learning to compress. In the other direction, a compressor is a model: a complete code with lengths "believes" the distribution .
Minimum description length (MDL). The decoder must know the model. A fair comparison of two models counts the bits for the model and the bits for the data given the model: . A huge model may code the data in few bits but cost many bits itself. MDL picks the model with the smallest total; it is one precise form of Occam's razor.
Data come from , and you compress them with an ideal code for the model . How many extra bits per symbol do you pay, compared with the best code for ?
The average length is , and the best code costs . The expectation is over (the data), and sits inside the log, so the extra cost is . is the total, not the extra cost. can even be negative.
Answers to section 1. (1) 1 bit. Each symbol needs at least one bit, so , is optimal, 0.531 bits above . Coding pairs of flips gives 0.645 bits per flip (section 4), blocks of flips get within of 0.469, and arithmetic coding gets within 2 bits of of the whole sequence. (2) bits per symbol with ideal lengths , plus less than 1 bit if the lengths are rounded up to whole numbers. (3) About 250 KB: 2 bits instead of 8 bits per character is a factor of 4, and bits bytes. The decoder needs the same model, so a fair comparison (MDL, section 3.5) adds the size of the model.
4. Worked example #
(a) A Huffman code by hand. Five symbols with .
| step | merge the two smallest | new node | nodes left |
|---|---|---|---|
| 1 | (0.05) + (0.08) | (0.13) | 0.45, 0.25, 0.17, 0.13 |
| 2 | (0.13) + (0.17) | (0.30) | 0.45, 0.30, 0.25 |
| 3 | (0.25) + (0.30) | (0.55) | 0.45, 0.55 |
| 4 | (0.45) + (0.55) | root (1) | — |
Label the branches: gets 0 and gets 1; inside , gets 0 and gets 1; inside , gets 0 and gets 1; inside , gets 0 and gets 1. The code is
- Expected length: bits.
- Entropy: the surprisals are bits, so bits. Check the theorem: ✓. A fixed-length code would need 3 bits.
- Kraft sum: : the code is complete.
- Decoding : .
(b) Shannon lengths. . The expected length is bits: below , as promised, but 0.5 bits worse than Huffman. The Kraft sum is : 28% of the budget is wasted.
(c) A wrong model. True with bits.
- Use the code for the uniform model (all lengths 2): bits. The KL in bits is , and indeed .
- The other way round: the code on uniform data gives .
Both results are exact, because every length equals of the model probability.
(d) Blocks. The coin with , bits. One flip at a time: 1 bit. Pairs have probabilities . Huffman merges , then , then . The lengths are , so
below the bound . Blocks of 3, 4, 5, 6 flips give bits per flip.
5. In code #
NumPy and SciPy check the hand computations above: the entropy, the expected lengths, the Kraft sums, a brute-force search over all valid length vectors, and the cost of a wrong model.
import itertools
import numpy as np
from scipy.stats import entropy
p = np.array([0.45, 0.25, 0.17, 0.08, 0.05])
huffman = np.array([1, 2, 3, 4, 4]) # lengths of the code built by hand in section 4
shannon = np.ceil(-np.log2(p)) # Shannon lengths
print(shannon) # [2. 2. 3. 4. 5.]
print(round(entropy(p, base=2), 4)) # 1.9606 = H in bits
print(round(p @ huffman, 4), round(p @ shannon, 4)) # 1.98 2.48
print((2.0 ** -huffman).sum(), (2.0 ** -shannon).sum()) # 1.0 0.71875 (Kraft sums)
# Brute force over all length vectors that satisfy Kraft: nothing beats 1.98.
grid = np.array(list(itertools.product(range(1, 6), repeat=5)))
ok = (2.0 ** -grid).sum(axis=1) <= 1
print(round((grid[ok] @ p).min(), 4)) # 1.98
# Wrong model: ideal lengths -log2 q(x) cost H(p) + KL(p || q) bits per symbol.
p4, u4 = np.array([1/2, 1/4, 1/8, 1/8]), np.full(4, 1/4)
print(entropy(p4, base=2) + entropy(p4, u4, base=2)) # 2.0 = 1.75 + 0.25
print(entropy(u4, base=2) + entropy(u4, p4, base=2)) # 2.25 = 2 + 0.25
scipy.stats.entropy(p, base=2) is in bits, and entropy(p, q, base=2) is
. The notebook builds the Huffman code with heapq, encodes and decodes,
and compares model-based code lengths with zlib on real text.
6. Where it shows up #
- File formats. DEFLATE (zip, gzip, PNG) is LZ77 followed by Huffman coding. Baseline JPEG Huffman-codes the quantized DCT coefficients. zstd uses Huffman coding for literals and an ANS coder for the rest.
- Language models as compressors. With arithmetic coding, a model's cross-entropy in bits per token is its compressed size per token. Delétang et al. (ICLR 2024) report that Chinchilla 70B, trained on text, compresses ImageNet patches to 43.4% and LibriSpeech audio to 16.4% of the raw size, better than PNG (58.5%) and FLAC (30.3%), when the model size is not counted.
- Bits per byte (lesson 04) is exactly this compression rate, measured per raw byte so that models with different tokenizers can be compared.
- Tokenizers. Byte-pair encoding (BPE) started as a compression algorithm (Gage, 1994): it replaces frequent pairs of symbols by new symbols. A tokenizer shortens the sequence the model must predict.
- Model compression. Deep Compression (Han, Mao and Dally, ICLR 2016) prunes, quantizes by weight sharing, and Huffman-codes the result: 35× smaller for AlexNet, 49× for VGG-16. After quantization, the entropy of the histogram of the quantized weights is a lower bound on the bits per weight of any code that treats the weights as independent draws from that histogram.
- Learned image compression uses a neural network as the model for arithmetic coding of a quantized latent; this is lossy coding, the topic of lesson 10.
- ML for science. Error-bounded compressors for simulation output (the SZ family) predict each value from its neighbours, quantize the prediction error, and entropy-code the result. A better predictor gives smaller errors with lower entropy: compression = prediction again.
7. Common mistakes #
- "Huffman reaches the entropy." Only for dyadic probabilities (powers of ). Otherwise , and the gap can come close to 1 bit: for , bit but bits.
- "Shannon lengths are optimal." They prove the bound; Huffman can be much better (2.48 vs 1.98 bits above). For the Shannon length of the rare symbol is 14 bits, while 1 bit is enough.
- "Each Huffman codeword is at most long." False symbol by symbol. For , one Huffman code has lengths : the symbol with gets 3 bits, but its Shannon length is 2. Only the average is better.
- "The entropy bound holds for every symbol." It is a bound on the expected length. A single rare symbol can get a codeword much longer than the average.
- Wrong direction of the KL. Data from , code for : the cost is .
- Bits vs nats. Code lengths use ; ML losses use . Divide nats by to get bits.
- Forgetting the model. The decoder needs the code or the model. In MDL its size is part of the total length.
- "A good compressor shrinks every file." There are bit strings of length and only shorter ones, so no lossless code shortens all of them. Random bits cannot be compressed.
8. Check yourself #
- Is there a binary prefix code with lengths ? With ?
Answer
Kraft sums: , so no. , so yes: . - Build a Huffman code for . Give its expected length and the entropy.
Answer
Merge ; then ; then ; then . The lengths are , for example . bits; bits. (MacKay, Example 5.15.) - The data are fair coin flips. An arithmetic coder uses the model ,
. About how many bits per flip does it spend, and why?
Answer
bits . The model error costs 0.208 bits per flip. - Why does an optimal prefix code have Kraft sum exactly 1?
Answer
If the sum is below 1, the code tree is not full: some internal node has only one child. Deleting that branch's bit from every codeword below it keeps the code prefix-free and lowers (all ). So the code was not optimal. - A complete code has lengths . Which distribution does it "believe in"? What is its
expected length on , written as entropy plus KL?
Answer
. bits . - Why can arithmetic coding beat the Huffman code for the coin with ?
Answer
Huffman gives every flip its own codeword, so it needs at least 1 bit per flip. Arithmetic coding codes the whole sequence as one interval of width and needs fewer than bits in total: about bits for flips on average.
What is a prefix-free code?
A code in which no codeword is the beginning (prefix) of another codeword. It can be decoded from left to right, symbol by symbol, without separators.
State the Kraft inequality.
The lengths of a binary prefix code satisfy ; conversely, any lengths that satisfy it have a prefix code.
Why does a codeword of length use of the budget?
All bit strings that start with it form an interval of length in , and the intervals of a prefix code do not overlap.
State the entropy bound for the best expected length of a symbol code.
, with exactly when every is a power of .
What are the Shannon code lengths, and what do they prove?
. They satisfy Kraft and give , which proves the upper bound.
What is the rule of Huffman's algorithm?
Repeatedly merge the two nodes with the smallest weights into one node whose weight is their sum.
Compute the Huffman code lengths for .
, with bits (the entropy is 1.846 bits).
What is the ideal code length of under a model ?
bits. Arithmetic coding reaches it for a whole sequence within 2 bits.
How many extra bits per symbol does a code for cost on data from ?
, because the expected length is .
Why is a language model's loss a compression rate?
By the chain rule, ; arithmetic coding with the model needs this many bits, which is the summed loss in bits.
9. Interview angle #
- "What does entropy mean operationally?" The smallest expected number of bits per symbol for lossless coding, reached in the limit of long blocks.
- "Prove the Kraft inequality." Disjoint sets of descendants in the code tree, or disjoint intervals of length in .
- "Is Huffman optimal? Then why use arithmetic coding?" Huffman is optimal among symbol codes for a fixed, known . But it pays up to 1 bit per symbol and adapts badly. Arithmetic coding gets within 2 bits of of the whole message, with any adaptive model.
- "Why is cross-entropy a compression objective?" The model spends bits on ; the expected excess over the entropy is .
- "Can you compress uniformly random bits?" No. Their entropy is 1 bit per bit, and by counting, no lossless code shortens every string.
- "Your LM has 0.9 bits per byte. What does that mean?" With arithmetic coding, the model would store the text in 0.9 bits per raw byte, about 11% of the original size, not counting the model.
10. Practice #
The notebook for this lesson runs in Colab. It has five exercises, each with a check cell and a folded solution:
huffman_code(probs)withheapq; check that the code is prefix-free and complete.encodeanddecodefor a prefix code, and a round trip on a random message.- Brute force: no length vector that satisfies Kraft beats Huffman on a small example.
block_rate(probs, n): bits per symbol of Huffman codes on blocks, for the coin with and .- Code a text with a unigram model and a bigram (previous-character) model: ideal code lengths
compared with
zlib.
11. Watch and read #
- David MacKay, Information Theory, Inference, and Learning Algorithms (free PDF): §5.1–5.6 (symbol codes, Kraft, implicit probabilities, Huffman and its weaknesses) and §6.2 (arithmetic coding).
- Stanford EE274 (Data Compression) notes: prefix-free codes, Huffman codes and arithmetic coding.
- Delétang et al., Language Modeling Is Compression (ICLR 2024): §2 (arithmetic coding, and why compressing well means modelling well in log-loss) and §3 (experiments).
Runs in your browser with nothing to install. The notebook repeats the key demos and has exercises with checks; solutions are inside, folded.
No Google account needed: Python runs inside your browser. The first start downloads about 40 MB; your changes are saved in this browser only.