Part VI — Unsupervised Learning, Clustering, Dimensionality & Time Series · Chapter 8

Recommender systems & matrix factorization

Hook

Three users, three items, and one rating nobody ever entered. Every other model in this course was trained on a complete table of examples — what does gradient descent even optimize when part of the table is simply missing?

Intuition
4.73.62.33.62.81.82.31.81.1
rows = users, cols = items — total error 19.96

Toggle between one latent factor and two. With one, the reconstructed grid never quite matches the real ratings — it's making the same kind of mistake in the same place, no matter how long it trains. With two, it locks onto the real pattern.

Formalize

Give every user ii and every item jj a small vector of latent factors, and predict a rating as their dot product:

r^ij=uivj,L=(i,j)observed(rijr^ij)2\hat{r}_{ij} = u_i \cdot v_j, \qquad \mathcal{L} = \sum_{(i,j)\,\text{observed}} (r_{ij} - \hat{r}_{ij})^2
  • r^ij\hat{r}_{ij} — the predicted rating of item jj by user ii.
  • uiu_i — user ii's latent factor vector.
  • vjv_j — item jj's latent factor vector.
  • rijr_{ij} — the actual observed rating, when one exists.
  • L\mathcal{L} — the total squared-error loss, summed only over ratings that are actually observed.
  1. Train only on ratings that exist

    Gradient descent updates every uiu_i and vjv_j to reduce that squared error — but only summing over ratings that actually exist. The missing entry never appears in the loss at all.

  2. Predicting a missing entry is just the same dot product

    Once training finishes, predicting a rating that was never observed is nothing special — just plugging its user and item vectors into the same uivju_i \cdot v_j used everywhere else.

Play
4.73.62.33.62.81.82.31.81.1
k=1: U3 rated I3 a 5, predicted well under 2
5.04.01.04.03.21.01.01.05.0
k=2: every observed rating reconstructed almost exactly

With one factor, U3U_3's rating of I3I_3 — a genuine 55 — comes out well under 22, and no amount of extra training time fixes it. With two factors, the same entry reconstructs almost exactly. One number wasn't enough to describe two people who like opposite things.

Worked example

Two real taste groups: U1U_1 and U2U_2 like I1I_1/I2I_2 and dislike I3I_3; U3U_3 is the mirror image:

  1. One factor plateaus at a real error, not a training failure

    A single number per user and per item can only express "more of one thing," not two independent directions of taste. Training converges — the loss stops moving — but it converges to a genuinely wrong answer, because a rank-1 model cannot represent this data no matter how long it runs.

  2. Two factors reconstruct every observed rating almost exactly

    With one extra dimension — and a starting point that isn't identical across dimensions, so the second one doesn't just copy the first — the total squared error over all 8 known ratings drops to essentially 00.

  3. The missing rating gets a specific, sensible prediction

    U2U_2's hidden rating of I2I_2 comes out to about 3.213.21 — between U1U_1's 44 and something lower, exactly reflecting that U2U_2 likes I1I_1 slightly less than U1U_1 does.

Checkpoint

Find the number of latent factors that reconstructs every observed rating with total error under 0.01.

4.73.62.33.62.81.82.31.81.1
error 19.959 — predicted missing rating: 2.80
Pick a k to try it
Summary
r^ij=uivj,L=(i,j)observed(rijr^ij)2\hat{r}_{ij} = u_i \cdot v_j, \qquad \mathcal{L} = \sum_{(i,j)\,\text{observed}} (r_{ij} - \hat{r}_{ij})^2

Two things had to be true for this to work at all: enough latent factors to represent the real structure in the data, and a starting point that actually lets each factor learn something different from the others — the same symmetry-breaking problem Part III's weight-initialization chapter ran into, one level removed. Real recommender systems scale this to millions of users and items and dozens of latent factors, but the mechanism — dot products, squared error, gradient descent, summed only over what's actually observed — is exactly this.