Citation
Methodology
Proof panel
The prediction equation — plain English and formal notation, together
In plain English: the star rating this model predicts for one user and one item is just four numbers added together — the average rating everyone gives, how much higher or lower this user tends to rate things, how much higher or lower this item tends to get rated, and how well this user's learned taste vector points in the same direction as this item's. Formally, in the same breath:
| Term | Plain English | Formal |
|---|---|---|
| Global average | The average star rating across every rating in the whole training set, regardless of who gave it or what it was for. | μ |
| User bias | How much higher or lower this user rates things than that average — some people are just harsher or more generous graders, independent of taste. | bu |
| Item bias | How much higher or lower this item gets rated than average, independent of who's rating it — a widely-loved item vs. a widely-panned one. | bi |
| Personalized match | How well this user's latent taste vector (20 numbers, learned purely from ratings, with no hand-labeled genres) points in the same direction as this item's — their dot product. | qiTpu |
Read the full derivation — the objective function, regularization, and the exact update rule (for a technical reader)
The four terms above aren't fit one at a time — they're learned jointly by minimizing one number: the total squared prediction error over every known rating, plus an L2 regularization penalty that keeps every learned number small so the model doesn't overfit to any single rating.
L is minimized with stochastic gradient descent: for every known rating, visited in random order, each term nudges itself toward making THAT ONE prediction more accurate, scaled by a learning rate γ and pulled back toward zero by the same λ. This run used γ=0.01, λ=0.05, over 60 full passes ("epochs") through the training data — pu in the qi update below is the value from before this interaction's own update (Koren et al. 2009's simultaneous-update formulation).
The Proof panel's headline number is RMSE (root-mean-square error), computed on the held-out set T — 2105 (user, item, rating) triples the model never trained on: the square root of the average squared gap between predicted and actual rating.
This is exactly the risk this run's falsification proof guards against: popularity bias — a model that just learned "recommend whatever's already popular" can look accurate on many real datasets, because popular items collect denser, less noisy rating signal. The pre-registered threshold in the Proof panel above is a popularity-only baseline's own RMSE, computed on this same held-out set with zero leakage; this model beats it on data it never trained on, which a pure-popularity model structurally could not do.
⇩ Download the full technical write-up (.md) — citation, every formula above, and this run's real hyperparameters, in one self-contained fileMeet Jordan
Jordan has rated exactly 3 titles: 5 stars for a scifi pick, 4 stars for an action film, 1 star for a romance. That's the entire signal the model gets — it has never been told what any of those genre words mean, only 3 numbers next to 3 IDs. So here's the question this whole walkthrough is really asking: can it figure Jordan out from that alone?
👆 Click a user in the list on the left. Jordan — the gold-outlined “scenario” entry at the top — is pre-selected for you: their known ratings appear on the left of the panel that opens, and the model's top unrated picks appear on the right.
Users
You're now looking at one real prediction end to end. Check the “genre affinity” table at the bottom of that panel and the payoff box beneath it — the model was never told what a genre is, yet its picks cluster exactly where Jordan already rates highly. That's one person. Step 2 shows you exactly how that number gets computed, term by term; Step 3 checks whether the pattern holds up across everyone else.
Next: Grab the real equation →Look inside one prediction
So how did the model actually reason about Jordan? Not with a genre lookup — it doesn't have one. Every predicted rating is just 4 numbers added together. Below, you move each one by hand, on Jordan's real learned position, and watch a real prediction change live — the exact same formula the server just used to build the recommendation list you saw in Step 1.
Controls 1–4: four independently-manipulable terms, one live equation
👆 Drag the gold dot below — it's the user you picked in Step 1, plotted on 2 of the model's 20 learned taste dimensions. Watch the ranked list on the right reorder as you move it.
👆 Try the two “Factor” dropdowns below to plot a completely different pair of the model's 20 dimensions — the dot jumps to this user's real position on whichever 2 you pick.
| # | Item | Genre | Predicted |
|---|
👆 Click any dot on the plot to pin an item, then drag the two sliders below. “User bias” shifts every item's score by the same amount; “Item bias” moves only the pinned item. Watch the top-5 list and the pinned item's math respond instantly.
Try pinning a different item (click any dot), or nudge both sliders to see the top-5 list and the pinned item's math respond instantly. Step 3 lets you confirm the accuracy number these controls imply.
Next: Verify the proof yourself →Did the model get Jordan right — and does it hold up?
The Proof panel up in Reference reports one number, computed once, offline, over the full 2,105-pair held-out set — the aggregate version of the same question Jordan just answered. Don't take that on faith either: draw from that exact same set right now and watch your own number converge onto it.
👆 Start small: click “Draw 1 pair” below to see one real held-out example scored live. Once you've seen a single draw, click “Draw 100 pairs” a few times — watch the green dot on the RMSE track below walk toward the gold “pre-registered” line. That's the Law of Large Numbers happening in front of you, not asserted.
5Verify the proof yourself — draw from the real held-out set
predict() function every other
control on this page uses, and watch YOUR running RMSE below converge onto the pre-registered number as
your sample grows — the same Law-of-Large-Numbers pattern that makes a coin's observed flip
frequency converge onto its true probability, grounded here in this demo's real falsification-gate
result instead of a toy.
| User | Item | Actual | Predicted | |error| |
|---|---|---|---|---|
| No draws yet -- click "Draw 1 pair" above. | ||||
If your running RMSE (green dot) lands left of the red dashed “threshold” line, this draw sample already confirms the model beats the popularity baseline — the exact bar the falsification gate had to clear.
↑ Back to the top — jump to any step, or explore the raw JSON API in the README.