Chapter 3 · Part 2

Predicting a rating

We can measure who's similar to whom. Now the payoff move: predict how a user would rate a movie they haven't seen. The idea is exactly how you'd ask friends for a recommendation — but you trust the friends with similar taste more, and you politely discount the ones who never agree with you.

A similarity-weighted average

To predict Alice's rating for a movie, we take the ratings other users gave it, and average them weighted by how similar each user is to Alice. We work in centered space (relative ratings) and add Alice's own average back at the end:

In code

recommender.py (continued)
def predict(user, movie):
  raters = np.where(seen[:, movie])[0]        # users who rated this movie
  raters = raters[raters != user]             # excluding ourselves
  if len(raters) == 0:
      return means[user]                      # nobody to learn from

  sims = similarity[user, raters]
  weight = np.sum(np.abs(sims))
  if weight == 0:
      return means[user]

  offset = np.sum(sims * centered[raters, movie]) / weight
  return means[user] + offset

What would Alice think of the movies she missed?

Alice hasn't seen Interstellar (a sci-fi film) or Love Actually (a rom-com). Watch the prediction split them cleanly:

recommender.py (temporary test)
print("Interstellar :", round(predict(0, 2), 2))   # movie index 2
print("Love Actually:", round(predict(0, 4), 2))   # movie index 4
Interstellar : 4.07
Love Actually: 1.55

A predicted 4.07 for Interstellar versus 1.55 for Love Actually. The model has never been told Alice likes sci-fi — it just noticed that the users most like her rated Interstellar highly, and the users least like her are the ones who love rom-coms. One prediction is all it takes; do it for every unseen movie and you have a recommendation. Next chapter.