ml-models / Inference and deployment / Knowledge distillation core

Knowledge distillation

Distillation trains a small student to copy a large teacher's full output distribution instead of only the right answer. This page shows what a temperature does to a softmax, why the soft-target term is multiplied by T², how a student trained on soft targets beats one trained on the same fifteen labels, and how the same idea becomes token-level, sequence-level and on-policy distillation for language models.

On this page
  1. Problem
  2. Intuition
  3. Mechanics
  4. Temperature softmax
  5. The distillation loss
  6. Why multiply by T²
  7. Matching more than outputs
  8. Distilling language models
  9. The pieces in PyTorch
  10. Worked example
  11. Implementation
  12. Tradeoffs
  13. Connections
  14. Read first
  15. Read next
  16. References

Problem

The model that wins on accuracy is rarely the one you can afford to serve. Ensembles, very deep networks and large language models cost memory, latency and money on every request, while the device or the budget only allows something several times smaller. Training the small model from scratch on the original labels usually leaves a gap.

The large model already knows more than the labels say. For a photo of a cat, the label is just "cat", but a good classifier also says it looks a little like a dog and almost nothing like a car. Distillation asks how to move that knowledge into the small model: train it to match the teacher's outputs, not only the one-hot targets. Bucilă, Caruana and Niculescu-Mizil did this in 2006 to compress large ensembles into small neural nets; Hinton, Vinyals and Dean named it distillation in 2015 and built it around a softmax temperature, which this page is mostly about.

Intuition

A one-hot label carries at most log₂ K bits per example and says nothing about which wrong answers are nearly right. The teacher's probabilities say how similar this input is to every class, which is information about the shape of the function the teacher learned. A student that matches those probabilities on an input learns, from that one input, roughly what the teacher would have learned from many nearby labelled examples.

The catch is that a confident teacher hides most of this in tiny numbers: 0.0003 for "car" looks the same as 0 to a cross-entropy loss. Dividing the logits by a temperature T > 1 before the softmax spreads the probability out, so the ratios between the wrong classes, the "dark knowledge", become large enough to matter. The ranking never changes; only how loudly the teacher states it.

The same teacher logits softened by four temperatures Four groups of bars, one per temperature T = 1, 2, 4, 8, each showing the teacher's probabilities for cat, dog, fox, car from logits (6.0, 3.5, 2.5, −2.0). At T = 1 the probabilities are (0.899, 0.074, 0.027, 0.000). At T = 8 they are (0.364, 0.267, 0.235, 0.134). The order of the classes never changes, but the entropy rises from 0.56 to 1.92 bits. 0.90 cat 0.07 dog 0.03 fox 0.00 car T = 1 H = 0.56 bits 0.68 cat 0.19 dog 0.12 fox 0.01 car T = 2 H = 1.28 bits 0.48 cat 0.26 dog 0.20 fox 0.06 car T = 4 H = 1.73 bits 0.36 cat 0.27 dog 0.24 fox 0.13 car T = 8 H = 1.92 bits

The teacher's logits (6.0, 3.5, 2.5, −2.0) for one image of a cat, divided by T before the softmax. Higher T shows how much more "dog" and "fox" the image is than "car".

Mechanics

Temperature softmax

Given logits z, the teacher's softened distribution and the student's (logits v) are

pi(T) = exp(zi/T) / Σj exp(zj/T),   qi(T) = exp(vi/T) / Σj exp(vj/T)

T = 1 is the ordinary softmax; T → ∞ tends to the uniform distribution and T → 0 to the one-hot argmax. Dividing by T does not change which logit is largest, so the teacher's prediction is the same at every temperature.

The distillation loss

The student is trained on a weighted sum of the usual cross-entropy with the label y, at T = 1, and a KL divergence between the softened distributions:

L = α · CE(y, q(1)) + (1 − α) · T² · KL(p(T) ‖ q(T))

The teacher is frozen; only the student's logits v receive gradients. KL(p ‖ q) and the cross-entropy H(p, q) differ by H(p), which does not depend on the student, so either can be used; KL is zero when the student matches, which makes it easier to read. At test time the student uses its ordinary softmax, T = 1.

Teacher, student and the two loss terms One input x goes to a frozen teacher and to the student. The teacher's logits z are divided by T and passed through a softmax to give soft targets p(T). The student's logits v go two ways: divided by T and softmaxed to give q(T), compared with p(T) by a KL divergence scaled by T squared; and softmaxed at T = 1 to give q(1), compared with the label y by cross-entropy. The two terms are mixed with weights 1 − α and α, and only the student is updated by the gradient. x teacher frozen student trained softmax(z / T) p(T) softmax(v / T) q(T) softmax(v) q(1) T² · KL(p ‖ q) soft term CE(y, q) hard term label y L mix α gradient reaches the student only

The teacher can run once ahead of time and its logits be stored; the student needs both terms only during training.

Why multiply by T²

The gradient of the KL term with respect to a student logit is short:

∂ KL(p(T) ‖ q(T)) / ∂vi = (qi(T) − pi(T)) / T

One factor 1/T comes from the chain rule through v/T. The other comes from the softening itself: as T grows both distributions approach uniform, and for logits with mean zero qi − pi ≈ (vi − zi) / (N T) over N classes. Together the gradient falls like 1/T², so without correction raising T would quietly turn the soft term off. Multiplying the loss by T², as Hinton, Vinyals and Dean recommend, keeps the soft and hard terms in roughly the same proportion whatever T is.

The same approximation shows what very high temperatures do: T² times the gradient tends to (vi − zi)/N, the gradient of matching the logits themselves with a squared error. Ba and Caruana trained shallow students exactly that way, regressing the teacher's logits with an L2 loss, so logit matching is the high-temperature limit of distillation.

Matching more than outputs

The teacher's hidden layers are knowledge too. FitNets (Romero et al.) trains a deeper, thinner student using the teacher's intermediate representations as hints: because the student's hidden layer is narrower, a small regressor maps it onto the teacher's, and the two are matched with a squared error. DistilBERT combines three terms during pretraining: masked language modelling, distillation on the output distribution, and a cosine loss aligning the student's and teacher's hidden states. Any such feature loss needs a projection when widths differ, and a choice of which layers to pair.

Distilling language models

A language model's output at each position is already a distribution over the vocabulary, so token-level (word-level) distillation is the loss above summed over positions, with teacher-forced inputs from a fixed dataset. It requires teacher and student to share a tokenizer, otherwise the two distributions are over different sets.

Sequence-level distillation (Kim and Rush) instead runs the teacher's beam search and trains the student with ordinary cross-entropy on the teacher's output sequences, approximating the teacher's distribution over whole sequences by its mode. Fine-tuning a small model on text a larger model generated is this method, and it works across tokenizers.

Both train the student on sequences it did not produce, while at inference it conditions on its own earlier tokens; small errors lead it into prefixes it never saw in training. On-policy distillation samples sequences from the student and has the teacher score every token of them: GKD (Agarwal et al.) frames this as training on self-generated mistakes, and MiniLLM (Gu et al.) minimizes the reverse KL, KL(q ‖ p), with an on-policy optimization.

The direction of the KL matters when the student is too small to match everywhere. Forward KL(p ‖ q), the classical choice, is large wherever the teacher has mass and the student does not, so the student spreads to cover every mode, including putting mass between them. Reverse KL(q ‖ p) is large wherever the student puts mass the teacher does not, so the student is pushed onto the teacher's main modes and may ignore small ones: mode-seeking. MiniLLM uses it to stop the student overestimating regions where the teacher assigns low probability.

The pieces in PyTorch

PyTorch has no distillation module; it is built from log_softmax and KLDivLoss. KLDivLoss takes the student's log-probabilities as input and the teacher's probabilities as target (or log-probabilities with log_target=True). Its default reduction "mean" averages over every element, which is not the KL; kl_div warns about it and recommends "batchmean", which sums and divides by the batch size. CrossEntropyLoss also accepts class probabilities as the target, which gives H(p, q): the same gradient as KL.

ComponentShape/ParamsMeaningSource
F.softmax, F.log_softmax logits (B, K), dim=−1 Turn z/T into p(T) or log q(T); log_softmax is the stable way to get log-probabilities. functional.py 2176-2216, 2293-2324
nn.KLDivLoss input log q (B, K), target p (B, K), reduction="mean", log_target=False Σ p (log p − log q). Use reduction="batchmean" for the true KL per example. loss.py 464-564
F.kl_div same, plus the "mean" warning "batchmean" reduces with "sum", then divides by input.size(0). functional.py 3401-3475, 3456-3475
nn.CrossEntropyLoss input logits (B, K), target class indices (B,) or probabilities (B, K), label_smoothing=0.0 The hard term, and with probability targets the soft term up to the constant H(p). loss.py 1200-1407, 1336-1344
nn.MSELoss input and target of the same shape Logit matching (the T → ∞ limit) and FitNets-style hint losses on hidden features. loss.py 567-630
nn.CosineEmbeddingLoss x1, x2 (B, D), y = ±1, margin=0 A direction-only alignment of student and teacher hidden states, as in DistilBERT's cosine term. loss.py 1671-1740
If the student is trained at T = 4, why does it use T = 1 at test time, and does that change its prediction?

Temperature only rescales logits, so the argmax, and therefore the predicted class, is the same at every T. T = 1 is used because the cross-entropy term trains the student's ordinary softmax to give calibrated probabilities; T = 4 was only a lens for reading the teacher's small probabilities during training.

Worked example

Softening the teacher. Teacher logits (6.0, 3.5, 2.5, −2.0) over (cat, dog, fox, car), true class cat. Entropy in bits.

Tp(cat)p(dog)p(fox)p(car)Entropy
10.89880.07380.02710.00030.561
20.67630.19380.11750.01241.282
40.47910.25640.19970.06481.732
80.36430.26650.23520.13401.919

At T = 1, "car" gets 0.0003: the teacher's view that this cat is 245 times more dog than car is in the data, but a cross-entropy against these targets would barely feel it. At T = 4 the same ratio is spelled out as 0.256 against 0.065.

One loss evaluation. A student with logits v = (2.0, 1.5, 0.0, 0.5), T = 4, α = 0.5. Logs are natural here.

  • q(1) = (0.509, 0.309, 0.069, 0.114), so the hard term is −ln 0.5089 = 0.6755.
  • q(T) = (0.315, 0.278, 0.191, 0.216) against p(T) = (0.479, 0.256, 0.200, 0.065): KL = 0.1113, and T² · KL = 1.7812.
  • L = 0.5 × 0.6755 + 0.5 × 1.7812 = 1.2284.
  • Gradient of the hard term q(1) − y = (−0.491, 0.309, 0.069, 0.114); of the raw KL (q(T) − p(T))/T = (−0.0411, 0.0054, −0.0022, 0.0379); of L, α(q − y) + (1 − α)T(q(T) − p(T)) = (−0.574, 0.197, 0.017, 0.360).

The hard term only pushes "cat" up and every other class down in proportion to the student's own probabilities. The soft term pushes "car" down hardest, 0.0379 versus 0.0054 for "dog", because it is the one class the student rates far above what the teacher does.

The 1/T² decay. Same logits, centred to mean zero, soft term only. The approximation predicts T² · gradient → (v − z)/N = (−0.625, −0.125, −0.250, 1.000).

T‖∂KL/∂v‖T² · ∂KL/∂v
10.47090(−0.390, 0.235, 0.042, 0.113)
20.17762(−0.589, 0.207, 0.046, 0.336)
40.05616(−0.657, 0.086, −0.035, 0.606)
80.01628(−0.659, −0.013, −0.125, 0.798)
160.00440(−0.647, −0.069, −0.184, 0.900)
320.00114(−0.637, −0.097, −0.216, 0.951)

Each doubling of T divides the raw gradient by close to four (3.85 from T = 16 to 32), while the scaled gradient settles towards logit matching.

Training a student. Three classes in 2-D, Gaussian with means (0.0, 1.2), (−1.0, −0.7), (1.0, −0.7) and standard deviations 0.6, 1.4, 1.0, equally likely. The teacher is the exact Bayes posterior, whose logits are quadratic in x because the spreads differ. The student is softmax regression, linear in x, so it cannot copy the teacher exactly. Each student sees only 15 labelled points and the teacher's logits on those same points, starts from zero and runs 400 full-batch gradient steps at learning rate 0.5. Scores are on 3000 fresh points, averaged over seeds 1, 2, 3, 4, 5.

ModelTrain NLLTest NLLTest accuracyAgrees with teacherKL(teacher ‖ model)
teacher (Bayes posterior)–0.51479.4%100.0%0.000
hard labels only 0.1741.40069.4%79.8%0.869
α = 0.0, T = 1 0.4630.62376.4%89.8%0.112
α = 0.5, T = 2 0.3620.66274.5%86.5%0.149
α = 0.0, T = 4 0.5990.68372.6%80.9%0.174

On labels alone the student fits its fifteen points well (train NLL 0.174) and generalizes badly (test NLL 1.400): nothing stops its weights growing until it is overconfident. Pure soft targets at T = 1 give test NLL 0.623 and accuracy 76.4% against 69.4%, from the same inputs, because each point now says how much it belongs to every class. Not every setting helps equally: here T = 4 does worse than T = 1 (KL to the teacher 0.174 against 0.112). High T approaches logit matching, and a linear student matching quadratic logits everywhere spends its capacity on the scores of classes that do not affect predictions. T and α are hyperparameters to tune, not constants. Per seed:

SeedClass countshard test NLLα 0.0, T 1 test NLLα 0.5, T 2 test NLLα 0.0, T 4 test NLL
16 / 5 / 41.3590.6230.6720.667
26 / 6 / 31.2790.6410.6880.717
36 / 5 / 41.7500.6180.6530.669
44 / 6 / 50.8950.6110.6580.723
59 / 1 / 51.7170.6200.6390.639

Implementation

import torch
import torch.nn.functional as F

def distillation_loss(student_logits, teacher_logits, labels, T=4.0, alpha=0.5):
    hard = F.cross_entropy(student_logits, labels)
    soft = F.kl_div(
        F.log_softmax(student_logits / T, dim=-1),
        F.log_softmax(teacher_logits / T, dim=-1),
        reduction="batchmean",          # "mean" would also divide by the class count
        log_target=True,
    )
    return alpha * hard + (1 - alpha) * T * T * soft

teacher.eval()
for x, y in loader:
    with torch.no_grad():               # the teacher is never updated
        teacher_logits = teacher(x)
    loss = distillation_loss(student(x), teacher_logits, y)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

# Token-level distillation for a language model: flatten (batch, seq, vocab)
# to (batch * seq, vocab) and drop padded positions before calling the same loss.

This is the formula the worked example evaluates in plain Python. Passing log-probabilities with log_target=True avoids taking the log of a teacher probability that underflowed to zero. When the teacher is expensive, its logits are often computed once and stored; for large vocabularies only the top few per position are kept, which truncates the soft target and should be renormalized.

Tradeoffs

  • Teacher cost. Every training example needs a teacher forward pass, either online or precomputed and stored. Precomputed logits fix any data augmentation in place; online teachers cost compute at every step.
  • Temperature and α. Low T ignores dark knowledge, high T approaches logit matching and asks the student to reproduce scores that do not affect predictions. The worked example's best setting was the lowest T; on other problems it differs.
  • Fidelity is not accuracy. Stanton et al. find that students often fail to match their teachers' predictive distributions even when they have the capacity to, largely because of optimization, and that closer matching does not always improve the student's generalization.
  • The transfer set. Soft targets can label unlabeled or synthetic inputs, as Bucilă et al. did by generating extra points; the student only learns the teacher's function where the transfer set has inputs.
  • Labels still matter. The hard term corrects the teacher where it is wrong; with α = 0 the student inherits every teacher mistake and bias.
  • Language models. Token-level KD needs a shared tokenizer and full (or top-k) distributions; sequence-level KD needs only generated text but transfers less per example; on-policy methods cost a student sampling step and a teacher scoring pass per update.
  • Alternatives. Quantization and pruning shrink the same model instead of training a new one, and they combine with distillation.
A student is trained only with the soft term at T = 1. Is that the same as training on the teacher's predicted labels?

No. The teacher's argmax gives each example one class, like any other label. The soft term keeps the full distribution. In the worked example the T = 1 soft student reaches test NLL 0.623 from the same fifteen inputs where labels gave 1.400.

Connections

Read first

Read next

No page builds on this one yet.

References

  • Bucilă, Caruana and Niculescu-Mizil. Model Compression. KDD 2006.
  • Ba and Caruana. Do Deep Nets Really Need to be Deep? NIPS 2014. arXiv:1312.6184
  • Hinton, Vinyals and Dean. Distilling the Knowledge in a Neural Network. NIPS 2014 Deep Learning Workshop. arXiv:1503.02531
  • Romero, Ballas, Kahou, Chassang, Gatta and Bengio. FitNets: Hints for Thin Deep Nets. ICLR 2015. arXiv:1412.6550
  • Kim and Rush. Sequence-Level Knowledge Distillation. EMNLP 2016. arXiv:1606.07947
  • Sanh, Debut, Chaumond and Wolf. DistilBERT, a distilled version of BERT: smaller, faster, cheaper and lighter. 2019. arXiv:1910.01108
  • Stanton, Izmailov, Kirichenko, Alemi and Wilson. Does Knowledge Distillation Really Work? NeurIPS 2021. arXiv:2106.05945
  • Gu, Dong, Wei and Huang. MiniLLM: Knowledge Distillation of Large Language Models. 2023 (later versions retitled MiniLLM: On-Policy Distillation of Large Language Models). arXiv:2306.08543
  • Agarwal, Vieillard, Zhou, Stanczyk, Ramos, Geist and Bachem. On-Policy Distillation of Language Models: Learning from Self-Generated Mistakes. ICLR 2024. arXiv:2306.13649
  • PyTorch v2.15.0: torch/nn/modules/loss.py, torch/nn/functional.py.