Chapter 5 · Part 2
Because you liked…
So far we found similar users. But there's a twist on the same idea that powers one of the most familiar lines on the internet — "because you watched The Matrix". Instead of asking "who's like this user?", we ask "which movies are like this movie?" That's item-based collaborative filtering.
Similar movies, from who rated them alike
The insight: two movies are similar if the same people tend to rate them the same way. Sci-fi fans rate The Matrix and Interstellar both high; rom-com fans rate both low. So we run the exact same cosine-similarity machinery — just on the columns (movies) instead of the rows (users). Center each movie by its own average rating, then compare:
# center each MOVIE by its average rating (over users who rated it)
movie_means = R.sum(axis=0) / seen.sum(axis=0)
movie_centered = np.where(seen, R - movie_means[None, :], 0.0)
cols = movie_centered.T # movies as rows now: (6 movies, 6 users)
cnorms = np.linalg.norm(cols, axis=1, keepdims=True)
movie_unit = cols / np.where(cnorms == 0, 1, cnorms)
movie_similarity = movie_unit @ movie_unit.T # (6, 6) movie-movie similarityIt's the same three lines as the user version — normalize, matrix-multiply — just transposed. Cosine similarity doesn't care whether the vectors are users or movies.
"If you liked The Matrix…"
def similar_movies(movie, n=3):
scores = movie_similarity[movie]
order = np.argsort(scores)[::-1] # highest similarity first
order = [i for i in order if i != movie][:n] # drop the movie itself
return [(movies[i], round(scores[i], 2)) for i in order]
print(similar_movies(0)) # movie 0 = The Matrix[('Interstellar', 0.68), ('Inception', 0.62), ('Pretty Woman', -0.37)]The two closest movies to The Matrix are Interstellar (0.68) and Inception (0.62) —
the other two sci-fi films — while the rom-com Pretty Woman sits at −0.37, actively
anti-recommended. Now "because you liked The Matrix, try Interstellar" writes itself.
Item-based recs have a practical edge: movies' similarities change slowly (a film's audience is stable), so you can precompute this matrix once and serve recommendations instantly — which is why the big streaming services lean on it. Last chapter: is any of this actually good?