Chapter 4 · Part 2
Recommending movies
A prediction for one movie is nice. A recommendation is the natural next step: predict every movie a user hasn't seen, sort by predicted rating, and hand back the top few. That's the whole product.
Score every blank, then rank
def recommend(user, n=3):
unseen = np.where(~seen[user])[0] # movies not yet rated
scored = [(movies[i], predict(user, i)) for i in unseen]
scored.sort(key=lambda pair: pair[1], reverse=True) # best first
return scored[:n]Recommend for Alice
for title, score in recommend(0): # Alice is user index 0
print(f"{score:.2f} {title}")4.07 Interstellar
1.55 Love ActuallyThere it is — a working recommender. Alice's top pick is Interstellar, the sci-fi film she happened to miss, scored well above the rom-com. We never wrote a rule about genres; the ranking came entirely from "people with your taste loved this."
It's personalized — really
The proof that this isn't a fixed "popular movies" list: run it for someone with the opposite taste and the recommendations flip completely.
print("For Alice:", recommend(0, n=1)) # sci-fi fan
print("For Dave: ", recommend(3, n=1)) # rom-com fanFor Alice: [('Interstellar', 4.07)]
For Dave: [('Pretty Woman', 4.26)]Same code, same data — but the sci-fi fan is steered to Interstellar and the rom-com fan to Pretty Woman. Each person's recommendations come from their own neighborhood of similar users. That's collaborative filtering working end to end. Next, a different angle on the same idea — one that can explain why.