Addaly is in open beta. Things will change, and AI answers can be wrong — check anything that matters.

The Maths You Actually Need

Eight ideas that carry almost all the weight in machine learning.

Lesson 44 of 7610 min

Cross-entropy and KL: the cost of believing the wrong distribution

Paying with the wrong code

Entropy is what you pay when your predictions match reality. Cross-entropy is what you pay when they do not. If outcomes really arrive with probabilities p but you built your code, or your model, around probabilities q, the average cost is

H(p, q) = − Σ p_i × log2(q_i)

The probabilities that decide how often you pay are the true ones, p. The probabilities that decide how much you pay each time are yours, q.

Take the reality from the last lesson, p = (0.5, 0.25, 0.125, 0.125), whose entropy is 1.75 bits. Suppose your model believes the four outcomes are equally likely, q = (0.25, 0.25, 0.25, 0.25). Every outcome now costs −log2(0.25) = 2 bits, so H(p, q) = 2 bits. You pay a quarter of a bit more per outcome than a perfect model would.

Now a model that is wrong in a different way, q = (0.7, 0.1, 0.1, 0.1):

0.5   × −log2(0.7) = 0.5   × 0.515 = 0.257
0.25  × −log2(0.1) = 0.25  × 3.322 = 0.830
0.125 × −log2(0.1) = 0.125 × 3.322 = 0.415
0.125 × −log2(0.1) = 0.125 × 3.322 = 0.415
                                     -----
H(p, q) = 1.918 bits

This model is overconfident in the first outcome and pays for it on the second, which it thought was rare and which happens a quarter of the time.

The gap has a name

The extra cost over the entropy is the Kullback-Leibler divergence:

KL(p ‖ q) = H(p, q) − H(p) = Σ p_i × log2(p_i / q_i)

For the uniform model it is 2 − 1.75 = 0.25 bits; for the overconfident one, 1.918 − 1.75 = 0.168 bits. KL is never negative, and it is zero only when q equals p exactly. It measures, in bits per outcome, how wrong a belief is.

Where a cross-entropy of 2.00 bits actually goesCross-entropy, 2.00 bitswhat a model believing q pays per outcomeKL divergence, 0.25 bitsthe removable part: how wrong the belief isEntropy of the data, 1.75 bitsthe floor, which no model can go beneathCross-entropy is entropy plus KL divergence. Training against fixed data can only shrink the secondterm, so a loss that plateaus above zero may be sitting on the floor rather than failing. Compute thefloor from your own label column before judging any curve.
Where a cross-entropy of 2.00 bits actuallygoesCross-entropy, 2.00 bitswhat a model believing q pays per outcomeKL divergence, 0.25 bitsthe removable part: how wrong the belief isEntropy of the data, 1.75 bitsthe floor, which no model can go beneathCross-entropy is entropy plus KL divergence.Training against fixed data can only shrink thesecond term, so a loss that plateaus above zero maybe sitting on the floor rather than failing. Computethe floor from your own label column before judgingany curve.

That identity, H(p, q) = H(p) + KL(p ‖ q), is the most useful line in this module. When you train a model by minimising cross-entropy against data, H(p) is a property of the data and does not move. So minimising cross-entropy is minimising KL, and the loss can never go below the data's own entropy. A language model's loss plateaus above zero not because it has failed but because language is genuinely uncertain: the floor is real. The previous lesson computed that floor for a label column; the same logic applies to every token.

With one-hot labels

In classification the "true" distribution for a single example is a one-hot: probability 1 on the correct class, 0 elsewhere. Every term in the sum vanishes except one, and the cross-entropy collapses to −log q(correct): the surprise of the right answer. That is why the loss you see in a training loop is simply minus the log of the probability the model gave the label. The elaborate definition and the simple one are the same thing.

KL is not symmetric

Swap the roles and you get a different number. With p = (0.5, 0.25, 0.125, 0.125) and q uniform:

KL(p ‖ q) = 0.25 bits
KL(q ‖ p) = 0.25 × (log2(0.25/0.5) + log2(0.25/0.25) + 2 × log2(0.25/0.125))
          = 0.25 × (−1 + 0 + 2) = 0.25 bits

Equal in this case, by coincidence of the round numbers. Change p to (0.7, 0.1, 0.1, 0.1) and KL(p ‖ uniform) = 0.53 while KL(uniform ‖ p) = 0.64. The direction matters, and it matters most when one distribution puts probability near zero where the other does not.

The practical consequence: if q assigns probability 0 to something p can produce, KL(p ‖ q) is infinite, because you would pay −log 0 when it happened. A model trained against exact one-hot targets is therefore pushed to make the correct logit infinitely larger than the rest, and never gets there. Label smoothing, which replaces the target (1, 0, 0, 0) with something like (0.97, 0.01, 0.01, 0.01), exists to give the model a finite place to stop.

The direction also changes behaviour. Minimising KL(p ‖ q) over q makes q cover everywhere p has mass, even if it must spread thin. Minimising KL(q ‖ p) makes q sit on one mode of p and ignore the others. When a preference-trained language model is penalised for drifting from its reference model, the penalty is the second kind, taken over the model's own samples, which is one reason such models become narrower rather than broader.

Two things KL is not

It is not a distance: it is asymmetric and does not satisfy the triangle inequality, so "the KL between two embeddings" is not a meaningful phrase unless both are distributions. And it is not bounded: a single near-impossible event can make it arbitrarily large, so an average KL across a dataset can be dominated by one row.

The trap in the library

torch.nn.functional.kl_div(input, target) expects input to be log probabilities and target to be plain probabilities, and it computes KL(target ‖ exp(input)). Passing probabilities for both runs without error and returns nonsense. scipy.special.rel_entr(p, q) takes plain probabilities for both and returns the elementwise terms; sum them yourself. Compute one small example by hand, as above, and check the library agrees before trusting it on anything larger.

The one thing to keep

Cross-entropy is entropy plus KL divergence, so minimising it against fixed data can only shrink the KL and never go below the data's own entropy, which is why a loss plateau above zero can be the floor rather than a failure.

Before you move on

A classifier's cross-entropy falls to 0.90 nats and stays there, with a flat rather than rising curve, while the labels' own entropy is estimated at 0.85 nats. What is going on?

Pick the one you would defend. Nobody sees your answer.

No ads. No data sale. No public scores on people. Ever.

© 2026 Addaly