๐Ÿ“ˆ Machine Learning ยท Lecture 42 of 47

Recommender Systems II: Matrix Factorisation and Latent Factors

Matrix factorisation represents users and items as vectors in a shared latent space. We derive the regularised objective, train it with SGD and ALS, add biases and implicit feedback, and connect it to modern embedding models.

The Netflix Prize (2006โ€“2009) offered one million dollars to anyone who could improve Netflix's rating predictions by 10%. The decisive technique was matrix factorisation: represent every user and every item as a short vector of latent factors so that their dot product predicts the rating. The idea is simple, scales to huge data and underlies the embedding-based retrieval used by today's recommendation systems.

The model#

Choose a latent dimension $k$ (e.g. 20โ€“200). Learn user vectors $\mathbf{p}_u \in \mathbb{R}^k$ and item vectors $\mathbf{q}_i \in \mathbb{R}^k$ such that

$$ \hat{r}_{ui} = \mu + b_u + b_i + \mathbf{p}_u^\top\mathbf{q}_i $$

where $\mu$ is the global mean rating, $b_u$ a user bias (some people rate everything high) and $b_i$ an item bias (some films are universally liked). Stacking vectors, $\mathbf{R} \approx \mathbf{P}\mathbf{Q}^\top$ โ€” a low-rank approximation.

The latent dimensions often become interpretable after training: one might separate serious dramas from light comedies; another, films for children from films for adults. Nobody labels these dimensions; they emerge from the data.

Why not just use the SVD?#

Classical SVD requires a complete matrix. Filling missing entries with zeros or means would treat "unseen" as "disliked" and swamp the model with fake data. Instead we fit only the observed entries $\mathcal{K}$:

$$ \min_{\mathbf{P}, \mathbf{Q}, \mathbf{b}}\sum_{(u,i) \in \mathcal{K}}\big(r_{ui} - \hat{r}_{ui}\big)^2 + \lambda\left(\|\mathbf{p}_u\|^2 + \|\mathbf{q}_i\|^2 + b_u^2 + b_i^2\right) $$

Regularisation is essential: with many parameters and sparse data, the model would otherwise memorise the observed ratings.

Training method 1: stochastic gradient descent#

For each observed rating, compute the error $e_{ui} = r_{ui} - \hat{r}_{ui}$ and update:

$$ \mathbf{p}_u \leftarrow \mathbf{p}_u + \eta(e_{ui}\mathbf{q}_i - \lambda\mathbf{p}_u), \qquad \mathbf{q}_i \leftarrow \mathbf{q}_i + \eta(e_{ui}\mathbf{p}_u - \lambda\mathbf{q}_i) $$

(and similarly for biases). This is Simon Funk's famous approach from the Netflix Prize.

python
import numpy as np

def train_mf(ratings, n_users, n_items, k=20, lr=0.01, reg=0.05, epochs=30, seed=0):
    rng = np.random.default_rng(seed)
    P = 0.1 * rng.normal(size=(n_users, k)); Q = 0.1 * rng.normal(size=(n_items, k))
    bu, bi = np.zeros(n_users), np.zeros(n_items)
    mu = np.mean([r for _, _, r in ratings])
    for epoch in range(epochs):
        rng.shuffle(ratings)
        for u, i, r in ratings:
            e = r - (mu + bu[u] + bi[i] + P[u] @ Q[i])
            bu[u] += lr * (e - reg * bu[u]); bi[i] += lr * (e - reg * bi[i])
            P[u], Q[i] = P[u] + lr * (e * Q[i] - reg * P[u]), Q[i] + lr * (e * P[u] - reg * Q[i])
    return mu, bu, bi, P, Q

# Synthetic data with a true rank-3 structure
rng = np.random.default_rng(1)
U, I, K = 300, 200, 3
true = rng.normal(size=(U, K)) @ rng.normal(size=(I, K)).T
obs = [(u, i, float(np.clip(3 + true[u, i] + rng.normal(0, .3), 1, 5)))
       for u in range(U) for i in range(I) if rng.random() < 0.05]
split = int(0.8 * len(obs)); train, test = obs[:split], obs[split:]
mu, bu, bi, P, Q = train_mf(list(train), U, I)
rmse = np.sqrt(np.mean([(r - (mu + bu[u] + bi[i] + P[u] @ Q[i])) ** 2 for u, i, r in test]))
base = np.sqrt(np.mean([(r - mu) ** 2 for _, _, r in test]))
print(f"test RMSE: MF={rmse:.3f}  global-mean baseline={base:.3f}")

Training method 2: alternating least squares (ALS)#

The objective is not jointly convex in $\mathbf{P}$ and $\mathbf{Q}$, but it is convex in each with the other fixed. ALS alternates: fix $\mathbf{Q}$ and solve a ridge regression for every user vector in closed form,

$$ \mathbf{p}_u = \left(\mathbf{Q}_{\mathcal{I}_u}^\top\mathbf{Q}_{\mathcal{I}_u} + \lambda\mathbf{I}\right)^{-1}\mathbf{Q}_{\mathcal{I}_u}^\top\mathbf{r}_u $$

then fix $\mathbf{P}$ and solve for every item. Each half-step is embarrassingly parallel, which is why ALS is the standard in distributed systems such as Spark MLlib.

Implicit feedback#

Hu, Koren and Volinsky (2008) adapted ALS to implicit data: treat every userโ€“item pair as a preference $p_{ui} \in \{0, 1\}$ (interacted or not) with a confidence $c_{ui} = 1 + \alpha\,(\text{interaction count})$. All pairs enter the loss, weighted by confidence, and clever algebra keeps ALS efficient despite the dense matrix. Alternatives train with ranking losses such as Bayesian Personalised Ranking (BPR), which learns that observed items should score higher than sampled unobserved ones.

From factorisation to deep recommenders#

  • Factorisation machines generalise MF to arbitrary features (user attributes, context) by modelling pairwise feature interactions with latent vectors.
  • Two-tower models use neural networks to map user features and item features into the same embedding space โ€” MF with learned encoders. They handle cold start (new items have features) and power large-scale candidate retrieval via approximate nearest-neighbour search.
  • Sequential recommenders (e.g. transformer-based) model the order of a user's interactions.
JA
Written by

Janin A Apurba

B.Sc. in CSE, AUST ยท Advanced ICT Officer, CNRS-UNHCR. Teaching AI, ML and Deep Learning to the next generation of engineers and researchers.

Keep learning

Related lectures

๐Ÿ“ˆ Machine Learning

Recommender Systems I: Content-Based and Collaborative Filtering

Recommendation engines drive what billions of people watch, read and buy. We compare content-based and collaborative approaches, build user- and item-based neighbourhood models, and confront cold start and popularity bias.

Intermediateโฑ 5 min#090
๐Ÿ“ˆ Machine Learning

Encoding Categorical Variables: One-Hot, Ordinal, Target and Beyond

Models need numbers, but many features are categories. We compare one-hot, ordinal, frequency, target and hashing encoders, handle high cardinality and unseen categories, and avoid target-encoding leakage.

Beginnerโฑ 5 min#084
๐Ÿ“ˆ Machine Learning

t-SNE and UMAP: Visualising High-Dimensional Data

Non-linear embeddings reveal cluster structure that PCA hides. We explain how t-SNE and UMAP work, what their hyperparameters do, and โ€” critically โ€” how not to misread their plots.

Intermediateโฑ 5 min#079