search_ads_recsys / 23 · federated learning lesson 23 / 39

Federated learning for recommendation

Every model in this course assumed a comfortable premise: clicks, watch-times, and queries all land in one warehouse and you train on them. Federated learning challenges that premise directly — it trains a shared model while the raw behavior never leaves the device. A beautiful answer to privacy, a brutal answer to systems design.

The one-line premise
Centralized ML moves the data to the model. Federated learning moves the model to the data. The phrase to keep in your head is "data stays put, the model travels." Everything downstream — the algorithm, the costs, the failure modes — falls out of that single inversion.

Why anyone would accept this much pain

Centralizing raw user behavior is the default because it is easy and it works. Federation gives that up, so it had better be buying something. The trigger is 22 · Privacy turned into a constraint: regulation (GDPR, PIPL) plus eroding user trust make a central honeypot of raw behavior a liability rather than an asset. Federation buys three things back:

The honest framing: federation trades a large, recurring systems tax (communication, heterogeneity, convergence loss) for a reduction in privacy/legal risk. Whether the trade is positive depends entirely on how high the risk side is — which is why federation is real in mobile keyboards and health, and mostly aspirational in mainstream feed ranking.

FedAvg, derived

Start from ordinary SGD. To take one gradient step on the global model w you need the average gradient over all data:

∇L(w) = Σk (nk / n) · ∇Lk(w)

Client k holds nk examples; n = Σ nk is the total. The key observation: this average is separable. Each client computes its own term ∇Lk on its own data, and the server needs only the data-size-weighted average. No raw example ever moves. That single fact is the whole reason federation is possible.

Naively you would have each client send one gradient per step. But a step is tiny and the network round-trip is enormous — you would spend almost all your time talking, not learning. The fix that defines Federated Averaging (FedAvg): let each client run many local SGD steps before it phones home, and average the resulting weights instead of single gradients. One round:

#StepWhoOn the wire
1Select a small fraction C of available clients (e.g. 0.1% of phones idle, charging, on Wi-Fi)server
2Broadcast the current global model wtserver → clientswt (down)
3Local training: each client runs E epochs of SGD on its own data → wtkeach clientnothing leaves
4Upload the update Δk = wtk − wt (a weight delta, not data)clients → serverΔk (up)
5Aggregate: wt+1 = wt + Σk (nk/n) · Δkserver
wt+1 = Σk (nk / n) · wtk   (the data-size-weighted average of locally-trained models)

Repeat for hundreds of rounds. The sanity check: when E = 1 and clients take a single full-batch step, FedAvg reduces exactly to centralized SGD. The interesting regime is E > 1, where it stops being equivalent and the tradeoffs begin.

ONE ROUND OF FedAvg ────────────────────────────────────────────────────────────── ┌────────────────────────────┐ │ COORDINATING SERVER │ │ aggregate Δ → new global w │ └───────┬──────────┬──────────┘ ① broadcast wₜ (down)│ │② upload Δₖ only (up) ┌───────────────┘ └───────────────┐ ▼ ▼ ▲ ┌────────────┐ ┌────────────┐ ┌────────────┐ │ Phone A │ │ Phone B │ · · · │ Phone K │ │ private │ │ private │ │ private │ │ clicks stay│ │ clicks stay│ │ clicks stay│ │ E SGD epochs│ │ E SGD epochs│ │ E SGD epochs│ └────────────┘ └────────────┘ └────────────┘ ────────────────────────────────────────────────────────────── ③ wₜ₊₁ = wₜ + Σ (nₖ/n)·Δₖ → loop for hundreds of rounds

The communication–computation tradeoff

The reason FedAvg exists is that bandwidth, not FLOPs, is the scarce resource. A phone has spare cycles when charging overnight; what it lacks is the willingness (or the data plan) to upload a full model every few milliseconds. So the design knob is E, the local epochs per round:

total uplink ≈ (rounds to converge) × (clients / round) × (model bytes per client)

Crank E up and each client does more useful work between syncs, so you need fewer rounds → fewer uploads → less total communication. The win is large: FedAvg with E in the tens cuts communication rounds 10–100× versus naive per-step gradient sharing. But the win is not free.

More local work is not a free lunch
Every extra local epoch lets each client's model drift further toward its own data before averaging. If clients are similar (IID) they drift the same way and averaging is fine. If they differ (non-IID — the realistic case) they drift apart, and averaging their disagreeing weights blunts or stalls progress. E trades communication down against an accuracy penalty that grows with how heterogeneous your users are. There is no single best E.

Two cheaper tricks ride alongside E to shrink bytes-per-round directly:

The non-IID problem — the quiet model killer

Centralized SGD shuffles all data, so every mini-batch is a roughly unbiased sample of the global distribution. Federation cannot shuffle: each client sees only its owner's data, and no two users are an i.i.d. sample of "everyone." One user watches only cooking videos; another only basketball. Their local gradients point in genuinely different directions. Two flavors:

Averaging skewed local models drifts the result away from the true global optimum (client drift), and convergence slows or plateaus below centralized accuracy. How much? On a well-shuffled (IID) federated setup FedAvg essentially matches centralized training; under realistic non-IID splits the typical penalty is a 3–8% drop in accuracy / AUC, and in pathological cases (e.g. each phone sees only one category) it can stall far worse or fail to converge at all. Recommendation makes it worse because the user–item interaction matrix is extremely sparse: each client touches a sliver of the catalog, amplifying the skew. Standard responses:

TechniqueIdeaWhat it costs
FedProxAdd a proximal term μ‖w − wt‖² to the local loss, leashing each client's update to the global model so it can't drift too far.One hyperparameter μ; slower local progress.
Personalized FL (Per-FedAvg / MAML-style)Don't force one global model — learn a good shared initialization each client fine-tunes locally in a few steps. Accepts that users differ.Each client keeps its own head; more eval complexity.
Layer splitFederate the shared lower layers (embeddings, feature extractors); keep the top ranking layers local and personalized.Architectural commitment; harder to reason about globally.
Dynamic-weighted aggregationWeight a client by more than its data size — down-weight clients whose distribution (by KL divergence to global) is an outlier.Server must estimate distributions without seeing data.

On top of statistical heterogeneity sits system heterogeneity: a flagship phone and a five-year-old budget device differ 10× in compute, so a synchronous round runs at the speed of its slowest participant. Stragglers are handled by over-selecting clients and dropping the laggards, by asynchronous aggregation, or by giving weak devices a smaller distilled model to train.

Horizontal vs vertical — which axis are you partitioning?

Everything above quietly assumed one kind of split: millions of phones, each holding the same feature schema but a different user. That is horizontal federated learning (HFL) — the data is partitioned by sample/user, the feature space is shared. It is the cross-device regime, and FedAvg is its workhorse. The on-device item-table problem below is an HFL setting through and through.

Vertical federated learning (VFL) flips the axis: the same users, but different feature spaces held by different organizations. A video platform knows your watch behavior; a bank knows your spend. Neither has the other's columns. Before you can train you must figure out which rows are the same person without revealing your user lists — encrypted entity alignment via private set intersection (PSI). Then training proceeds over encrypted intermediate representations exchanged between the parties (one side forwards its partial activations, gradients flow back), and only the party holding the labels ever sees the loss signal. This leans hard on the SMPC / homomorphic-encryption machinery from lesson 22 — far heavier crypto than HFL's plain averaging.

The third, sparser case is federated transfer learning: little overlap in either users or features, so you transfer a representation learned by one party to bootstrap another rather than jointly fitting one model. Naming the axis matters in an interview — "federated" alone is ambiguous until you say which dimension is shared.

Federating a multi-task ranker — gradient conflict, amplified

A production ranker is never single-objective — it jointly predicts watch-time, like, comment, share (12 · Multi-task). On a central trainer those heads already fight: the gradient that raises like-rate can lower the gradient for watch-time, because the behaviours trade off (a user who taps "like" and swipes away is the opposite of one who watches to the end). Centralized training averages that conflict over a shuffled, population-representative batch, so the tug-of-war is at least balanced. Federation breaks that balance.

Why non-IID amplifies objective conflict
Each client trains E local epochs on one user's skewed behaviour. A "liker" client sees almost no long watches, so its local multi-task gradient is dominated by the like head and points hard in the like direction; a "binge-watcher" client points hard the opposite way. FedAvg then averages weights that were each pulled toward a different objective by a different user. The result oscillates: the conflict that was averaged-out within a central batch is now spread across clients, where averaging can't see it. Non-IID and multi-objective are not two separate taxes — they multiply.

The fix has two halves — balance the objectives locally before upload, then de-conflict at aggregation.

WhereTechniqueMechanism
On device, before uploadGradNorm / uncertainty weighting (Kendall)Re-scale each objective's loss so no single head's gradient dominates the local update — equalize gradient magnitudes (GradNorm) or weight by learned task uncertainty. Stops the "liker" client from uploading a like-only delta.
On device, before uploadGradient projection (PCGrad-style)If two objective gradients have negative inner product, project the conflicting one onto the normal plane of the main objective (watch-time) so they no longer cancel. Project all heads into a common subspace to kill the oscillation.
Server, at aggregationPer-objective dynamic weights / CAGRWeight each client by its per-objective contribution, not just data size — up-weight clients whose watch-time gradient is healthy; add a conflict-aware regularizer (CAGR) penalizing aggregated directions that worsen any objective.

Worked projection. Take two objective gradients on a client — watch-time (the main objective) and like:

gwatch = (1.0,  0.0),    glike = (−0.8,  0.6)

Their inner product is glike · gwatch = (−0.8)(1.0) + (0.6)(0.0) = −0.8 < 0 — a genuine conflict: stepping along glike partly undoes the watch-time step. Naive summation gives gwatch + glike = (0.2, 0.6), whose watch-time component has collapsed from 1.0 to 0.2 — the like head has eaten 80% of the watch-time progress. PCGrad projection removes the offending component of glike along gwatch:

glikeproj = glike − (glike · ĝwatch) ĝwatch = (−0.8, 0.6) − (−0.8)(1, 0) = (0.0,  0.6)

Now the combined step is gwatch + glikeproj = (1.0, 0.6): watch-time keeps its full magnitude and the like head still contributes its non-conflicting component. The phone uploads a delta that improves the main objective and respects the secondary one, instead of an angry like-only vector that fights every other client at aggregation.

The trade-off, stated plainly
Projection and GradNorm cost almost nothing on-device (a few dot products) but they assume an objective priority — projecting glike onto watch-time silently declares watch-time the boss. Pick the priority wrong and you systematically starve a real objective across the whole fleet. And because the conflict is per-client, the same projection rule is right for a binge-watcher and wrong for a liker — which is exactly why the server-side per-objective weighting in row 3 exists: it lets the priority adapt to who the client is.

The recsys killer — where does the item embedding table live?

This is what makes federated recommendation genuinely different from federated keyboards or vision. As lesson 04 · Ranking models hammered, a recommender's parameters are dominated not by its dense network but by its embedding tables — one learned vector per user and per item. Three hundred million items at 64-dim fp32 is 300 × 10⁶ × 64 × 4 ≈ 77 GB. FedAvg's step 2 says "broadcast the global model to each client." You cannot broadcast a 77 GB item table to a phone, and the phone cannot train it.

The asymmetry that breaks naive FedAvg
The user embedding is private, tiny, and naturally local — a phone needs only its owner's row. The item table is enormous, shared, and global — and a single phone interacts with a microscopic fraction of it. Treating both the same way (download everything, train everything, upload everything) is impossible on-device. The fix is to split them.

The standard architecture is a hybrid central-item / federated-user split — exactly the sharding mindset from 19 · Large-scale optimization, but with the shard boundary drawn along a privacy line instead of just a memory line:

This split is why the clean "data stays put, model travels" slogan gets muddy for recommendation: the model is too big to travel, so you travel only the per-request slice of it, and you accept that the global item knowledge is effectively still centralized.

Secure aggregation and its link to differential privacy

A subtle point: FedAvg already keeps raw data on-device, but the updates can still leak. A single client's Δk, or the set of item gradients it sends, can be inverted to reconstruct training examples (gradient-inversion attacks), and the model can memorize, exposing it to membership-inference. Two complementary defenses:

Spend ε non-uniformly — the budget is not one number
Treating ε as a single global dial wastes it. The DP primitives (Gaussian mechanism, clipping, composition) are derived in 22 · Privacy and 39 · Privacy & compliance — here the engineering decision is allocation: split one budget across signals and users by their sensitivity and statistics.
SecAgg and DP solve different threats — use both
SecAgg hides the individual update from the server but the released model could still memorize. DP bounds what the released model reveals but doesn't hide your raw update from a curious server. Federation, secure aggregation, and differential privacy are three layers of one stack: keep the data home, hide each contribution, and provably limit leakage from the result. The full DP machinery is 22 · Privacy.

Robust aggregation — surviving poisoned clients

Gradient-inversion was a privacy threat: an honest server might learn too much. The mirror-image threat is integrity: a malicious or simply faulty client sends crafted or garbage updates — model poisoning, data poisoning, or a targeted backdoor that misfires only on a chosen trigger. Plain FedAvg is defenceless here. It computes a weighted mean, and a mean has breakdown point zero: a single contributor pushing a large enough Δk can drag the global model anywhere it likes.

The fix is to replace the mean with a statistic that resists outliers — a Byzantine-robust aggregator. Three standard ones:

AggregatorIdea
KrumScore each update by the sum of distances to its nearest neighbours; select the single update most agreed-with, discarding the rest. An outlier is far from everyone and never wins.
Coordinate-wise medianTake the median of each parameter independently. A minority of extreme values can't move a median.
Trimmed meanDrop the top and bottom β-fraction per coordinate, then average the rest — a tunable midpoint between mean and median.

The catch is the same one the non-IID section warned about, now wearing a security hat: a legitimately different client looks exactly like an attacker. A user who only watches cooking videos sends an update that is a genuine outlier, and a robust aggregator will happily trim it away — so you buy robustness at the cost of throwing out real signal from the tail of the heterogeneity distribution. Tune β too aggressively and you re-introduce the convergence penalty you were fighting in the first place.

Robust aggregation and SecAgg pull in opposite directions
Secure aggregation hides every individual Δk and reveals only the sum — but robust aggregators work by inspecting and comparing individual updates to spot the outlier. You cannot filter what you cannot see. Reconciling privacy-preserving aggregation with Byzantine robustness (e.g. via verifiable or secret-shared robust statistics) is an active research tension, not a solved checkbox.

How do you even evaluate a federated model?

Every offline metric you know — AUC, NDCG, mean watch-time — assumes a central test set: pool the labels, score the model, compute the number. Federation forbids exactly that. The labels live on devices and never leave, so there is no place to run roc_auc_score(y, ŷ). This is a genuine, non-obvious failure mode: a team can build a flawless federated training pipeline and then discover it has no honest way to measure what it built. The answer mirrors training — don't move the data, aggregate the statistics.

The recurring trick: every metric you want is a function of some aggregate (a count, a sum, a sorted distribution). Compute the local piece on each device, then combine the pieces through SecAgg so the server sees only the global statistic, never a client's raw scores.

MetricLocal computation (on device)How it aggregates
Seed-aligned samplingServer broadcasts one shared sampling seed; each client hashes its examples and keeps the same deterministic fraction (federated hashing).Guarantees every client evaluates on a comparable slice without revealing which examples it held — the prerequisite for any of the rows below.
AUC (Fed-AUC)Each client computes quantiles of its predicted scores for positives and negatives separately (a small score histogram, not the raw pairs).SecAgg sums the per-client histograms into a global positive/negative score distribution; AUC is then read off the reconstructed curve. No individual score ever surfaces.
Watch-time (Fed-NDCG, mean)Discretize watch-time into bins (short / mid / long) and emit an encrypted count per bin; optionally Box-Cox first to tame extreme values.SecAgg adds the per-bin histograms; the mean and tail come from the summed histogram, not from any user's actual seconds-watched.

Worked Fed-AUC. Say three clients each report, after SecAgg, a 4-bucket score histogram for positives and negatives. The summed global counts are:

positives per bucket = (5, 15, 30, 50),    negatives per bucket = (60, 25, 10, 5)

AUC is the probability a random positive outscores a random negative, estimable from these histograms. Bucket-4 positives (50) beat all negatives in buckets 1–3 (60+25+10 = 95) and tie the 5 in bucket 4; bucket-3 positives (30) beat buckets 1–2 negatives (85); and so on. Summing winning pairs over 100 positives × 100 negatives = 10,000 comparisons gives 50·95 + 30·85 + 15·60 = 8,200 clear wins plus 1,225 same-bucket ties at half credit (612.5), so AUC ≈ (8,200 + 612.5) / 10,000 ≈ 0.88 — computed without the server ever seeing one (score, label) pair. Coarser buckets cost accuracy in the estimate; that granularity is itself a privacy knob.

Two leaks the naive version forgets
Repeated evaluation composes: every metric query spends privacy budget, so a daily Fed-AUC dashboard leaks cumulatively. Add DP noise to each aggregated statistic and track the running cost with Rényi differential privacy (tighter composition than naive ε-addition — see 22 · Privacy), or your "private" eval slowly de-anonymizes the fleet. Second, online A/B testing has its own trap: the experiment bucket is assigned by device-ID hash, but federation aggregates by node, so the two partitions must be reconciled or your treatment and control silently leak into each other.

Federated cold start — bootstrapping a client with no history

The non-IID section gave personalized FL (Per-FedAvg) for users who differ; cold start is the harder cousin — a brand-new user or a newly-joined client (a fresh region/platform) with almost no local data to fine-tune on, where the central tricks from 15 · Cold start and 38 · Cold start (advanced) can't run because the cold user's data won't move. Three named federated mechanisms, each attacking it differently:

MechanismIdeaWhen it fits
FedMeta (Meta-FedAvg, MAML-style)The server learns a meta-initialization — not a finished model but a starting point engineered so that a handful of local SGD steps adapt it fast. A new device downloads it and reaches usable personalization from a few likes/dwells.New users on existing clients; you want one-shot-ish adaptation.
FedProtoEach client keeps local class-/interest-prototype vectors (centroids), not raw data. The server aggregates them into a prototype-similarity matrix that guides transfer — a cold client borrows the prototypes of similar clients to seed its representation.New region/client whose feature space overlaps existing ones; prototypes are cheap and naturally privacy-light.
Federated distillationThe server holds a small clean public set, runs the global model to produce soft labels (or DP-GAN synthetic interactions), and distills that signal into cold clients — injecting global knowledge to counter the extreme non-IID of a data-starved client.Severely sparse clients where even a shared init isn't enough; doubles as a non-IID smoother.

The privacy tie-in: cold start is exactly when you'd relax the budget — F2's adaptive ε says spend more ε early (accept higher privacy cost to get a usable profile fast), then tighten as the user accumulates real local signal.

Interactive · federated round-cost estimator

The thing to feel is how communication cost behaves as you turn the dials. More local epochs cut rounds; compression cuts bytes-per-round; but a bigger model and more clients push everything back up. And the item table, if you ever tried to federate it, dwarfs all of it — which is the whole argument for the hybrid split above.

Where does the byte budget go?
A toy model of total uplink: more local epochs (E) → fewer rounds to converge (down to a client-drift floor); compression cuts the bytes each client sends. The numbers are illustrative, the shape is real.
rounds to converge
bytes / client / round
total uplink
item table / device
Reading

An honest verdict — when does federation actually pay?

Federated learning is real, deployed technology (mobile keyboard prediction is the canonical success). For a recommender, be clinical:

DimensionCentralizedFederated
Raw data locationcentral warehousestays on device / in silo
What's on the wireraw logsmodel updates only (ideally masked + noised)
Privacy / legal riskhigh (a honeypot)low (no central raw store)
Convergence / accuracybest case (IID, shuffled)worse (non-IID drift, DP noise)
Communication costone-time ingestrecurring, every round, every device
Item embedding tabletrivially centralcan't be on-device → hybrid split
Operational complexitymoderatehigh (client selection, stragglers, SecAgg)
The decision rule
Federation pays when the privacy/legal/silo value is high and the part you need to federate is small and naturally per-user — an on-device personalization head, a cross-app interest signal, a regulated domain like health. It does not pay for mainstream feed ranking whose accuracy is paramount, whose item table is unavoidably central, and where you already hold the data lawfully — there the recurring communication tax and the non-IID accuracy hit lose to a well-run central pipeline. The mature production answer is almost always hybrid: keep the giant item model and the heavy ranking central, federate only the sensitive on-device user representation, and glue them with secure aggregation and a tuned privacy budget.

Interview prompts you should be ready for

  1. "Derive FedAvg and say where it's exact versus approximate." (The full-data gradient is a data-size-weighted sum of per-client gradients, so it's separable — clients compute local terms, server averages weights. With E = 1 full-batch it is exactly centralized SGD; with E > 1 local steps drift and the averaged model is only an approximation of the centralized optimum.)
  2. "Why average weights every E epochs instead of gradients every step?" (Bandwidth, not compute, is scarce. Per-step gradient sharing spends all its time on network round-trips. Larger E means more local work per sync, fewer rounds, 10–100× less communication — at the cost of client drift that grows with non-IID-ness.)
  3. "What is the non-IID problem and how do you fight it?" (Clients aren't i.i.d. samples of the population; their local optima diverge, so averaging drifts off the global optimum. Mitigations: FedProx proximal term, personalized FL / per-client heads, layer splits, distribution-aware aggregation weights.)
  4. "You want to federate a recommender. Where does the 77 GB item embedding table go?" (It cannot live on a phone. Hybrid split: user embedding + personal head federated on-device; item table stays central; the phone gets only the few hundred item rows it's scoring, and uploads sparse partial gradients. This is the recsys-specific crux.)
  5. "FedAvg keeps raw data on-device — isn't that already private? What can still leak?" (No. Uploaded deltas are invertible via gradient-inversion; the released model can memorize. SecAgg hides individual updates from the server; DP bounds leakage from the released model. They cover different threats; use both.)
  6. "A client uploads a gradient for item j. What did you just leak, and how do you stop it?" (That the user interacted with item j — sparse item gradients are an interaction-history side channel. SecAgg so the server sees only the summed update, plus DP noise so j's presence isn't individually inferable.)
  7. "When would you NOT use federation for a feed recommender?" (When accuracy is paramount, the item table is unavoidably central, and you already hold the data lawfully. The recurring comms tax plus non-IID/DP accuracy hit lose to a well-run central pipeline. Federate only the small sensitive on-device piece.)
  8. "You federate a multi-task ranker — watch-time, like, comment. What breaks, and how do you fix it on-device versus at the server?" (Objective gradients conflict — like vs watch-time have negative inner product — and non-IID amplifies it because each client over-weights one objective. Fix locally before upload: GradNorm/uncertainty weighting to balance heads, PCGrad-style projection so conflicting gradients stop cancelling. Fix at aggregation: per-objective dynamic weights / CAGR so the priority adapts to each client. Walk the projection: g_like·g_watch < 0 → project g_like onto the normal of g_watch so watch-time keeps its full magnitude.)
  9. "Your federated model trains fine but you can't pool a test set. How do you compute AUC and watch-time?" (Aggregate statistics, not data. Seed-aligned sampling so clients evaluate comparable slices; for AUC, per-client positive/negative score quantile histograms summed via SecAgg into a global curve; for watch-time, encrypted binned histograms. DP-noise each released statistic and track cumulative leakage with Rényi-DP. Watch the A/B trap: device-ID-hash buckets must reconcile with federated-node partitions.)
Takeaway
Federated learning inverts the deal — the model travels to the data instead of the data to the model — and FedAvg makes it work by averaging locally-trained weights instead of shipping raw logs. The three taxes are communication (tuned by E), non-IID client drift, and the recsys killer that a multi-gigabyte item table can't live on a phone, forcing a hybrid central-item / federated-user split wrapped in secure aggregation and a differential-privacy budget. Federation is the privacy-side answer to the same tension every lesson in this track circles: the model you wish you could build versus the constraints — latency, cost, bias, trust — the real world imposes. The remaining lessons turn to the frontier (graphs, multi-agent dynamics, LLMs), causal evaluation, and the data/serving/availability plane beneath all of it.