← Back to DevBytes

How to Build a Recommendation Engine with Collaborative Filtering

What is Collaborative Filtering?

Collaborative filtering is a technique used by recommendation engines to predict a user’s interests by collecting preferences from many other users. The core assumption is that if two users agreed in the past on some items, they are likely to agree again in the future. Instead of analyzing item features (like in content-based filtering), collaborative filtering relies purely on user–item interaction data, such as ratings, clicks, or purchases.

There are two main families of collaborative filtering algorithms:

Memory-Based Approaches

Memory-based methods can be user-centric or item-centric. In user-user collaborative filtering, you find users whose rating history resembles the target user’s history, then recommend items those similar users liked. In item-item collaborative filtering (popularized by Amazon), you find items similar to the ones the user already rated highly, then recommend those similar items. Both approaches rely on a similarity metric like cosine similarity or Pearson correlation computed over co-rated items or users.

Model-Based Approaches

Model-based methods try to capture latent factors that explain observed ratings. The most famous example is matrix factorization, where the large, sparse user–item matrix is decomposed into two smaller matrices: a user-feature matrix and an item-feature matrix. Multiplying them reconstructs the rating matrix, filling in missing values. Singular Value Decomposition (SVD) and Alternating Least Squares (ALS) are widely used. These models handle sparsity better, generalize more smoothly, and scale well with proper optimization.

Why Collaborative Filtering Matters

🚀 Deploy your AI agent in 10 minutes

Managed Hermes hosting. Zero DevOps. 100M tokens/mo included.

Try it free →

Collaborative filtering powers the personalization behind Netflix, Spotify, Amazon, and YouTube. It matters because:

In practice, pure collaborative filtering struggles with the cold-start problem (new users or new items have no history). That’s why production systems often blend it with content-based or demographic signals. Still, collaborative filtering remains the backbone of modern recommenders.

How to Build a Recommendation Engine with Collaborative Filtering

We’ll walk through a complete implementation, starting with memory-based user-user filtering and then a model-based SVD recommender. We’ll use Python with pandas, numpy, and scikit-learn. For the model-based part, we’ll use the surprise library. The dataset will be a small movie ratings dataset, but the principles apply to any interaction data.

1. Preparing the Data

The raw data usually consists of triplets: user ID, item ID, rating (or implicit signal like view count). We pivot this into a user–item matrix where rows are users, columns are items, and cells are ratings. Missing entries are typically NaN.

import pandas as pd
import numpy as np

# Sample ratings data
ratings_dict = {
    'user_id': [1, 1, 1, 2, 2, 2, 3, 3, 3, 4],
    'item_id': ['A', 'B', 'C', 'A', 'B', 'D', 'B', 'C', 'E', 'A'],
    'rating': [5, 3, 4, 4, 5, 2, 3, 4, 5, 1]
}
df = pd.DataFrame(ratings_dict)

# Create user-item matrix
user_item_matrix = df.pivot(index='user_id', columns='item_id', values='rating')
print(user_item_matrix)

Output will look like this (NaN where no rating exists):

item_id    A    B    C    D    E
user_id                        
1        5.0  3.0  4.0  NaN  NaN
2        4.0  5.0  NaN  2.0  NaN
3        NaN  3.0  4.0  NaN  5.0
4        1.0  NaN  NaN  NaN  NaN

2. Computing Similarity

For user-user CF, we compute similarity between each pair of users based on the items they co-rated. We replace missing values with 0 (or mean-impute) but only consider co-rated items. A common approach is to center each user’s ratings by subtracting their mean, then use cosine similarity. This avoids bias from users who always rate high or low.

from sklearn.metrics.pairwise import cosine_similarity

# Fill NaN with 0 for similarity computation (we will mask later)
matrix_filled = user_item_matrix.fillna(0)

# Center ratings by subtracting user mean (only over rated items)
user_means = user_item_matrix.mean(axis=1)
matrix_centered = user_item_matrix.sub(user_means, axis=0).fillna(0)

# Compute user-user cosine similarity
user_similarity = cosine_similarity(matrix_centered)
user_sim_df = pd.DataFrame(user_similarity,
                           index=user_item_matrix.index,
                           columns=user_item_matrix.index)
print(user_sim_df.round(2))

This gives a symmetric similarity matrix. A value close to 1 means very similar; 0 means no overlap or orthogonal tastes.

3. Generating Predictions

For a target user u and an unrated item i, the predicted rating is a weighted average of ratings from similar users who rated i. Weights are the similarity scores. Often we use only the top-k most similar users (k-NN) to reduce noise.

def predict_rating(user_id, item_id, matrix, similarity, k=2):
    if item_id not in matrix.columns:
        return None
    # Users who rated this item
    rated_by = matrix[item_id].dropna().index
    # Similarities between target user and those users
    sims = similarity.loc[user_id, rated_by]
    # Keep top k most similar
    top_k = sims.nlargest(k)
    if top_k.sum() == 0:
        # No similar user rated the item
        return None
    # Corresponding ratings
    ratings = matrix.loc[top_k.index, item_id]
    # Weighted average prediction
    pred = np.dot(top_k, ratings) / top_k.sum()
    return pred

# Predict for user 1 on item 'D'
pred = predict_rating(1, 'D', user_item_matrix, user_sim_df, k=2)
print(f"Predicted rating for user 1 on item D: {pred:.2f}")

We can loop over all unrated items for a user and recommend the ones with highest predicted ratings.

4. Building a Model-Based Recommender with Matrix Factorization

For a more robust and scalable solution, we use Singular Value Decomposition (SVD). We'll use the surprise library, which implements SVD optimized for rating prediction (using stochastic gradient descent). First install it: pip install scikit-surprise.

from surprise import Dataset, Reader, SVD
from surprise.model_selection import train_test_split, cross_validate

# Prepare data for surprise (needs user, item, rating columns)
ratings_data = df[['user_id', 'item_id', 'rating']]
reader = Reader(rating_scale=(1, 5))
data = Dataset.load_from_df(ratings_data, reader)

# Train-test split
trainset, testset = train_test_split(data, test_size=0.2, random_state=42)

# Build and train SVD model
model = SVD(n_factors=20, n_epochs=30, biased=True, random_state=42)
model.fit(trainset)

# Evaluate on testset
predictions = model.test(testset)
rmse = accuracy.rmse(predictions)
print(f"RMSE: {rmse:.4f}")

We can now predict a rating for any user–item pair:

# Predict for user 1, item 'D'
pred = model.predict(1, 'D')
print(f"Predicted rating for user 1 on item D: {pred.est:.2f}")

5. Evaluating the Model

Evaluation metrics depend on the goal. For rating prediction, RMSE (Root Mean Squared Error) and MAE (Mean Absolute Error) are standard. For top-N recommendation, use Precision@k, Recall@k, or MAP. With surprise, you can run cross-validation easily:

from surprise.model_selection import GridSearchCV

# Simple cross-validation
cv_results = cross_validate(model, data, measures=['RMSE', 'MAE'], cv=5, verbose=True)
print(cv_results['test_rmse'].mean())

Always split your data temporally if possible (train on older, test on newer) to avoid simulating future information leaking into the past.

Best Practices

Conclusion

Collaborative filtering transforms raw user–item interactions into personalized recommendations by exploiting similarity patterns across users or items. You can start with a simple memory-based user-user or item-item approach, then graduate to model-based matrix factorization for better scalability and accuracy. The code examples above give you a complete, runnable blueprint – from pivoting a DataFrame to training an SVD model and evaluating it. Remember to normalize data, handle cold start, and keep iterating based on both offline metrics and online user feedback. With these fundamentals, you're ready to build the recommendation engine that sits at the heart of modern data-driven applications.

🚀 Need a reliable AI agent for your project?

Deploy Hermes Agent in 10 minutes. Managed hosting, zero DevOps.

Get Started — $23.99/mo
← Back to all articles