HomeAI & Machine LearningRecommendation Engine — Collaborative Filtering Live

🛒 Recommendation Engine — Collaborative Filtering Live

Interactive recommender-system simulator: a user-item rating matrix factors into latent taste vectors — watch recommendations update in real time as a user rates more products.

AI & Machine Learning3DAdvanced60 FPS
ai-marketing-automation ↗ Open standalone

About Collaborative Filtering & Matrix Factorization

Recommender systems like the ones behind online storefronts, streaming services and marketing automation platforms rarely know anything about *why* a customer likes a product — they only see a sparse table of who rated what. Matrix factorization is the technique that turns that sparse table into predictions: it represents every user and every product as a short vector of "latent factors" in the same space, learned so that the dot product of a user's vector and a product's vector reconstructs the ratings that were actually observed. Products a user hasn't rated yet get a predicted score for free, simply because their latent vector sits near products the user already rated highly.

This simulation trains a real rank-2 matrix factorization model with stochastic gradient descent, entirely in the browser. Ten synthetic users and twelve products generate a sparse 1–5 star rating matrix from hidden ground-truth taste factors plus noise; the model never sees those ground-truth vectors — it only sees the sparse stars and has to reconstruct a sensible 2D taste space from scratch. Click a user to see their observed ratings and the model's live top-N recommendations, then add a new rating and watch a few extra gradient steps pull that user's point — and their recommendation list — into a new position.

Frequently Asked Questions

What is collaborative filtering?

Collaborative filtering predicts what a user will like based on the ratings patterns of the whole community, not on hand-coded product attributes. The core idea is that users who agreed in the past (rated the same products similarly) will probably agree again. Matrix factorization is the modern form of collaborative filtering: it compresses the sparse user-item rating matrix into two small dense matrices of latent vectors — one row per user, one row per item — whose dot product reconstructs the observed ratings and, crucially, generalises to the unobserved ones.

What does a latent factor actually represent?

A latent factor is a dimension the model invents during training to explain patterns of agreement in the rating data — it is not chosen or labelled by a human. In this simulation each user and product ends up with a 2D vector; the two axes might loosely correspond to something like practical-vs-playful or cheap-vs-premium purchasing taste, but the model never sees those labels. It only sees numbers, and gradient descent discovers whatever coordinate system best predicts the observed stars. That is why the axes have no fixed meaning across different training runs — only the relative positions of points to each other are meaningful.

What is the cold-start problem for new users?

A brand-new user with zero ratings has a latent vector that is just its random initialisation — it carries no signal about their taste, so predictions for them are no better than the global average rating plus noise. This is the cold-start problem: collaborative filtering needs some observed interactions before it can place a user meaningfully in latent space. In this simulator you can watch it directly — add a single rating for a user and their point visibly jumps toward the products they rated highly, and the recommendation list reorders immediately.

Why is the loss only computed over observed ratings?

The rating matrix is deliberately sparse — each user has only rated a handful of the catalogue, so the vast majority of entries are simply unknown, not zero. Training the model to predict a 0 or an average value for every unobserved entry would actively teach it the wrong thing (that unrated products are disliked). Instead, the squared-error loss sums only over the (user, item) pairs that actually have a star rating: L = Σ(observed) (r_ui − r̂_ui)². Gradients only flow through cells with real feedback, and the latent vectors for unrated pairs are pulled into sensible positions purely by sharing rows and columns with observed cells.

What does the regularization term do?

The training objective adds λ(‖u‖² + ‖p‖²) to the squared-error loss, penalising latent vectors with large magnitude. Without it, a user or product with very few observed ratings can drift to an extreme vector that fits those one or two data points almost perfectly but predicts wildly for everything else — classic overfitting on sparse data. Regularization shrinks vectors toward zero unless the data provides strong repeated evidence to push them further out, trading a little training accuracy for much better generalisation to the unrated products that recommendations actually depend on.

How does adding a new rating change the recommendations live?

When you rate a product for the selected user, that single (user, item, rating) triple is added to the observed set and the optimiser runs a further batch of SGD passes focused on the updated data. Because the user and product vectors are shared parameters, a handful of extra gradient steps is enough to nudge the user's latent position toward products with similar factors — you can watch the point move in the scatter plot and the top-N predicted list reorder within a second, without retraining from scratch.

Why use gradient descent instead of solving for the factors directly?

If every entry of the rating matrix were observed, singular value decomposition (SVD) could compute the optimal low-rank factors directly in closed form. But real rating matrices are extremely sparse — a user has rated a tiny fraction of the catalogue — so classical SVD is undefined for the missing entries. Stochastic gradient descent sidesteps this cleanly: it only ever touches observed cells, scales to millions of ratings because each update is O(K) per rating, and naturally supports incremental updates when new ratings arrive, which is exactly what the live retraining in this simulation relies on.

Why does RMSE plateau instead of reaching zero?

The synthetic ratings in this simulation are generated from ground-truth latent factors plus random noise, so even a perfect model cannot predict the exact noisy stars every time — there is an irreducible error floor set by the noise variance. Regularization also deliberately trades a little training-set accuracy for generalisation, further preventing RMSE from reaching zero. In practice this is healthy: a model that drives observed-set RMSE to zero with only two latent dimensions and a handful of ratings per user is almost certainly memorising noise rather than learning taste.

⚙ Under the hood

A user-item rating matrix factors into latent taste vectors — watch recommendations update live as a user rates more products.

Three.jsWebGLAIMachine Learning

3D · Three.js / WebGL renderer · 60 FPS target · runs fully client-side, no install

What did you find?

Add reproduction steps (optional)