Machine Learning β€Ί Unsupervised Learning β€Ί Day 188

Day 188: Recommender Systems

Day 188 of 365 β€” Recommender Systems

Master recommender systems: formulate collaborative filtering with cosine and Pearson similarities, implement matrix factorization via SGD and Alternating Least Squares (ALS), and evaluate ranking metrics.

Course
Machine Learning
Category
Unsupervised Learning
Reading time
β‰ˆ 35 min
Practical time
β‰ˆ 50 min
Lesson duration
1h 25m
Last verified
2026-08-29

Hands-on lab for this lesson

Lab files on GitHub: https://github.com/ai-roadmap-365/ai-roadmap-365.github.io/tree/main/labs/sections/machine-learning/day-188-recommender-systems

  1. Get the hands-on files. Clone the labs repository once (you can reuse this clone for every lesson). This works on macOS, Linux, and Windows (PowerShell or WSL):
    git clone https://github.com/ai-roadmap-365/ai-roadmap-365.github.io.git
    cd ai-roadmap-365.github.io
  2. Open this lesson's lab. Move into the directory for this specific day. Every lab lives at the same predictable path β€” section / subsection / week / day:
    cd labs/sections/machine-learning/day-188-recommender-systems
  3. Read the lab guide. Open `README.md` in that directory. It lists the exact commands, what each does, the expected output, and how to check your work β€” read it before running anything.
  4. Run it and check your work. Follow the README's "How to run" section: run the example first to see the finished result, then complete the numbered exercises in `starter/`, then run the tests. The tests pass (exit 0) only when your work is correct.
    bash tests/run_tests.sh   # or the test command named in the lab README

You can also open the lab as a local page (works offline, shows the file tree and expected output).

Learning objectives

By the end of this lesson you will be able to:

Prerequisites

In the modern digital economy, information abundance creates the paradox of choice:

No human user can manually search or evaluate millions of potential items. Recommender Systems bridge this fundamental gap, acting as intelligent algorithmic curators that personalize feeds, suggest relevant items, and drive the vast majority of digital engagement (powering greater than 80% of video views on Netflix and greater than 35% of purchases on Amazon).

Today, we master the complete theory and implementation of recommender systems: Neighborhood Collaborative Filtering, Matrix Factorization (Funk SVD), Alternating Least Squares (ALS), and Ranking Evaluation Metrics (RMSE, Precision@K, NDCG@K).


Why this matters

Personalized recommendation architectures are core revenue engines in modern software systems:

  1. Streaming Media Personalization: Dynamically ordering homepage video rows, movie carousels, and automated next-track playlists based on real-time watch histories.
  2. E-Commerce Conversion Optimization: Serving cross-sell (β€œCustomers who bought this also bought…”) and personalized basket bundles.
  3. News and Social Media Feed Ranking: Scoring billions of candidate posts to deliver high-engagement, real-time social streams (TikTok, X, Instagram).
  4. Talent and Job Matching: Pairing candidate resumes with job openings in enterprise hiring portals (LinkedIn, Indeed).
  5. App Store and Digital Marketplace Discovery: Surfacing relevant software apps, mobile games, and digital assets.

The idea in plain language

Imagine walking into a massive bookstore containing 1,000,000 books:


Historical background

  1. 1992 (Tapestry - Goldberg et al.): Introduced the term Collaborative Filtering at Xerox PARC for filtering technical email documents based on peer annotations.
  2. 1994 (GroupLens - Resnick et al.): Developed automated neighborhood-based collaborative filtering using Pearson correlation on Usenet news feeds.
  3. 2006–2009 (The Netflix Prize): Netflix offered a $1,000,000 grand prize to any team that could improve their Cinematch movie recommendation algorithm by 10% RMSE. Simon Funk published a blog post introducing gradient-descent-based Matrix Factorization (Funk SVD), which became the cornerstone of the winning ensemble (BellKor’s Pragmatic Chaos).
  4. 2008 (Hu, Koren, Volinsky): Published Implicit Feedback ALS, allowing matrix factorization to scale across binary click, view, and purchase interactions.
  5. 2016–Present (Deep Learning & Two-Tower Embeddings): YouTube and Google introduced deep neural Two-Tower architectures (Candidate Generation via vector search followed by heavy Ranker scoring).

What it is β€” and what it is not

What Recommender Systems ARE:

What they are NOT:


Why it was created and what problems it solves

Traditional search engines require the user to formulate an explicit text query. But in discovery scenarios (e.g. β€œWhat music should I listen to while cooking dinner?”), users do not know what specific item they want.

Recommender systems solve this by proactively surfacing relevant items without requiring explicit search queries, unlocking long-tail catalog monetization and dramatically boosting customer retention.


How it works

Let us dissect the mathematical formulation of Collaborative Filtering, Matrix Factorization, and Ranking Metrics.

1. Collaborative Filtering: Similarity Metrics

Two path diagram illustrating User based collaborative filtering neighborhood consensus versus Item based similarity weighting

Given a sparse user-item rating matrix R in R^(M x N), where r_(u,i) represents the rating given by user u to item i.

A. Cosine Similarity:

For two user rating vectors u and v (or item vectors i and j):

sim_cos(u, v) = (u . v) / (||u|| * ||v||) = sum_{i in I_{uv}} (r_{u,i} * r_{v,i}) / (sqrt(sum r_{u,i}^2) * sqrt(sum r_{v,i}^2))

where I_(uv) is the set of items co-rated by both user u and user v.

B. Pearson Correlation Coefficient:

Accounts for user rating baselines (harsh vs generous raters):

sim_pearson(u, v) = sum_{i in I_{uv}} (r_{u,i} - r_bar_u) * (r_{v,i} - r_bar_v) / (sqrt(sum (r_{u,i} - r_bar_u)^2) * sqrt(sum (r_{v,i} - r_bar_v)^2))

Rating Prediction in User-User Collaborative Filtering:

To predict rating r_hat_(u,i) for user u on item i:

r_hat_{u,i} = r_bar_u + sum_{v in N_k(u; i)} sim(u, v) * (r_{v,i} - r_bar_v) / sum_{v in N_k(u; i)} |sim(u, v)|

where N_k(u; i) is the set of top-k most similar users to u who have rated item i.


2. Matrix Factorization (Funk SVD) Formulation

Matrix factorization diagram decomposing a sparse user item rating matrix R into dense user embedding matrix P and item embedding matrix Q with latent dimension k

Matrix Factorization maps both users and items to a joint latent factor space of dimensionality K (typically K = 20 to 100):

The Rating Prediction Model:

r_hat_{u,i} = mu + b_u + b_i + p_u^T * q_i

where:

Regularized Loss Function:

Let Kappa be the set of all observed user-item pairs (u, i) in rating matrix R. We minimize the regularized Mean Squared Error:

min_{P, Q, b} sum_{(u,i) in Kappa} (r_{u,i} - r_hat_{u,i})^2 + lambda * (||p_u||^2 + ||q_i||^2 + b_u^2 + b_i^2)

where lambda is the L2 regularization hyperparameter.


3. Optimization via Stochastic Gradient Descent (SGD)

For each observed rating r_(u,i) in training set Kappa, we compute the prediction error:

e_{u,i} = r_{u,i} - r_hat_{u,i} = r_{u,i} - (mu + b_u + b_i + p_u^T * q_i)

We update parameters in the opposite direction of the loss gradient with learning rate gamma:

b_u   <- b_u   + gamma * (e_{u,i} - lambda * b_u)
b_i   <- b_i   + gamma * (e_{u,i} - lambda * b_i)
p_u   <- p_u   + gamma * (e_{u,i} * q_i - lambda * p_u)
q_i   <- q_i   + gamma * (e_{u,i} * p_u - lambda * q_i)

4. Alternating Least Squares (ALS) and Implicit Feedback

While SGD updates one rating at a time, Alternating Least Squares (ALS) alternates between:

  1. Fixing all item vectors Q: The loss function becomes quadratic and convex with respect to user vectors P. Each user vector p_u is solved independently via regularized linear regression:
    p_u = (Q_u^T * Q_u + lambda * I)^{-1} * Q_u^T * r_u
  2. Fixing all user vectors P: Each item vector q_i is solved independently:
    q_i = (P_i^T * P_i + lambda * I)^{-1} * P_i^T * r_i

Because user updates are completely decoupled, ALS scales effortlessly across distributed Apache Spark clusters.

Implicit Feedback Matrix Factorization (Hu-Koren-Volinsky ALS-WR):

In real-world web applications, explicit star ratings are exceedingly scarce (less than 1% of users rate items). Instead, systems collect implicit feedback (clicks, video views, page dwell time, repeat purchases).

Hu, Koren, and Volinsky (2008) converted raw interaction counts r_(u,i) into binary preferences p_(u,i) and confidence weights c_(u,i):

The loss function optimizes confidence-weighted squared error over ALL user-item pairs (including zero interactions):

min_{P, Q} sum_{u, i} c_{u,i} * (p_{u,i} - p_u^T q_i)^2 + lambda * (sum_u ||p_u||^2 + sum_i ||q_i||^2)

Through algebraic trickery, the global Gram matrix sum_i q_i q_i^T is precomputed once per epoch in O(N * K^2), enabling exact closed-form ALS updates in linear time O(M * K^3 + |Observed| * K^2).


5. Bayesian Personalized Ranking (BPR)

Standard matrix factorization treats unobserved pairs as missing values (in explicit rating) or negative zeros (in implicit ALS). However, an unobserved interaction does not necessarily mean the user dislikes the item; it may simply mean the user was never exposed to it.

Bayesian Personalized Ranking (BPR) (Rendle et al., 2009) frames recommendation as a pairwise ranking problem. For user u, given an observed item i and an unobserved item j, BPR optimizes the probability that user u prefers item i over item j:

P(i >_u j | Theta) = sigma(x_hat_{u,i,j}(Theta)) = 1 / (1 + exp(-(p_u^T q_i - p_u^T q_j)))

The maximum posterior objective minimizes the negative log-likelihood with L2 weight decay:

min_{Theta} - sum_{(u, i, j) in D_S} ln sigma(p_u^T q_i - p_u^T q_j) + lambda_Theta * ||Theta||^2

Trained via stochastic gradient ascent over randomly sampled triples (u, i, j), BPR directly optimizes top-K ranking accuracy (AUC and NDCG) rather than point-wise rating estimation.


6. Evaluation Metrics for Recommender Systems

  1. RMSE (Root Mean Squared Error):
    RMSE = sqrt((1 / |Kappa_{test}|) * sum_{(u,i) in Kappa_{test}} (r_{u,i} - r_hat_{u,i})^2)
  2. Precision@K and Recall@K:
    Precision@K = (|Relevant Items in Top K|) / K
  3. NDCG@K (Normalized Discounted Cumulative Gain):
    DCG@K = sum_{r=1}^K (2^{rel_r} - 1) / log_2(r + 1)
    NDCG@K = DCG@K / IDCG@K
    where IDCG@K is the Ideal DCG obtained by sorting items in perfect descending relevance order.

An everyday analogy

Think of dating apps:


Examples in practice

Let us inspect a complete, modular, pure NumPy implementation of Matrix Factorization via SGD:

import numpy as np

class MatrixFactorizationSGD:
    def __init__(self, n_factors=10, lr=0.01, reg=0.05, n_epochs=50, random_state=42):
        self.n_factors = n_factors
        self.lr = lr
        self.reg = reg
        self.n_epochs = n_epochs
        self.random_state = random_state
        self.mu = 0.0
        self.b_u = None
        self.b_i = None
        self.P = None
        self.Q = None

    def fit(self, R_sparse):
        # R_sparse is list of tuples: (u, i, rating)
        rng = np.random.default_rng(self.random_state)
        n_users = max(u for u, i, r in R_sparse) + 1
        n_items = max(i for u, i, r in R_sparse) + 1

        self.mu = np.mean([r for u, i, r in R_sparse])
        self.b_u = np.zeros(n_users)
        self.b_i = np.zeros(n_items)
        self.P = rng.normal(0, 0.1, (n_users, self.n_factors))
        self.Q = rng.normal(0, 0.1, (n_items, self.n_factors))

        for epoch in range(self.n_epochs):
            for u, i, r in R_sparse:
                pred = self.mu + self.b_u[u] + self.b_i[i] + np.dot(self.P[u], self.Q[i])
                err = r - pred

                # Gradient updates
                self.b_u[u] += self.lr * (err - self.reg * self.b_u[u])
                self.b_i[i] += self.lr * (err - self.reg * self.b_i[i])

                p_u_old = self.P[u].copy()
                self.P[u] += self.lr * (err * self.Q[i] - self.reg * self.P[u])
                self.Q[i] += self.lr * (err * p_u_old - self.reg * self.Q[i])

        return self

    def predict(self, u, i):
        return self.mu + self.b_u[u] + self.b_i[i] + np.dot(self.P[u], self.Q[i])

Implications: security, privacy, performance, scalability, and cost

  1. The Filter Bubble and Polarization:
    • Over-optimizing engagement metrics (clicks, watch time) creates self-reinforcing echo chambers and radicalization. Modern recommenders inject Exploration & Diversity constraints (e.g. epsilon-greedy sampling, Determinantal Point Processes / DPP).
  2. Cold Start Strategies:
    • For new users: Serve demographic/popular defaults, onboarding preference quizzes, or contextual bandit exploration.
    • For new items: Use Two-Tower Neural Networks where content features (text descriptions, image embeddings) map cold items directly into the latent factor space.

Alternatives: free, open source, and commercial

ArchitectureParadigmLatencyRecommended Library
Matrix Factorization (Funk SVD)Latent Matrix Factorizationless than 1 mssurprise, implicit
ALS (Implicit Feedback)Distributed Matrix Decompositionless than 1 msimplicit, Apache Spark MLLib
Two-Tower Neural EmbeddingsDeep Retrieval (ANN Search)< 5 msTensorFlow Recommenders (TFRS)
Monolithic Transformer RankersDeep Session Transformers10–50 msNVIDIA Merlin / HugeCTR

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                   RECOMMENDER ARCHITECTURE COMPARISON                  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Dimension          β”‚ Collaborative Filterβ”‚ Content-Based  β”‚ Two-Tower  β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Data Required      β”‚ User-Item Ratings   β”‚ Item Metadata  β”‚ Both + Logsβ”‚
β”‚ Cold Start Handlingβ”‚ Poor                β”‚ Excellent      β”‚ Excellent  β”‚
β”‚ Serendipity        β”‚ High (Discovers)    β”‚ Low (Similar)  β”‚ Very High  β”‚
β”‚ Scalability        β”‚ O(N^2) or O(M*N*K)  β”‚ O(Items * Dim) β”‚ O(log N)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

When to use it β€” and when not to

When to USE Recommender Systems:

When NOT to use them:


Knowledge check

  1. What is the Cold Start problem, and how do hybrid recommenders resolve it for newly added items?
  2. Why are explicit user and item bias terms b_u and b_i critical in matrix factorization?
  3. How does Alternating Least Squares (ALS) parallelize matrix factorization updates across multiple CPU cores?
  4. What is the difference between explicit rating matrices and implicit interaction datasets?
  5. How does NDCG@K evaluate the ranking quality of a recommended top-10 list?

Hands-on exercise

In this lab, you will implement MatrixFactorizationSGD in pure NumPy, fit latent factor vectors on a sparse movie rating matrix, calculate test RMSE, and generate top-K personalized item recommendations.

Expected output

[Recommender Benchmark Execution]
Dataset: 50 users, 20 items, 250 observed ratings
Matrix Factorization: Latent Factors K=4, Epochs=40
Training RMSE: 0.2845
Test Rating Prediction: User 0 on Item 3 -> 4.12 stars
Test Suite: 2 passed in 0.08s

Validate your work

Run the automated test runner:

./tests/run_tests.sh

Troubleshooting

Common mistakes


Practice assignment

  1. Implement Item-Item Collaborative Filtering using Pearson correlation and evaluate prediction RMSE on the MovieLens dataset.
  2. Build an automated NDCG@K ranking metric evaluator in pure NumPy.

Extension challenge

Implement Bayesian Personalized Ranking (BPR-MF):

Quiz

Q1. What is the Cold Start Problem in collaborative filtering recommender systems?

  1. The difficulty of generating accurate recommendations for brand new users or newly added items that have zero historical interactions or ratings
  2. The latency overhead of spinning up GPU worker nodes during morning peak traffic
  3. The numerical instability of computing matrix inverse on zero matrices
  4. The memory exhaustion caused by loading 1 billion user rows into RAM
Show answer

Answer: A. The difficulty of generating accurate recommendations for brand new users or newly added items that have zero historical interactions or ratings

Collaborative filtering relies on overlapping interaction histories. When a new user or item joins with zero ratings, the system has no vectors to compute similarities against.

Q2. Why are explicit user and item bias terms (b_u and b_i) included in matrix factorization: r_hat_{u,i} = mu + b_u + b_i + p_u . q_i?

  1. They capture systematic tendencies, such as critical users who consistently rate 1 star lower or universally acclaimed blockbuster movies that rate higher overall
  2. They prevent matrix multiplication from outputting negative numbers
  3. They normalize the latent dimension size K to equal 100
  4. They convert implicit clicks into explicit star ratings
Show answer

Answer: A. They capture systematic tendencies, such as critical users who consistently rate 1 star lower or universally acclaimed blockbuster movies that rate higher overall

Much of rating variation is explained by baseline user tendencies (some people are generous raters; others are harsh) and item quality, rather than complex user-item interaction affinities.

Q3. What is the primary difference between explicit feedback and implicit feedback in modern recommender systems?

  1. Explicit feedback consists of direct user ratings (e.g. 1-5 stars); implicit feedback consists of passive behavioral telemetry (e.g. clicks, watch time, purchase events)
  2. Explicit feedback uses floating point values; implicit feedback uses binary strings
  3. Explicit feedback requires GPU training; implicit feedback runs on CPU
  4. Explicit feedback is only available for e-commerce products
Show answer

Answer: A. Explicit feedback consists of direct user ratings (e.g. 1-5 stars); implicit feedback consists of passive behavioral telemetry (e.g. clicks, watch time, purchase events)

Explicit feedback captures deliberate scores, which are rare (<1% of users rate). Implicit feedback captures continuous user activity, which is abundant but lacks negative signals.

Q4. How does Normalized Discounted Cumulative Gain at K (NDCG@K) reward ranking quality compared to Precision@K?

  1. NDCG applies a logarithmic position discount, penalizing relevant items placed lower in the recommended top-K list far more heavily than top positions
  2. NDCG only checks whether the single top item is relevant
  3. NDCG ignores item order and counts total relevant items
  4. NDCG measures the execution time of the ranking database query
Show answer

Answer: A. NDCG applies a logarithmic position discount, penalizing relevant items placed lower in the recommended top-K list far more heavily than top positions

NDCG rewards placing highly relevant items at the very top of the list by discounting utility by 1 / log2(rank + 1), reflecting true user browsing behavior.

Q5. What is the key computational advantage of Alternating Least Squares (ALS) over Stochastic Gradient Descent (SGD) for matrix factorization?

  1. When fixing item vectors Q, the objective for each user vector p_u decouples into independent ridge regressions that can be solved in parallel across thousands of CPU cores
  2. ALS does not require any matrix inversions
  3. ALS eliminates the need for regularization parameters
  4. ALS guarantees 100% training accuracy in 1 iteration
Show answer

Answer: A. When fixing item vectors Q, the objective for each user vector p_u decouples into independent ridge regressions that can be solved in parallel across thousands of CPU cores

Fixing one matrix makes the loss quadratic and convex. User and item vectors can be updated independently and in parallel across distributed Spark or Ray clusters.

Glossary

Recommender System
An algorithmic system that predicts user preference ratings or ranks items to deliver personalized suggestions.
Collaborative Filtering
A recommendation method based on historical interactions and behavioral similarities between users and items without requiring domain attributes.
Matrix Factorization
Decomposing a sparse user-item interaction matrix into low-rank latent user and item embedding vectors.
Cold Start Problem
The challenge of recommending items to new users or recommending new items with no prior interaction history.
Implicit Feedback
Passive user behavioral signals (clicks, views, dwell time, purchases) rather than explicit numeric ratings.
Alternating Least Squares (ALS)
An optimization algorithm that alternates between fixing user matrices to solve for items and fixing item matrices to solve for users.
NDCG@K
Normalized Discounted Cumulative Gain at rank K, measuring ranking quality with logarithmic position penalties.
Cosine Similarity
A metric measuring the cosine of the angle between two multi-dimensional vectors, evaluating directional similarity independent of magnitude.

Sources and further reading


Kept in this browser, no account needed. Your progress page turns the whole record into one link you can bookmark or open on another device.