Feedback Loops & Bias
Position bias, popularity bias, the closed-loop causal trap, IPS/debiasing
A recommender trains on logs it generated itself. That single sentence is the source of the field's hardest correctness problem: the data is not a neutral sample of user preference — it's a sample of *what the previous model chose to show*, filtered through *where it chose to show it*. Train naively on that data and you don't learn relevance; you learn to imitate your own past behavior.
Position bias: rank determines clicks, so raw clicks aren't relevance. Users click the top slot far more than the bottom slot *regardless of item quality* — attention drops with position. If you train the next ranker on raw click labels, it learns "items that were at position 1 get clicked" and dutifully re-ranks whatever was already on top. The model reproduces position effects, not relevance — a self-reinforcing loop where good-but-low-ranked items can never climb.
Popularity bias: the flywheel amplifies whatever is already popular. Popular items get shown more → get more interactions → look even more relevant to the model → get shown more still. Niche and new items are starved of exposure, so the model has little data on them and under-ranks them, deepening the imbalance. Left uncorrected, the catalog collapses toward a shrinking head, coverage falls, and the long tail dies — even as short-term clicks look healthy.
The closed-loop causal trap and how debiasing breaks it. The core issue is causal: you observe clicks *conditional on* being shown at a position, but you want P(relevant), which requires reasoning about what *would* have happened under a different exposure. Inverse Propensity Scoring (IPS) is the standard tool: weight each observed interaction by 1/P(shown | position) so items shown in low-attention slots count *more* when they still got clicked, recovering an unbiased relevance estimate. Propensities are estimated from a position-bias model or from deliberate randomization (occasionally shuffling positions to gather unbiased data). The naming to know: IPS / doubly-robust estimators / counterfactual learning-to-rank — all attack the same "learn from logs you generated" trap. And randomization/exploration isn't just for cold start; it's how you keep collecting the unbiased signal debiasing needs — and that same controlled randomization budget is what lets you validate that an IPS or doubly-robust correction actually recovered true relevance, rather than just swapping in a differently-biased estimate.
Key points
- Raw clicks are not relevance — position bias contaminates them. Top slots get clicks regardless of quality, so training on raw clicks teaches the model to resurface whatever was already on top, a self-reinforcing loop. The tell: precision@1 higher for items historically shown at *low* positions (they had to be genuinely good to get clicked there).
- Popularity bias is the flywheel turned pathological. Popular items get exposure → interactions → look relevant → more exposure, starving niche/new items of the data needed to rank them. Uncorrected, coverage collapses toward a shrinking head while short-term clicks still look fine.
- IPS breaks the loop by reweighting. Weight each interaction by 1/P(shown | position) so clicks earned in low-attention slots count more, recovering an unbiased relevance estimate. Propensities come from a position-bias model or from deliberate randomization; doubly-robust and counterfactual LTR are the same family.
- Randomization/exploration is the data source debiasing depends on. Occasionally shuffling positions (or exploring) gathers the unbiased observations that let you estimate propensities and train counterfactually — it's not only a cold-start tool, and that same budget is what lets you validate that an IPS or doubly-robust correction actually recovered true relevance rather than swapping in a differently-biased estimate.
A recommender trains on logs it generated, so raw clicks encode position bias (rank drives clicks) and popularity bias (the flywheel amplifies the head) rather than relevance — a closed-loop causal trap where the model imitates its own past. Inverse Propensity Scoring (weight by 1/P(shown|position)), fed by deliberate randomization, recovers an unbiased relevance estimate; doubly-robust and counterfactual LTR are the same idea.
Recap
- A recommender trains on logs it generated: the data reflects what the *previous* model showed and *where*, not neutral preference. Train naively and you learn to imitate your own past, not relevance.
- Position bias: top slots get clicks regardless of quality, so raw-click training resurfaces whatever was already on top — a self-reinforcing loop. Tell: precision@1 higher for items historically shown at *low* positions (they had to be genuinely good to get clicked there).
- Popularity bias: the flywheel turned pathological — popular items get exposure → interactions → look relevant → more exposure, starving niche/new items; coverage collapses toward a shrinking head while short-term clicks still look fine.
- IPS breaks the loop: weight each interaction by 1/P(shown|position) so clicks from low-attention slots count more, recovering an unbiased relevance estimate. Propensities come from a position-bias model or deliberate randomization; doubly-robust and counterfactual LTR are the same family.
- Randomization/exploration is the unbiased data source debiasing depends on — occasionally shuffling positions decouples exposure from the model's own choices so propensities can be estimated and corrections validated. Not just a cold-start tool.
Check your understanding
Q1. Your LTR model shows *higher* precision@1 for items that were historically displayed at low positions than for items displayed at high positions. What does this reveal, and what's the principled fix?
- A) Label noise — low-position items accumulate roughly 5-10x fewer clicks, producing noisier labels; commission editorial relevance judgments for the bottom three ranking positions specifically.
- B) Position bias: items that still got clicked from low positions were genuinely strong. Fix with inverse-propensity weighting (1/P(shown|position)) plus position randomization.
- C) Overfitting to a small set of head queries that dominate the training log; fix with query-frequency-weighted sampling that down-samples the top 100 most frequent queries.
- D) Feature leakage from an explicit popularity feature correlated with position; removing all popularity-derived features from the model resolves the asymmetry.
Q2. Why does inverse propensity scoring weight a click from a low-attention slot *more* than a click from the top slot?
- A) Because low slots produce roughly an order of magnitude fewer total clicks, so each individual click is statistically rarer and IPS treats rarity itself as a proxy for reliability.
- B) P(shown|position) is small for low-attention slots, so a click there is strong evidence of relevance; dividing by that small propensity up-weights it, correcting the exposure imbalance.
- C) IPS is built on the assumption that human attention decays exponentially with rank, so positions below rank 5 are treated as inherently more trustworthy ground-truth sources than rank 1.
- D) It doesn't — after the standard clipping and normalization step, IPS converges to weighting every position equally regardless of its exposure probability.
Q3. A team wants to remove position bias but refuses to ever randomize the ranking ("it would hurt engagement"). Select the *two* correct reasons this is self-defeating for debiasing.
- A) Without any randomization, every log is fully confounded by the current model's own choices, so there's no unbiased observation from which to estimate P(shown|position).
- B) A small, controlled randomization budget is also what lets you validate that an IPS or doubly-robust correction actually recovered true relevance, rather than swapping in a differently-biased estimate.
- C) Randomization is only useful for solving cold start on brand-new items, and has no bearing on estimating or correcting position bias in an already-warm, fully-interacted catalog.
- D) Refusing to randomize causes the ANN index's HNSW graph to drift out of sync with the embedding table roughly every 6 hours, which is the actual root cause of the observed bias.
Try it interactively
ML Systems Lab is a free interview-prep platform for ML engineers — work through the full interactive module, quizzes, and drills.
Open ML Systems Lab →