Part III · Ranking · chapter 13 of 19
Multi-task, debiasing and distillation
Three stories, each repairing its own breakage in the last layer of ranking: there is in fact more than one goal, the data is biased by display position, and the model that is best of all does not fit the budget. What unites them is that all three are about the gap between what a model is trained on and what it is used for.
- A shared trunk is a compromise, and it has a price. If the tasks need representations 90° apart, each gets 0.71 of its signal; at 180° neither gets anything.
- MMoE costs a fraction of a percent of the parameters. The gates are 1.54% of the model; everything else is simply the capacity of the experts.
- A CVR head must not be applied where it was not trained. It trains on 5% of the data and is applied to every impression — 20 times more objects. Hence the whole construction of ESMM.
- A label is binary, a teacher's prediction is not. At ten impressions the noise in the estimate of a click is 138% of the quantity itself: the label says almost nothing about the particular object.
1. Multi-task learning
Ranking almost never optimises a single signal. The classic breakdown, using a video platform as the example:
- Engagement — clicks, watch time;
- Satisfaction — likes, ratings, «do not show me this»;
- Long-term signals — return rate, LTV.
Training a separate model per signal costs several times the resources, and it is harder to improve and to maintain. Hence multi-task architectures.
Shared bottom and its trouble
The simplest construction: shared layers first, then separate heads for each task. The upsides are obvious — regularisation, since the tasks «support» each other, transfer of knowledge, and a saving of resources.
A simple model that shows the essence. Suppose the tasks need representations whose directions differ by an angle \(\alpha\). A shared trunk can only produce one direction, the optimum of the sum lies on the bisector, and each task gets \(\cos(\alpha/2)\) of its signal:
| Angle \(\alpha\) | Share of the signal per task | Loss against a separate model |
|---|---|---|
| 0° | 1.0000 | 0.0% |
| 30° | 0.9659 | 3.4% |
| 60° | 0.8660 | 13.4% |
| 90° | 0.7071 | 29.3% |
| 120° | 0.5000 | 50.0% |
| 180° | 0.0000 | 100.0% |
The numbers are reproduced by the script _tools/mtl_demo.py in this repository.
The model is deliberately simplified, but it explains two observations at once. First: at a small divergence a shared trunk is almost free — at 30° the loss is 3.4%, and multi-task learning looks like a pure win. Second: the degradation is non-linear, and on conflicting tasks both sag at once.
Hence the blunt cure that does actually work: simply increase the capacity of the trunk so that there is room for both directions. Expensive, but honest.
Mixture of Experts and MMoE
The original construction:
$$ y = \sum_{i=1}^{K} g_i(x)\, f_i(x) $$where \(f_i\) are the experts and \(g\) the gate that sets the weights. The key idea is conditional computation: only part of the experts works on each object.
MMoE replaces the shared trunk with a mixture of experts, but the main thing is the first letter of the acronym: multi-gate, every task has its own gate. If the tasks are unrelated, each learns its own subset of experts and the conflict of the previous section simply does not arise.
An input of 1024, a representation of 256, four tasks. Shared bottom is one trunk of 2.62e+05 parameters.
| Experts | Parameters of the experts | Gates | Total | Against shared bottom |
|---|---|---|---|---|
| 2 | 5.24e+05 | 8.19e+03 | 5.32e+05 | ×2.0 |
| 4 | 1.05e+06 | 1.64e+04 | 1.06e+06 | ×4.1 |
| 8 | 2.10e+06 | 3.28e+04 | 2.13e+06 | ×8.1 |
The numbers are reproduced by the script _tools/mtl_demo.py.
Note the proportion: with four experts the gates are 1.54% of the model's parameters. That is, the idea of MMoE itself costs one and a half percent, and what we pay for is the experts, that is, simply capacity.
Hence the right way to frame a comparison: MMoE has to be compared not with a narrow shared bottom but with one widened to the same capacity. If the gain remains, the mechanism of separating tasks is working; if it disappears, what was working was capacity.
An observation from practice confirming that the mechanism works as intended: during training experts really do appear that specialise in particular tasks — that is, the gates diverge rather than converging to uniform weights.
2. ESMM: when a head is applied where it was not trained
A separate and very characteristic story. Suppose we want to rank the output by purchases. There are two obvious attempts and both fail — and the analysis of why is the content of this section.
Take typical figures: 108 impressions, a CTR of 5%, a click-to-purchase conversion of 3%.
- clicks: 5.0e+06, purchases: 1.5e+05;
- \(P(\text{purchase} \mid \text{impression}) = 0.15\%\);
- class imbalance when training directly: 1 to 666.
The numbers are reproduced by the script _tools/mtl_demo.py.
Attempt 1: train \(P(\text{purchase} \mid \text{impression})\) directly. It does not work, for two reasons. Sparsity — there are very few positives, 1 to 666. And the complexity of the signal: we know too little about a purchase to predict it, and everything unknown to us turns into noise.
Attempt 2: model \(P(\text{purchase} \mid \text{click})\). There are relatively more positives — 3% against 0.15% — and training goes noticeably better. But ranking by such a model is not allowed, and here is why.
The CVR head trains on 5.0e+06 clicks — that is 5% of the data, and is applied to all 108 impressions, that is, to 20 times more objects. We rank impressions as though all of them had already been clicked. This is a mismatch between the slice of training and the slice of application — and it is worth being able to name it exactly that way.
| Item | pCTR | pCVR | pCTR · pCVR |
|---|---|---|---|
| A | 0.010 | 0.400 | 0.00400 |
| B | 0.080 | 0.090 | 0.00720 |
| C | 0.040 | 0.150 | 0.00600 |
The order by pCVR: A > C > B. The order by the product: B > C > A — completely reversed.
By pCVR the top goes to A with an expected purchase of 0.00400 instead of B with 0.00720 — a loss of 44% at the top position.
The numbers are reproduced by the script _tools/mtl_demo.py.
Item A is a niche product: it is clicked rarely, but whoever clicks it buys. By the conditional probability it is the champion, by the unconditional one an outsider.
Two heads, CTR and CVR, and their product as the final score. But note: the second head is still applied on a different slice from the one it trains on. The decomposition on its own does not solve the problem.
So the key technique of ESMM is a different one: the second head is trained on a loss over \(P(\text{purchase}\mid\text{impression})\), that is, over the entire space of impressions rather than clicks alone. The gradient reaches the CVR head through the product, and it is trained on the same slice it later works on.
The same technique is used in advertising for modelling conversions: conversions are needed to correct bids in auctions where payment is per conversion rather than per click.
3. Positional debiasing
CTR is higher at the early positions of the output — for two different reasons, and the first thing to do is to tell them apart.
- Users click the early positions more often because they see them sooner and trust them more. That is a bias.
- The high positions really do hold more relevant items. That is not a bias, that is the model doing its job.
Mixing them means either «subtracting» real relevance along with the bias, or subtracting nothing at all.
Suppose the probability of examining a position decays as \(1/\text{pos}^{0.7}\):
| Position | Probability of examination | IPW weight = \(1/e\) |
|---|---|---|
| 1 | 1.0000 | 1.00 |
| 2 | 0.6156 | 1.62 |
| 5 | 0.3241 | 3.09 |
| 10 | 0.1995 | 5.01 |
| 20 | 0.1228 | 8.14 |
Now two items. X has a true relevance of 0.12 but was shown at position 5. Y has a relevance of 0.10 and was shown at position 1.
- Observed CTR: X — 0.0389, Y — 0.1000.
- A naive model confidently puts Y higher, though X is in fact better.
- After dividing by the probability of examination: X — 0.1200, Y — 0.1000. The order is restored.
The numbers are reproduced by the script _tools/mtl_demo.py.
Hence two consequences people ask about. False negatives: some of the unclicked items are in fact good, they were simply never seen. And the feedback loop: what the system likes is at the top, and because of positional bias it gets positive feedback more often and confirms itself.
| Method | How it works | The price |
|---|---|---|
| Train on the first position only | take \(P(\text{click}\mid\text{impression}, pos=1)\) | with a slate of 20 positions, 5% of the data is left |
| Position as a feature | add the position to the model and substitute \(pos = 1\) at inference | simple, but the model can «hide» relevance inside the position feature |
| Inverse propensity weighting | reweight the samples inversely to the probability of examination | you need the true probabilities, and for that random traffic; and a spread of weights of 8.1 times inflates the variance |
| A bias tower | a separate small tower that models the bias | needs careful tuning, but this is the production standard |
The design is simple, and it has three essential details.
- The tower's input is all the context useful for modelling the bias. Not just the position: the device, for instance, strongly affects the positional effect, because fewer positions are visible on a phone than on a desktop.
- During training the outputs are added: \(\text{logit} = f_{\text{main}}(u,c,i) + f_{\text{bias}}(pos, \text{device}, \dots)\). And there must be dropout on the tower's output — otherwise it explains too much by position and pulls the relevance signal onto itself, leaving the main model undertrained.
- At inference the tower is simply thrown away — what remains is a clean relevance score.
The idea is good because the bias is modelled explicitly and separably. We do not try to subtract it after the fact from a finished score; we give the model a separate channel to write it off to — and then cut that channel away.
A head can have an excellent AUC while its values are systematically biased. For ranking within one head that does not matter, but as soon as the scores of different heads are added or multiplied by money, the bias starts working at full strength.
It is convenient to check with the calibration widget in the trainer; the argument is in chapter 10.
4. Knowledge distillation
The motivation is purely engineering: trading quality for latency. A bigger model means higher quality, but a ranker has a hard ceiling of tens of milliseconds for hundreds of candidates. Distillation breaks that link: a large teacher model is trained offline, and a small student learns to reproduce its output and runs in the runtime.
Why a teacher's predictions are more useful than labels
A point that sounds paradoxical in an interview: we do have real labels, so why learn from somebody else's predictions? There are two reasons, and both are worth being able to unfold.
The label says «there was no click». The teacher says «the probability of a click was 0.40» or «0.02» — and these are completely different situations, which the label does not distinguish at all.
Such a signal is called dark knowledge: the teacher passes on not the answer but the shape of the distribution — including information about how hard the task was.
Suppose the true probability of a click is 0.05. How precisely does the label itself estimate it if the object was shown \(n\) times?
| Impressions of the object | Standard error | Relative noise |
|---|---|---|
| 1 | 0.2179 | 435.9% |
| 10 | 0.0689 | 137.8% |
| 100 | 0.0218 | 43.6% |
| 1000 | 0.0069 | 13.8% |
| 10000 | 0.0022 | 4.4% |
The numbers are reproduced by the script _tools/mtl_demo.py.
At ten impressions the noise of the estimate is 138% of the quantity itself. The label says almost nothing about the particular object, only about its class. And we already know that most of the catalogue has exactly that many impressions.
The teacher has averaged that noise over the whole training set and hands the student a smoothed target. And noise is the main source of overfitting on the tail, as in chapter 8.
Why a student has two heads
Under direct distillation the student learns from two targets at once — the real labels and the teacher's predictions — with a weight between them. That is the simplest variant, and in online ranking it brings a specific problem.
The technique: the student is given two heads. One learns from the target labels, the other from the teacher's predictions. The head trained on the target labels is the one used for ranking.
Why so complicated? Because the teacher has biases of its own, and we do not want them affecting the ranking. The teacher was trained on the logs of the same system and inherited its positional bias, its skew towards the popular, its feedback loop — everything the previous section was about. Distilling it directly, we distil that too.
The distillation head works as an auxiliary task in the multi-task sense: it forces the shared representation to absorb the teacher's knowledge without dictating the final order. The knowledge passes through the shared trunk, the biases stay in the other head.
The second motive is calibration. The teacher's predictions break it, while a head trained on real labels preserves it. For advertising, where the score is multiplied by a bid, that is the decisive argument.
- The teacher drifts. It is retrained, and the student's target changes abruptly. A student trained on the old teacher starts contradicting the new one — and monitoring will not show it, because each model on its own looks fine.
- The teacher has to be computed somewhere. It need not run in the runtime, but it must pass over the whole training stream. Distillation is not free — it moves the cost from inference to training.
- The student inherits the teacher's ceiling. If the teacher errs systematically, the student will reproduce the error and never surpass it on that subset — though on the real labels it could have.
- A closed circle of versions. The teacher is trained on logs collected by the previous student. After a few iterations the system distils itself — the same feedback loop, only at the level of models.
Interview questions
Why does a ranking model need several tasks, and what is the trouble with shared bottom?
Because there are always several signals: engagement (clicks, time), satisfaction (likes, ratings), long-term metrics. A separate model per signal costs several times the resources and is harder to maintain.
Shared bottom gives regularisation, transfer of knowledge and a saving. The trouble arises on conflicting tasks: the gradients of the heads pull the shared representation in different directions. In a simple geometric model where the directions of the tasks differ by an angle α, each gets cos(α/2): at 90° that is 0.71, a loss of 29%, and at 180° zero.
The blunt cure is to widen the trunk so that there is room for both directions. The more careful one is MMoE.
What is MMoE and how does it differ from MoE?
MoE: \(y = \sum_i g_i(x) f_i(x)\), where \(f_i\) are experts and \(g\) is a gate; the key idea is conditional computation, with part of the experts working on an object.
MMoE is multi-gate: every task has its own gate, that is, its own expert weights. If the tasks are unrelated, each learns its own subset of experts and no conflict arises.
An important note for an honest comparison: the gates are of the order of one and a half percent of the parameters, everything else is simply the capacity of the experts. So MMoE has to be compared not with a narrow shared bottom but with one widened to the same capacity — otherwise it is unclear what produced the gain.
What is ESMM and what problem does it solve?
The problem is a mismatch between the slice of training and the slice of application. Training P(purchase | impression) directly is blocked by sparsity: at a CTR of 5% and a CVR of 3% the imbalance is 1 to 666, and the signal is too complex besides. Training P(purchase | click) is easier, but such a head is trained on 5% of the data (clicks only) and applied to every impression — 20 times more objects.
Why that breaks ranking: pCVR is a probability conditional on a click. A niche product with a pCTR of 0.01 and a pCVR of 0.40 is the champion by the conditional probability, while by expected purchase it is 0.004 against 0.0072 for a popular one — a loss of 44% at the top position.
ESMM: model the chain impression → click → purchase, P(purchase|impression) = P(click|impression)·P(purchase|click), two heads. And the key technique — the second head is trained on a loss over P(purchase|impression), that is, over the entire space of impressions; the gradient reaches it through the product.
Why is CTR higher at the first positions and what is done about it?
For two different reasons, and they have to be told apart: users click the top more often because they see it sooner and trust it more (that is a bias), and the top really does hold more relevant items (that is the model working). Mixing them means subtracting real relevance along with the bias.
Concretely, the bias reverses the order: an item with a relevance of 0.12 at position 5 gives an observed CTR of 0.039, while an item with a relevance of 0.10 at position 1 gives 0.100. A naive model confidently puts the worse one higher.
Four cures: train on the first position only (with a slate of 20 that leaves 5% of the data), position as a feature with pos=1 substituted at inference (the model can hide relevance in the position feature), IPW (needs random traffic, and a spread of weights of 8 times inflates the variance) and a bias tower — the production standard.
How is a bias tower built?
A separate small tower fed with all the context useful for modelling the bias — not only the position but also, for instance, the device: fewer positions are visible on a phone than on a desktop.
During training the outputs are added in the logit: the main model plus the tower. A mandatory element is dropout on the tower's output, otherwise it explains too much by position, pulls the relevance signal onto itself, and the main model is left undertrained. At inference the tower is thrown away and a clean score remains.
The elegance of the idea is that the bias is modelled explicitly and separably: we do not subtract it after the fact, we give it a separate channel to be written off to, and then cut that channel away.
Why learn from a teacher's predictions if there are real labels?
Two reasons. First: a label is binary, a prediction is not. «There was no click» looks identical for an object with a probability of 0.40 and one with 0.02, while the teacher distinguishes those cases. This is dark knowledge — what is passed on is not the answer but the shape of the distribution.
Second: the teacher is a smoothed version of the data. At a true click probability of 0.05 and ten impressions, the standard error of the estimate is 0.069, that is, 138% of the quantity itself: the label says almost nothing about the particular object. The teacher averaged that noise over the whole set, and the student gets a less noisy target — and noise is the main source of overfitting on the tail.
The motivation for the whole technique is trading quality for latency: the teacher is computed offline, the student fits the ranker's budget.
Why is a student given two heads?
Because the teacher has biases of its own: it was trained on the logs of the same system and inherited its positional bias, its skew towards the popular and its feedback loop. Distilling it directly, we distil that too.
The solution: one head learns from the target labels, the other from the teacher's predictions, and the first is the one used for ranking. The distillation head works as an auxiliary task: it forces the shared representation to absorb the teacher's knowledge without dictating the order. The knowledge passes through the shared trunk, the biases stay in the other head.
The second motive is calibration: the teacher's predictions break it, a head on real labels preserves it. For advertising, where the score is multiplied by a bid, that settles it.
Where does distillation break in production?
Four places. The teacher drifts when retrained, and the student's target changes abruptly — and monitoring will not show it, since each model on its own looks fine. The teacher has to be computed over the whole training stream — distillation moves the cost from inference into training rather than removing it. The student inherits the teacher's systematic errors and will never surpass it on that subset, though on the real labels it could have. And a closed circle of versions: the teacher is trained on the logs of the previous student, and after a few iterations the system distils itself.
One-screen cheat sheet
Shared bottom
Regularisation and a saving, but at a 90° divergence of tasks each gets 0.71 of its signal.
MMoE
Its own gate per task. The gates are 1.54% of the parameters; compare at equal capacity.
The funnel
CTR 5%, CVR 3% → 0.15% purchases, an imbalance of 1 to 666.
ESMM
P(buy|imp)=P(clk|imp)·P(buy|clk), and train the CVR head over the whole space of impressions.
Two reasons
CTR is higher at the top both from bias and from relevance. Mix them and you lose the signal.
The bias tower
Context at the input, a sum of logits, dropout on the output, thrown away at inference.
Dark knowledge
At 10 impressions the noise of the label is 138%. The teacher gives a smoothed target, the label only a class.
Two heads
Rank with the head on labels; the distillation one is auxiliary. The biases stay in the other head.
Primary sources
- J. Ma, Z. Zhao, X. Yi, J. Chen, L. Hong, E. Chi. Modeling Task Relationships in Multi-task Learning with Multi-gate Mixture-of-Experts, KDD 2018 — MMoE.
- Z. Zhao et al. Recommending What Video to Watch Next: A Multitask Ranking System, RecSys 2019 — MMoE and the shallow bias tower in production.
- X. Ma et al. Entire Space Multi-Task Model: An Effective Approach for Estimating Post-Click Conversion Rate, SIGIR 2018 — ESMM.
- T. Joachims, A. Swaminathan, T. Schnabel. Unbiased Learning-to-Rank with Biased Feedback, WSDM 2017 — IPW for positional bias.
- G. Hinton, O. Vinyals, J. Dean. Distilling the Knowledge in a Neural Network, 2015 — dark knowledge.
- «Bridging the Gap: Unpacking the Hidden Challenges in Knowledge Distillation for Online Ranking Systems» — the source of the two-head technique and of the analysis of online failures.
- The numbers in this chapter:
_tools/mtl_demo.pyin this repository.