search_ads_recsys / 12 · multi-task learning lesson 12 / 39

Multi-task & multi-objective ranking

No feed is graded on clicks alone. This lesson is how one model predicts click, watch-time, like, share and conversion at once — why naïve sharing makes every head worse, and how MMoE, PLE and ESMM each remove one specific failure before collapsing the heads into a single ranking score.

Why one objective is never enough

Open a short-video feed. The product wants the user to click a video, watch most of it, then like / comment / share / follow, and — the metric that actually pays salaries — keep coming back next week. These are different events with wildly different statistics. The base rates alone tell you that you cannot train them the same way.

ObjectiveLabelLossBase rateWhat it proxies
CTR — click-throughbinary (clicked?)cross-entropy~1–10%attention, traffic
Watch-time / completioncontinuous / binaryMSE or CEdense, every impressioncontent–user fit, stickiness
Like / comment / sharebinary, very sparsecross-entropy~0.1–1%deep engagement
Follow / subscribebinary, sparsecross-entropy<0.1%long-term graph value
Conversion (ads / e-com)binary, sparse + delayedcross-entropy~0.1–5%revenue
Swipe-away / reportnegativebinary (skipped / flagged?)cross-entropy~0.5–5% / <0.05%dissatisfaction (subtract)

That last row is the one juniors forget. Production rankers carry negative heads — swipe-away rate (the user flicks past in <1s) and report rate — predicted exactly like the positive heads but subtracted in fusion. Without them the model happily learns that any attention-grabbing thumbnail is good, even one users immediately bounce from or flag. A swipe-away head is a cheap, dense dissatisfaction signal (every impression has a dwell time) that catches the failure long before the sparse report head fires; the report head is the safety floor. We return to where these enter the score in the fusion section.

You could train five separate models, but that throws away the central asset of a recommender: the same user and item features predict all five. The user embedding that helps you guess a click also helps you guess a like. And the sparse targets — share, follow, conversion — have so few positives that a model trained on them alone overfits hard. With a 0.1% follow rate, 100M impressions buys you only ~100k positives across the entire vocabulary of items; a from-scratch follow model never sees enough signal per item to learn. They need to borrow representational strength from the dense tasks. That borrowing is the whole point of multi-task learning (MTL).

Two terms that get conflated — keep them apart
Multi-task learning is an architecture / training question: how should one network produce several predictions? Multi-objective ranking is a decision question: given those predictions, how do we order the list? The first half of this lesson is MTL; the fusion section is the multi-objective decision. You need both, and they fail in different ways.

Crucially, the objectives conflict. Clickbait raises CTR while wrecking completion rate. Optimizing likes pushes toward agreeable, low-diversity content. On a real short-video corpus, comedy clips have high CTR and short watch-time; knowledge clips are the reverse — CTR and completion are outright negatively correlated within some segments. So MTL is not a free lunch. Sharing the wrong thing actively hurts, and that tension drives the entire architecture progression below. This is the same label-definition problem from 05 · Losses, now multiplied across heads.

Shared-bottom — MTL as transfer learning

The first idea is the obvious one. Stack a tower of shared layers — the "bottom" — that reads raw features into a common representation, then hang a small task-specific head on top for each objective. Every task backpropagates into the same bottom.

h = Bottom(x)  (shared)  ·  ŷk = Towerk(h)  ·  L = Σk wk · Lkk, yk)

This is transfer learning happening in both directions at once: the dense CTR task teaches the bottom a good user/item representation, and the sparse like/share tasks ride on it instead of starving. When tasks are positively correlated, shared-bottom is excellent — one forward pass through the expensive bottom, cheap heads, statistically strong. It is also the cheapest thing to serve, which matters under the few-hundred-µs budget from 04 · Ranking models.

Negative transfer — the failure that motivates everything after
Because all tasks are forced through one bottom, conflicting tasks fight over the same weights. The gradient from "watch-time" pulls a parameter one way; "CTR" pulls it the other. The bottom settles for a muddy compromise that serves neither — and adding a weakly-related task can make a strong task worse than its single-task baseline. You can measure this directly: take the two tasks' gradients on the shared bottom and compute cosine similarity. When cos(∇La, ∇Lb) < 0 the tasks are actively undoing each other's updates.

The fix cannot be "share everything" (negative transfer) nor "share nothing" (lose transfer, starve the sparse tasks). It must be conditional, learned sharing — let the network decide, per task, how much of the shared computation to use. That is exactly MMoE.

MMoE — experts plus per-task gates

MMoE (Multi-gate Mixture-of-Experts, Ma et al. 2018) replaces the single shared bottom with a bank of n parallel sub-networks called experts, and gives each task its own gating network that mixes the experts with task-specific weights. The experts are shared; the recipe for combining them is not. For task k the gate is a softmax over experts conditioned on the input:

gk(x) = softmax(Wgk · x)  ∈ Δn
fk(x) = Σi=1..n gki(x) · Ei(x)
ŷk = Towerk(fk(x))

Read it intuitively. There are n experts, each free to specialize — one learns "price sensitivity," another "novelty," another "session intent." Each task's gate is a tiny softmax that emits a probability distribution over those experts, per example. CTR can lean on experts 1 and 3; watch-time on 2 and 4; when their interests overlap they share an expert, when they conflict the gates route around each other. Conflicting tasks are no longer forced through one bottleneck — they take different weighted paths through one expert pool. That is the soft, learned parameter sharing shared-bottom lacked.

Two design notes. First, the gate is conditioned on x, so routing is per-user, per-item: the same model leans on the "explorer" expert for a new user and the "deep-consumer" expert for a power user. Second, MMoE is still cheap to serve — all experts run once (say 8 experts × a 256-wide MLP), and the per-task gates and towers are rounding error. With 4 tasks, you pay 8 expert passes versus 4 full bottoms for 4 separate models. It is a near-drop-in upgrade from shared-bottom.

When MMoE is the right call
MMoE shines when tasks are moderately correlated — enough shared structure to benefit from common experts, enough conflict that a single bottom would muddy. E-commerce CTR + add-to-cart is the classic fit. It is also the cheaper, more easily served choice when deployment resources are tight and the objectives are broadly aligned. Reported deltas (vendor-claimed, treat as direction not gospel): MMoE over shared-bottom lifts AUC +0.5–1.2% on mildly-conflicting tasks (Google), widening to +5–15% when task correlation is genuinely low — precisely the regime where one shared bottom is forced into the muddiest compromise.

The seesaw effect, and PLE's fix

MMoE softens conflict but does not eliminate it, because every expert is still shared by every task. When two objectives genuinely pull apart — short-video watch-time (needs deep interest signal) versus interaction rate (rewarded by shallow, immediate appeal) — you observe the seesaw effect: tuning the model to lift one objective reliably drags the other down. The shared experts cannot simultaneously hold a representation good for both. In practice teams see it as a Pareto frontier you slide along, never a configuration that lifts both at once.

PLE (Progressive Layered Extraction, Tencent 2020) attacks this by making the separation explicit in the architecture rather than hoping the gates discover it. Its core block is CGC (Customized Gate Control): split the expert pool into task-specific experts (private to one task) and shared experts (common to all). A task's gate may select from its own specific experts plus the shared ones — but never from another task's private experts.

gate→A ← {A-specific experts} ∪ {shared experts}
gate→B ← {B-specific experts} ∪ {shared experts}
shared gate ← {all experts}  (feeds deeper layers)

The "progressive layered" part stacks several CGC blocks: each layer refines the separation, the shared experts feed the next layer's gates, and information is gradually decoupled into shared-vs-private channels rather than in one shot. The task-private experts give each conflicting objective a protected place to learn what only it needs — exactly what the seesaw was punishing. The cost is parameters and a harder serving footprint: private-expert pools complicate sharding and dynamic loading, whereas MMoE's uniform expert bank is the friendliest to serve.

The reported payoff is large enough to justify that cost when the seesaw is real (numbers are vendor-claimed, cite as such). On Kuaishou's short-video stack, PLE versus MMoE cut inter-task gradient conflict by 47%, lifted a sparse long-tail head (e.g. favorite) AUC +1.2%, and added +2.3% per-user watch-time — attributed to PLE more faithfully capturing the progressive watch → like → follow funnel. Be honest about the cost direction: PLE adds parameters and FLOPs over MMoE (more experts, one gate per task), so at face value its inference is more expensive, not less. The serving cost is clawed back at inference time by gate-threshold expert-skipping — PLE's gates are peaky, so most experts can be skipped per example (see the serving-knobs section below) — not by the architecture being intrinsically cheaper.

Why PLE in production: the head-content-squeeze story
The seesaw isn't abstract — it shows up as head content squeezing the mid/long-tail out of the ranking. The shared bottom, pulled hard by the high-volume CTR head, learns a representation that favours splashy popular clips; high-completion niche videos (high watch-time, low click) sit below the fold and never accumulate the engagement to climb. The fix is structural, not a weight tweak: give completion its own private expert so its signal can't be overwritten by CTR, and add a long-tail gate that boosts the completion head's contribution for cold-start / low-impression item IDs. One platform's A/B: PLE over MMoE lifted mid/long-tail exposure share +23% and per-user watch-time +7% with CTR roughly flat — a Pareto move, not a trade. This is the concrete answer to "why did you reach for PLE here," distinct from the generic seesaw pitch.
SHARED-BOTTOM MMoE PLE / CGC ────────────── ─────────────── ──────────────────────── TowerA TowerB gateA gateB gateA gateB \ / | \ / | | \ / | shared bottom E1 E2 E3 (shared) A-spec shared B-spec | (per-task softmax (private experts shielded one path → over shared experts) from the rival task) conflict ────────────── ─────────────── ──────────────────────── full sharing soft gated sharing explicit shared + private strongly-aligned moderately correlated conflicting / unknown cheapest low cost highest cost
ArchitectureSharingBest when tasks are…CostReported delta vs prior
Shared-bottomfull (one bottom)strongly alignedcheapest; negative-transfer pronebaseline
MMoEsoft (gated shared experts)moderately correlatedlow; easy to serveAUC +0.5–1.2% (corr. low: +5–15%)
PLE / CGCexplicit shared + private expertsconflicting / unclearmost params + FLOPs; serving cost clawed back via gate-skip (peaky gates)conflict −47%, long-tail AUC +1.2%, watch-time +2.3%

Deltas are vendor-reported (Google for MMoE; Kuaishou short-video for PLE) — read them as the shape of the win, not a guarantee for your corpus.

Rule of thumb for selection
If objectives are clearly positively correlated and you're resource-constrained, MMoE. If the relationship is unknown, dynamic, or you can see a seesaw offline, PLE. A diagnostic worth automating: monitor inter-task gradient cosine similarity during training; persistently negative similarity is the signal to graduate from shared-bottom/MMoE to PLE.

CVR's hidden trap — sample-selection bias

So far tasks differed only in correlation. Conversion rate (CVR) differs in something deeper: where you can observe its label at all. In an ad or e-commerce funnel the events are sequential — impression → click → conversion — and a purchase is only possible after a click. So the natural CVR model is "given a click, will it convert?" and you train it on the clicked samples only.

That is quietly broken, for two compounding reasons:

The seductive wrong fix
"Just train CVR on impressions, labeling un-clicked items as non-conversions." Now you've redefined CVR = P(convert | impression), conflating two different probabilities and drowning the rare true conversions in a sea of forced negatives that were never given the chance to convert. SSB isn't solved by relabeling — it's solved by changing what you model.

ESMM — model on the entire exposure space

ESMM (Entire-Space Multi-task Model, Alibaba 2018) fixes both problems at once with a single identity from the funnel's structure. The thing you actually want for ranking ads is pCTCVR — the probability that an impression is both clicked and converted. By the chain rule of the funnel:

p(click & convert | impression) = p(click | impression) · p(convert | click)
pCTCVR = pCTR × pCVR

ESMM builds three outputs from two towers. A CTR tower and a CVR tower each consume a shared embedding layer — the sparse-feature embeddings are shared, which is where the sparse CVR task borrows strength from the dense CTR task. Then:

L = LCTR(pCTR, click) + LCTCVR(pCTR · pCVR, conversion)

The trick: both losses are computed over the entire impression space, not the click space. CVR is learned only implicitly, squeezed out as the factor that makes pCTR × pCVR match the conversion label. Because pCVR is never trained on the clicked-only subset, the sample-selection bias is gone by construction. And because its embeddings are shared with the high-volume CTR task, the sparsity problem is mitigated too. Two diseases, one cure. Note the failure mode: if pCTR is poorly calibrated (lesson 05), the error propagates multiplicatively into pCVR, so ESMM raises the stakes on CTR calibration.

ESMM — three outputs, two towers, one shared embedding ───────────────────────────────────────────────────────── pCTCVR = pCTR × pCVR ▲ ▲ pCTR pCVR ▲ ▲ CTR tower CVR tower ▲ ▲ shared embedding layer (sparse features) ▲ user / item / context IDs ───────────────────────────────────────────────────────── L_CTR on click label, over ALL impressions L_CTCVR on conversion label, over ALL impressions pCVR has NO direct loss — identified only via the product
Worked numbers — pCVR falls out of the division

Take one impression. The CTR head, trained on every impression, emits pCTR = 0.04 (a 4% click chance — plausible). The CTCVR head, also trained on every impression, emits pCTCVR = 0.002 (a 0.2% chance this impression is both clicked and converted). The conversion rate you actually want is the implied factor:

pCVR = pCTCVR / pCTR = 0.002 / 0.04 = 0.05

So this user, if they click, converts ~5% of the time. Notice you never trained a head on "given a click, did it convert?" — you trained two heads over the full log and divided. Sanity check the funnel: of 1,000,000 impressions at these rates, ~40,000 get clicked (pCTR) and ~2,000 convert (pCTCVR), so conversion-given-click = 2,000 / 40,000 = 5% — the same 0.05, recovered from the marginal counts. Reorder the same numbers and you see the bias that motivated all this: the naïve clicked-only CVR model trains on those 40k clicked rows, but at serving time scores all 1,000,000 — a 25× train/serve population mismatch, and its 2k positives are catastrophically sparse. ESMM never touches that 40k slice for CVR, so neither pathology can occur.

The failure mode a senior flags: multiplicative error
Because pCTCVR = pCTR × pCVR and only pCTCVR is supervised, all calibration error in pCTR leaks multiplicatively into pCVR. Suppose true pCTR is 0.04 but the CTR head is mis-calibrated to 0.05 (a modest +25% over-estimate); to still match the observed pCTCVR = 0.002, the implied pCVR collapses to 0.002 / 0.05 = 0.04 — a −20% error on CVR from a +25% error on CTR. ESMM therefore raises the stakes on CTR calibration (05 · Losses): a head you might have shrugged at as "good enough for ranking" now silently corrupts the revenue estimate downstream.

Weighting and reconciling conflicting losses

Whatever the architecture, you still combine task losses into one scalar to backprop. The baseline weighted sum L = Σk wk Lk has two real problems: tasks live on different scales (a 0–1 cross-entropy vs an MSE on watch-seconds that ranges 0–600), so the large-magnitude loss dominates the gradient; and hand-picking wk is brittle — tiny weight changes swing business metrics. Three families of fix:

MethodMechanismCost / caveatReach for it when…
Static weightshand-set wktrivial; brittle, drifts with data2 aligned tasks, fast baseline
Uncertaintylearn σk noiseassumes Gaussian noise, outlier-sensitivescales differ wildly; new task
GradNormequalize grad magnitudesextra backward pass, finicky to tunetasks learn at very different speeds
PCGradproject away conflicting componentcheap; one-shot, can under-correctintermittent cos < 0
CAGradworst-case-improving directionsmall QP per steppersistent strong conflict
MGDA / Paretocommon descent directioniterative QP, high computeneed provable non-domination

A complementary lens is Pareto optimality: among all weightings, the interesting ones are the non-dominated solutions where you cannot improve one objective without hurting another. MGDA finds a common descent direction for all tasks; Pareto-front analysis lets the business see the trade-off curve and pick a point on it rather than guessing weights. The cost is solving an optimization sub-problem during training.

Score fusion — from many scores to one ordering

The model now emits several calibrated probabilities. The feed shows one list. Somewhere you must collapse the heads into a single ranking score — the multi-objective decision, separate from training.

Weighted sum is the workhorse — normalize first (the heads are already 0–1 probabilities here, which helps), then weight:

score = w1·pCTR + w2·pWatch + w3·pLike + w4·pShare + …

Weighted product is common in industry because it is unit-free and rewards items that are decent across the board rather than spiky on one head:

score = pCTRa · (1 + watch_time)b · pLikec · …

The exponents act as elasticities; a head with exponent 0 is dropped, and the multiplicative form means an item must be non-terrible on every weighted objective to rank high — a useful guard against single-metric gaming like clickbait, where one head spikes and the rest crater.

The weights are not learned offline — they are tuned online
There is no offline label for "the right blend of click and watch-time and retention" — that is the business's value judgment. So fusion weights are set by experiment: ship variant A and variant B, measure guardrail and north-star metrics, keep the winner. The whole point of 08 · Evaluation here is to read the Pareto front empirically and pick the operating point. Real refinements: per-segment weights (new users weighted toward CTR for exploration, deep consumers toward watch-time — e.g. CTR:watch = 7:3 sliding to 5:5 as a user matures), and dynamic re-weighting (a PID controller nudging the watch-time weight up when rolling completion-rate dips below a threshold) — both with safety bounds so no single objective dominates.

A concrete win that interviewers like: one platform found comedy clips had high CTR but short watch-time, knowledge clips the reverse. Re-tuning fusion lifted per-user watch-time +15% while CTR fell only −2% — a clearly good trade. The honest objective, though, is discounted long-term user value, which immediate clicks only proxy; any blend tuned purely to immediate signals can quietly erode 7-day / 30-day retention. That is the bridge to reinforcement learning, where the feed is recast as an MDP and the reward is retention.

The online weight-control loop — the mechanism behind "tune it online"

"Tune the weights with A/B" is the right instinct but a slow loop — days per variant. Mature systems run a continuous control loop that adjusts fusion weights in near-real-time as the feed shifts (a hot event lands, a user's interest drifts, a daypart turns over). Three mechanisms, in increasing autonomy, all sitting downstream of a frozen model — they re-blend the heads, they do not retrain:

None of these ship without guardrails, because a runaway controller can wreck the feed faster than any offline bug:

Three safety rails every online weight loop needs

A concrete trace tying it together: a controller notices a user segment's golden-hour completion rate fell 5%, so it raises the watch-time weight 0.40 → 0.55 (EMA-smoothed over several ticks, never one jump) and trims the like weight by 0.10 to keep the blend normalized — all inside the click-≤-0.60 bound, with the KL fuse armed. No retrain, no deploy: the model is frozen, only the fusion blend moved.

Interactive · seesaw between click-AUC and watch-time

Slide the per-task loss weight for watch-time. The widget shows how the shared bottom reallocates capacity — click-AUC and watch-time move on a seesaw — and what the fused ranking score does at three sample weights. The numbers are a toy model of the trade-off; the diagnosis is the point.

Tune the watch-time loss weight
Two conflicting tasks share one bottom (cos(∇click, ∇watch) ≈ −0.4). Pushing the watch-time weight up steals capacity from click. Watch the seesaw, the gradient-conflict bar, and which architecture the verdict recommends.
click-AUC (toy)
watch-time index
grad conflict
verdict
Reading

Engineering reality — delay, heads, and consistency

Interview prompts you should be ready for

  1. "Why not just train one model per objective?" (Sparse heads — share, follow, conversion — have too few positives to learn alone; they overfit. MTL lets them borrow representation from the dense CTR task. Plus one forward pass serves all heads vs N models.)
  2. "Contrast shared-bottom, MMoE and PLE." (Full sharing → soft gated sharing → explicit shared+private experts. Shared-bottom suffers negative transfer; MMoE softens it with per-task softmax gates over shared experts; PLE adds task-private experts to defeat the seesaw on genuinely conflicting tasks. Increasing robustness, increasing serving cost.)
  3. "Write MMoE's gating math." (gᵏ(x) = softmax(W_gᵏ·x); fᵏ(x) = Σᵢ gᵏᵢ(x)·Eᵢ(x); ŷ_k = Tower_k(fᵏ(x)). Emphasize the gate is conditioned on x, so routing is per-example.)
  4. "What is the seesaw effect and how do you detect it?" (Lifting one objective drags another down because shared experts can't hold a representation good for both. Detect via persistently negative inter-task gradient cosine similarity, or a degrading Pareto front in offline experiments.)
  5. "Why is training CVR on clicked samples broken, and how does ESMM fix it?" (Sample-selection bias: trained on click space, served on impression space → miscalibrated; plus extreme sparsity. ESMM models pCTCVR = pCTR × pCVR over the entire impression space, supervising the product against the conversion label; pCVR has no direct loss. Shared embeddings also fix sparsity.)
  6. "You have five calibrated head scores. How do you produce one ranking, and how do you set the weights?" (Weighted sum or weighted product; product is unit-free and guards against single-metric gaming. Weights are not learnable offline — there's no label for the right blend — so tune them via A/B, optionally per-segment and dynamically with safety bounds.)
  7. "How do you handle the different scales of a CE loss and an MSE-on-seconds loss?" (Normalize targets — quantile or z-score on a sliding window — then either fixed weights or uncertainty weighting L = Σ (1/2σₖ²)Lₖ + log σₖ, or GradNorm / PCGrad at the gradient level.)
  8. "You add a share-rate head and watch-time drops. What now?" (Check gradient-conflict sign; isolate the new task in a private expert/tower (PLE-style) to cap blast radius; give it a small uncertainty-weighted initial weight; run an order-preservation eval on the mature heads' AUC/NDCG before shipping.)
  9. "You want to adjust fusion weights faster than A/B allows. Design the online loop and its safety rails." (Per-user-state schedule (7:3→5:5) / PID controller defending a guardrail like completion-rate / Thompson-sampled weight arms over a Beta posterior — all re-blending a frozen model, no retrain. Rails: EMA smoothing so weights can't jump, hard bounds (click ≤ 0.60) so no objective dominates, and a KL-divergence drift fuse that rolls back to the last stable blend. The fuse is what lets you be aggressive.)
  10. "Your PLE model blows the P99 latency SLA under load. What knobs do you have without retraining?" (Gate-threshold expert skip — drop experts whose gate < 0.1, ~30% FLOPs saved since gates are peaky; mixed precision — FP16 embeddings, INT8 dense; and a degradation fallback to a distilled shared-bottom when P99 > ~80ms, plus Triton concurrent pool pinning the top head to its own stream. Name the trade: skip introduces ragged batches.)
  11. "A like head looks like it lifts watch-time. Do you ship it as a watch-time driver?" (No — suspect a confounder: a hot author inflates both, so the heads correlate without causing each other. Need a causal estimate (DML: residualize the confounder, correlate residuals) before claiming the like head moves watch-time; this is the cross-objective face of debiasing.)
Takeaway
Multi-task learning is conditional parameter sharing under conflict: shared-bottom shares everything (transfer, but negative-transfer prone) → MMoE shares softly via per-task gates → PLE protects conflicting tasks with private experts → ESMM rebuilds the sparse, biased CVR task on the entire exposure space via pCTCVR = pCTR × pCVR. Then fusion turns the heads into one ordering, with the weights chosen online because only the business — read through an A/B test — knows the right trade-off. The interview signal: name what each architecture commits to and which specific failure of its predecessor it removes.