Recommendation Systems

Recommendation systems suggest relevant items to users — powering Netflix, Spotify, and Amazon. They fall into two families: content-based filtering (recommend items similar to what you liked) and collaborative filtering (recommend what users like you enjoyed).

Content-Based

Uses item features (genres, keywords) to find similar items. No data from other users required.

Collaborative Filtering

Uses user–item ratings. Finds users with similar taste and recommends what they liked.

Content-Based Filtering

Using the MovieLens dataset (9,742 movies), each movie is represented as a binary genre vector. Movies with similar genre vectors are considered similar.

One-Hot Encode Genres

import pandas as pd

movies = pd.read_csv('movies.csv')  # columns: movieId, title, genres

# Collect all unique genres
all_genres = set()
for g in movies['genres']:
    all_genres.update(g.split('|'))

# Create a binary column for each genre
for genre in all_genres:
    movies[genre] = movies['genres'].apply(
        lambda x: 1 if genre in x.split('|') else 0
    )

print(movies[['title', 'Action', 'Comedy', 'Drama']].head())

Recommend Similar Movies

from sklearn.metrics.pairwise import cosine_similarity

genre_cols = list(all_genres)
sim_matrix = cosine_similarity(movies[genre_cols])

def get_recommendations(title, n=5):
    idx = movies[movies['title'] == title].index[0]
    scores = sorted(enumerate(sim_matrix[idx]), key=lambda x: x[1], reverse=True)[1:n+1]
    return movies.iloc[[i for i, _ in scores]]['title'].tolist()

print(get_recommendations('Toy Story (1995)'))

Cosine Similarity

Notebook

Cosine similarity measures the angle between two vectors. A value of 1 = identical, 0 = no overlap, -1 = opposite.

// Formula

cos(θ) = (A · B) / (‖A‖ × ‖B‖)

import numpy as np

def cosine_sim(a, b):
    return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))

# Genre vectors: [Action, Animation, Children, Comedy, Fantasy]
toy_story = [0, 1, 1, 1, 1]
shrek     = [0, 1, 1, 1, 1]
die_hard  = [1, 0, 0, 0, 0]

print(cosine_sim(toy_story, shrek))    # 1.0 — identical genres
print(cosine_sim(toy_story, die_hard)) # 0.0 — no overlap

Collaborative Filtering

Collaborative filtering uses a user–item rating matrix. We use KNN on 100,836 ratings from 610 users with cosine distance to find similar movies.

Build the Rating Matrix

from scipy.sparse import csr_matrix

ratings = pd.read_csv('ratings.csv')  # userId, movieId, rating

def create_matrix(df):
    user_mapper  = {u: i for i, u in enumerate(df['userId'].unique())}
    movie_mapper = {m: i for i, m in enumerate(df['movieId'].unique())}
    movie_inv    = {v: k for k, v in movie_mapper.items()}

    user_idx  = [user_mapper[u]  for u in df['userId']]
    movie_idx = [movie_mapper[m] for m in df['movieId']]

    X = csr_matrix((df['rating'], (movie_idx, user_idx)))
    return X, movie_mapper, movie_inv

X, movie_mapper, movie_inv = create_matrix(ratings)

KNN Movie Recommendations

from sklearn.neighbors import NearestNeighbors

knn = NearestNeighbors(n_neighbors=6, algorithm='brute', metric='cosine')
knn.fit(X)

def similar_movies(movie_id, k=5):
    idx = movie_mapper[movie_id]
    _, indices = knn.kneighbors(X[idx], n_neighbors=k+1)
    return [movie_inv[i] for i in indices.flatten()[1:]]

print(similar_movies(1))  # Movies similar to Toy Story

Cold Start Problem

Collaborative filtering fails for new users (no ratings) or new items. Content-based filtering handles this — real systems combine both (hybrid recommenders).

Live Demo — Genre-Based Recommender

Notebook ONNX

Select the genres you enjoy and click Find Movies. The recommender builds your preference vector and returns the top matches using cosine similarity — exactly like a real content-based system.

Your Genre Preferences

Knowledge Check

Test your understanding — pick the best answer, then click Check.

1. What does cosine similarity measure?

2. What is the cold start problem?

3. What is the key difference between content-based and collaborative filtering?