Open a video app, a music app, or an online shop and a list is already waiting for you, different from the one your friend sees. Someone, or rather something, decided what goes first. At Netflix, the company’s own researchers wrote in 2015 that its recommendations influence the choice of about 80% of the hours members stream; the other 20% come from search (Gomez-Uribe and Hunt, 2015).
The software that builds those lists is a Recommender systemSoftware that predicts how much each person will like, click, or watch each item, then shows each person the items with the highest predictions. Feeds, shops, and streaming apps run on them.Open in glossary. This lesson builds one: people and shows become vectors, a dot product turns them into a predicted score, and gradient descent learns the vectors from ratings. Then it follows what happens when the system starts learning from its own recommendations.
What a recommender predicts
Every recommender does the same two things. It predicts a number for each pair of a person and an item, then shows each person the items with the highest numbers. The interesting question is which number.
- Ratings. When Netflix mailed DVDs, its system predicted how many stars, from 1 to 5, you would give a movie. Stars were then the main sign that a member had actually watched a video.
- Clicks and watching. Most people rarely rate anything. Today’s systems learn mostly from Implicit feedbackSignals of preference that people give without rating anything, such as clicks, plays, purchases, watch time, and skips. Plentiful but indirect; a missing click is not the same as a dislike.Open in glossary: what you click, play, finish, skip, or scroll past. By 2015 Netflix described the days of stars and DVDs as long past; it now drew on what members watch, how they watch, and even which recommendations they were shown but did not play.
- Watch time. YouTube’s engineers described in 2016 how they ranked videos by expected watch time rather than by the chance of a click, because “ranking by click-through rate often promotes deceptive videos that the user does not complete (‘clickbait’) whereas watch time better captures engagement” (Covington, Adams, and Sargin, 2016).
The same paper warns that the number a recommender predicts is a stand-in for what people actually value, and that the choice of stand-in “has an outsized importance on performance” yet is “very difficult to measure with offline experiments”. Whatever the system predicts is what it will get more of. If that is clicks, it gets clicks, whether or not anyone was glad they clicked. That is Goodhart's lawThe observation, usually phrased as "when a measure becomes a target, it ceases to be a good measure": optimizing hard for a proxy breaks its link to the real goal.Taught in Rewarding LLMs, and reward hackingOpen in glossary in a product.
Two ways to guess what you will like
Describe the items. Content-based filteringRecommending from descriptions of the items, such as genre, cast, or tempo, by matching them to the features of things a person liked. It works for new items but needs every item described.Open in glossary describes each item by its features (a film’s genre, cast, and length; a song’s tempo and instruments) and recommends items whose features match the ones you liked. Pandora’s Music Genome Project, for example, had trained analysts score each song on hundreds of musical characteristics. It works for an item nobody has tried yet, but someone has to describe every item, and it tends to recommend more of the same kind.
Learn from people. Collaborative filteringRecommending from behavior alone. It ignores what the items are and uses only who liked what, on the bet that people who agreed in the past will agree again.Open in glossary ignores what the items are. It uses only who liked what: people who agreed with you in the past will probably agree with you again. Koren, Bell, and Volinsky (2009) credit the name to the developers of Tapestry, an experimental system at Xerox PARC that filtered email and news using its users’ annotations (Goldberg and colleagues, 1992). It needs no descriptions and can find connections nobody would have labeled, but it knows nothing about an item until people have rated it.
People and shows as vectors
The most successful version of collaborative filtering gives every person and every item a short list of numbers, an EmbeddingA list of numbers (a vector) that represents a token, word, sentence, or image, learned so that similar things end up with similar vectors.Taught in Word embeddingsOpen in glossary. Think of each number as a hidden trait: one might end up tracking how light or dark a show is, another how realistic. A person’s numbers say how much they like each trait. A show scores well for you when its traits line up with your tastes, and the measure of lining up is the Dot productThe sum of the products of matching entries of two vectors. It equals the product of their lengths times the cosine of the angle between them.Taught in Vectors and similarityOpen in glossary from the vectors lesson.
The full prediction of person ‘s rating of item adds three plain averages to that match:
Here is the average of all ratings, is how much better or worse than average item does with everyone, is how generous person is, and is the taste match between person ‘s vector and item ‘s. Koren, Bell, and Volinsky give an example of the offsets alone: if the average rating is 3.7 stars, Titanic tends to get 0.5 more, and Joe tends to give 0.3 less, the first guess for Joe’s rating of Titanic is 3.7 + 0.5 - 0.3 = 3.9 stars. The taste match then moves that guess up or down for Joe in particular.
Notice that the match is the raw dot product, not the cosine similarity: a longer vector means a stronger taste, and it moves predictions further from average.
Why the name Matrix factorizationLearning a vector for every user and every item so that their dot product, plus offsets, predicts the known ratings. It fills in the empty cells of the user-by-item ratings table.Open in glossary? Write all the ratings in one table, a row per person and a column per item. Most cells are empty, because each person has rated a tiny fraction of the catalog. The model claims that the full table is (apart from the offsets) the product of a tall matrix with one row per person and a wide matrix with one column per item. Learning those two factors fills in every empty cell at once.
Ratings: people by shows
People
Shows
? = average + person's offset + show's offset + (highlighted row · highlighted column)
Learning the vectors
Nobody chooses the numbers. Training starts them small and random and adjusts them until the predictions match the known ratings. The loss is the squared error on every rating we know, plus a penalty on large numbers:
The penalty is the RegularizationAny technique that discourages a model from fitting noise, for example adding a penalty on large parameter values to the loss.Taught in Overfitting and generalizationOpen in glossary from the overfitting lesson, and its strength is a setting you choose. The model learns by Gradient descentAn optimization method that repeatedly moves the parameters a small step in the direction that lowers the loss fastest, the opposite of the gradient.Taught in Gradient descentOpen in glossary: every step nudges every vector a little downhill on .
Below, 40 simulated viewers have each rated 4 to 7 of 12 shows, and you are the 41st. The map shows each show’s learned vector (both numbers, nothing projected) and your vector as an arrow.
Train a recommender
Rate a few shows. The model learns a vector for every show and for you from everyone's ratings, then ranks the shows you have not rated.
- Stand-up special
- Baking contest
- Office sitcom
- Nature documentary
- True crime series
- War documentary
- Courtroom drama
- Heist thriller
- Monster horror
- Space war epic
- Animated musical
- Fairy-tale adventure
Challenges
0 of 2 complete
- With a single rating, make your top pick a show from the bottom half of the list a brand-new viewer gets. (not yet)
- Set the penalty to 0, rate exactly two shows, and make the model predict more than 7 stars (or less than -1) for a show you have not rated. (not yet)
Try this
- Before you rate anything, read the list. Your arrow has length zero, so your predictions are the average plus each show’s offset: the same list every brand-new viewer gets.
- Rate one show you would like 5 stars. Predict which shows will rise before you look. Your arrow appears, pointing roughly toward that show.
- Rate one more show and read the report under the map. Which prediction moved most, and why that one?
- Press Train again from a new random start. The map comes out turned or flipped, but your predictions do not change.
- Set the penalty to 0, then to 10, and watch the error on held-out ratings each time.
The model was never told what any show is about, yet shows that the same people like ended up near each other: the documentaries together, the dark fiction together, the light shows on the other side. In this simulation we know the truth, because we generated it: every show has two hidden traits, how light it is and how real it is, and every viewer has a taste for each. After the best turn, flip, and stretch, the learned positions explain about 96% of the variation in those hidden traits.
The two axes, labeled factor 1 and factor 2, have no names. Rotate every person’s and every show’s vector by the same angle and every dot product stays the same, so training settles on whichever orientation its random start leads to. Real systems use many more factors; Koren, Bell, and Volinsky describe 20 to 100, and the lesson on high dimensions shows what is lost when you flatten them for a picture.
The penalty decides how far the model trusts thin evidence. With no penalty, its error on the ratings it learned from falls to 0.30 stars, but on 80 held-out ratings it is 1.10 stars: it has fit the noise in viewers who rated only a few shows. With the errors are 0.36 and 0.65 stars. With every vector collapses to the center and only the average and the offsets are left, which UnderfittingWhen a model is too simple to capture the real pattern, so it does poorly on both the training data and new data.Taught in Overfitting and generalizationOpen in glossary. The same thing happens to you: with no penalty, two ratings of yours can stretch your arrow until some predictions run far off the 1 to 5 scale.
Matrix factorization by gradient descent in NumPyPython with NumPy
import numpy as np
shows = ["Sitcom", "Stand-up", "Baking", "Horror", "Space epic"]
# Five viewers (rows) rate the shows (columns), 1 to 5 stars; 0 = not rated.
# Viewer 4 is brand new and has rated nothing.
R = np.array([[5, 4, 0, 1, 0],
[4, 0, 5, 1, 1],
[1, 1, 0, 5, 4],
[0, 2, 1, 4, 0],
[0, 0, 0, 0, 0]], dtype=float)
known = R > 0
mu = R[known].mean() # the average rating
rng = np.random.default_rng(0)
k, lam, lr = 2, 0.5, 0.02 # factors, penalty, step size
P = rng.normal(0, 0.1, (5, k)) # one taste vector per viewer
Q = rng.normal(0, 0.1, (5, k)) # one vector per show
bu, bi = np.zeros(5), np.zeros(5) # viewer and show offsets
for step in range(3000):
pred = mu + bu[:, None] + bi[None, :] + P @ Q.T
err = np.where(known, R - pred, 0.0) # only known ratings count
# One gradient step on squared error + lam * (every parameter squared).
P, Q = (P - lr * (-2 * err @ Q + 2 * lam * P),
Q - lr * (-2 * err.T @ P + 2 * lam * Q))
bu -= lr * (-2 * err.sum(axis=1) + 2 * lam * bu)
bi -= lr * (-2 * err.sum(axis=0) + 2 * lam * bi)
pred = mu + bu[:, None] + bi[None, :] + P @ Q.T
rmse = np.sqrt(np.mean((R - pred)[known] ** 2))
print(f"error on known ratings: {rmse:.2f} stars")
for v, j in [(0, 2), (0, 4), (3, 0), (3, 4)]:
print(f"viewer {v}, {shows[j]}: predicted {pred[v, j]:.1f}")
print("new viewer's taste vector is zero:", bool(np.allclose(P[4], 0)))
print("so they get the crowd's order:", [shows[j] for j in np.argsort(-pred[4])])error on known ratings: 0.20 stars
viewer 0, Baking: predicted 4.8
viewer 0, Space epic: predicted 1.6
viewer 3, Sitcom: predicted 1.9
viewer 3, Space epic: predicted 3.3
new viewer's taste vector is zero: True
so they get the crowd's order: ['Sitcom', 'Horror', 'Baking', 'Stand-up', 'Space epic']The cold-start problem
A recommender that learns from people is stuck when it has no people to learn from. This is the Cold-start problemA recommender that learns from behavior knows nothing about a new user or a new item until they have some ratings or clicks, so it cannot personalize for the one or recommend the other on its merits.Open in glossary, and it comes in two forms.
A new person. With no ratings, your vector has nothing to fit, so the penalty keeps it at zero and you get the same list as everyone else, ordered by the shows’ offsets. You saw this before your first rating. One fix is to ask: in 2015 Netflix described a survey during sign-up in which new members pick videos from a set the algorithms chose, and those picks feed every algorithm from the start.
A new item. A show nobody has rated has a zero vector and a zero offset, so the model predicts each viewer’s own average for it. It cannot rise above the shows the model already likes, so it is not shown, so it is never rated. Koren, Bell, and Volinsky note that content-based filtering is better here, because a description exists on day one. Systems often combine the two: describe a new item by its content until ratings arrive. The other fix is to show it to some people on purpose.
Explore or exploit
A feed is not a one-time prediction. It decides what to show, and then learns from what people do with what it showed. Showing the best guess is exploiting; showing something uncertain to find out is exploring. This is the same Explore or exploit tradeoffThe choice between taking the action that looks best so far (exploit) and trying something less known that might be better (explore). Too little exploring locks in mistakes; too much wastes reward.Taught in Explore or exploit: banditsOpen in glossary as in the bandits lesson, with a person in place of each pull of a slot machine.
Below, the model from the first demo starts from the 40 viewers’ ratings. A 13th show, a new release, has none. Each day, 200 new viewers are each shown one show they have not seen, either the model’s best guess or, with some chance, a random show, and they rate it. Every night the model retrains on everything it has.
A feed that learns from itself
Each day, 200 new viewers are each shown one show they have not seen, and rate it. Every night the model retrains on all the ratings it has.
Challenges
0 of 2 complete
- Get the new release recommended by the model's own choice, not a random pick, to at least 20 viewers over the three days. (not yet)
- Explore so much that viewers rate what they are shown lower, on average, than with exploring off. (not yet)
Try this
- With exploring off, look at the new release. Then press New luck a few times. Does it ever get shown?
- Choose Day 1. Every viewer is new, so what does everyone get?
- Set exploring to 10% and look at how many times the model itself, not a random pick, chose the new release.
- Try All random. What happens to the average stars viewers gave?
With exploring off, the new release was never shown in any of the eight runs we checked, so it never collected a rating. On day 1 every new viewer got the same show, Office sitcom, the crowd’s favorite, and over three days the three most-shown shows took 78% of all recommendations while 6 of the 13 shows were never recommended at all. With 10% of picks random, the new release was shown 31 times, and 27 of those were the model’s own choice: a handful of random showings gave it ratings, the ratings placed its vector near the made-up shows its fans like, and from then on the model recommended it to them. All 13 shows got recommended, and viewers gave 3.79 stars on average against 3.78 with exploring off. With every pick random, the average fell to 3.53.
This catalog is tiny, which makes the new release’s chances better than they would be in a real one. With thousands of titles, every viewer has many shows predicted above average, and an unrated show at average has even less chance to surface without exploring.
Real systems treat this as a bandit problem. Li, Chu, Langford, and Schapire (2010) built a contextual bandit to choose news stories for the Yahoo! front page. Evaluated offline by replaying more than 33 million logged visits that had been shown random stories, it earned 12.5% more clicks than a standard bandit that ignored who the visitor was. YouTube’s 2016 paper describes a simpler guard: it trained on every video people watched, not only those it had recommended, because otherwise “it would be very difficult for new content to surface and the recommender would be overly biased towards exploitation.”
Feedback loops and popularity bias
The feed above is a Feedback loopA cycle in which a system's outputs shape the data it later learns from. A feed that learns from what people do with what it showed them learns little about what it never shows.Open in glossary. What it shows depends on what it believes, and what it learns depends on what it showed. Shows that start out popular are shown more, collect more ratings, and become the shows the model is surest about. That tilt toward already-popular items is called Popularity biasThe tendency of a recommender to show already-popular items more, because they have the most data and the surest scores, which makes them more popular still.Open in glossary.
The model's guesses
A predicted score for every person and every show
What the feed shows
Each person's top guesses, plus a few random picks if it explores
What people do
Watch, rate, or skip, but only the shows they were shown
New training data
Ratings of shown shows; nothing about the rest
Retrained every night
- Never shown, never rated. A show the model does not pick collects no ratings, so the model never finds out it is good.
- Popular gets surer. Shows that start out popular are shown more, collect more ratings, and become the ones the model is surest about.
How much does this matter in the real world? The evidence comes in different strengths, and it is worth keeping them apart.
- Simulations show the mechanism. Chaney, Stewart, and Engelhardt (2018) simulated recommenders retrained on data from users who had already seen recommendations and found it “homogenizes user behavior without increasing utility.” A simulation shows what can happen under its assumptions, not what does happen on a given platform.
- A controlled experiment on popularity. Salganik, Dodds, and Watts (2006) had 14,341 people download songs by unknown bands. When people could see how often earlier participants had downloaded each song, success became both more unequal and less predictable. There was no recommender, only a popularity count, but it is the same loop.
- Experiments on real platforms show that ranking changes what people see. Twitter kept a randomized group of nearly 2 million accounts on a reverse-chronological timeline; comparing it with the ranked timeline, Huszár and colleagues (2022) found that in six of seven countries the algorithm amplified tweets by elected legislators of the mainstream political right more than those of the left.
- Effects on attitudes are much less clear. During the 2020 US election, consenting Facebook and Instagram users moved to a chronological feed spent less time on the platforms and saw different content, but over three months their polarization, political knowledge, and other key attitudes did not change significantly (Guess and colleagues, 2023). On YouTube, bots that started from real users’ histories and then followed only the recommendations ended up with less partisan viewing, on average, than bots that replayed those users’ own choices (Hosseinmardi and colleagues, 2024, describing the system after its 2019 changes).
The phrase Filter bubbleThe idea, popularized by Eli Pariser in 2011, that personalization shows people mainly what fits their past behavior and so isolates them from other views. How strong this effect is on real platforms is still debated.Open in glossary, popularized by Eli Pariser in 2011, names the strong version of the worry: that personalization seals people off from other views and changes what they believe. The best real-world studies so far support the weaker claim, that feeds shape what people see and which items win attention, much more firmly than the strong one. They are also snapshots of particular platforms, periods, and measures, and the systems keep changing.
Real systems, as they were described
The Netflix Prize. On October 2, 2006, Netflix released over 100 million ratings from over 480,000 anonymous subscribers on nearly 18,000 movies and offered $1 million to the first team that predicted held-back ratings 10% more accurately, by root mean squared error, than its own system, Cinematch. A team called BellKor’s Pragmatic Chaos submitted the winning entry on July 26, 2009, 10.06% better on the test set; a rival team, The Ensemble, matched the score to four decimal places but submitted 20 minutes later and lost on the rules. The winners blended many models; Koren, Bell, and Volinsky, three of them, wrote in 2009 that their leading entries combined more than 100 predictors, most of them variants of matrix factorization, and their article on the method is the source of this lesson’s formula. The data had a cost too: Narayanan and Shmatikov showed that a few known ratings could identify a subscriber’s record, and Netflix canceled a planned second contest.
YouTube, 2016. Covington, Adams, and Sargin described two stages. A candidate generator learns an embedding for each video and computes one for each user from their history; serving becomes a nearest-neighbor search in dot-product space that narrows millions of videos to hundreds. A ranking network then scores those hundreds, mainly by expected watch time. The models had about a billion parameters trained on hundreds of billions of examples. That is a description from 2016; companies change these systems constantly and publish only parts of them.
Word vectors are a factorization tooOptional
GloVe, the word embedding from the word embeddings lesson, has the same shape as a recommender. Pennington, Socher, and Manning (2014) fit word vectors and context vectors with two offsets by weighted least squares:
where counts how often word appears near word and gives rare pairs less weight. Swap “log count of word j near word i” for “rating of item i by person u” and it is the recommender’s loss. In both cases a dot product of two learned vectors, plus offsets, is fit to a table of observations.
Two more details. Koren, Bell, and Volinsky fit the model with stochastic gradient descent, one rating at a time, or with alternating least squares, which fixes the item vectors and solves for each person’s vector exactly, then swaps; the feed simulation above retrains with alternating least squares because it needs no step size. And they apply the penalty once per rating, so it grows with how many ratings a person or item has; applied once per parameter, as in the formula above and in the lab, it weighs most, relative to the data, on people and items with few ratings.
Key ideas
- A recommender predicts a number for each person and item, then shows the top items. Whether that number is stars, clicks, or watch time decides what the system gets more of.
- Content-based filtering describes items; collaborative filtering learns only from who liked what.
- Matrix factorization gives every person and item a learned vector; the prediction is an average, two offsets, and a dot product, fit by gradient descent with a penalty against overfitting.
- With no ratings, a person or item has a zero vector: the cold-start problem. Asking new users, describing new items, and exploring are the fixes.
- A feed learns only from what it shows, which favors what is already popular. That feeds shape what people see is well established; that they trap people and change beliefs is not.