AI Computer Institute
Expert-curated CS & AI curriculum aligned to CBSE standards. A bharath.ai initiative. About Us

The Mathematics of Recommendation Systems

📚 Machine Learning⏱️ 21 min read🎓 Grade 10
✍️ AI Computer Institute Editorial Team Updated: August 2026 CBSE-aligned · Peer-reviewed · 21 min read
Content curated by subject matter experts with IIT/NIT backgrounds. All chapters are fact-checked against official CBSE/NCERT syllabi.

Open YouTube on two different phones — yours and a friend's — and search nothing. The home screens will look almost nothing alike. Somewhere, a server looked at a giant table of numbers, did a handful of multiplications and one division, and decided what you, specifically, should see first. There is no human curator behind that screen. There is a formula. This chapter derives that formula from scratch, using nothing beyond vectors, the law of cosines, and one derivative rule you already know — and shows exactly where each piece breaks down in practice, and how engineers fix it.

Turning "Taste" Into a List of Numbers

Before any recommendation math can run, a person's taste has to become something a computer can compare: a vector. Suppose four users on a streaming app have rated four films — 3 Idiots, Interstellar, Zindagi Na Milegi Dobara (ZNMD), and Drishyam — on a scale of 0 to 5. Each user's row of ratings is a point in 4-dimensional space:

Ananya = (4, 2, 4, 2)
Kabir = (1, 0.5, 1, 0.5)
Zara = (2, 4, 2, 4)

Read Ananya's vector as an instruction: "rate 3 Idiots and ZNMD around 4, rate Interstellar and Drishyam around 2." That instruction — the pattern across the four numbers — is what we mean mathematically by "taste." A real streaming service does exactly this, except the vector has one coordinate per item in the catalogue: tens of thousands of dimensions instead of four. The arithmetic below works identically at that scale; we keep it at four so you can check every step by hand.

Deriving Cosine Similarity From the Law of Cosines

The central question a recommender must answer is: given two taste-vectors, how similar are they? The tempting first guess is Euclidean distance — treat the ratings as coordinates and measure the straight-line gap. We will show in the next section that this guess is wrong, and derive the fix properly.

Start from two facts you already know from Class 10–11 trigonometry and coordinate geometry:

Fact 1 (Law of cosines). For two vectors a and b with angle θ between them,

|a − b|² = |a|² + |b|² − 2|a||b|cos θ

Fact 2 (Dot product expansion). For any vectors, |a − b|² = (a − b)·(a − b) = a·a − 2(a·b) + b·b = |a|² + |b|² − 2(a·b).

Both expressions equal |a − b|², so set them equal to each other:

|a|² + |b|² − 2|a||b|cos θ = |a|² + |b|² − 2(a·b)

The |a|² and |b|² terms cancel from both sides, leaving −2|a||b|cos θ = −2(a·b). Divide both sides by −2|a||b|:

cos θ = (a·b) / (|a||b|)

This is the cosine similarity formula, and notice it was not asserted — it fell straight out of the law of cosines and the algebraic definition of the dot product. Here a·b = Σ aᵢbᵢ (multiply matching coordinates, add them up) and |a| = √(Σ aᵢ²) (the Pythagorean length of the vector, generalised to n dimensions). The result cos θ always lies in [−1, 1]; for rating vectors, whose entries are never negative, it lies in [0, 1]: 1 means the two vectors point in exactly the same direction (identical taste pattern), 0 means they are perpendicular (unrelated patterns).

Worked Example: Why "Closer Numbers" Is the Wrong Intuition

Compute cos θ for Ananya and Kabir using the formula just derived.

a·b = (4)(1) + (2)(0.5) + (4)(1) + (2)(0.5) = 4 + 1 + 4 + 1 = 10

|Ananya| = √(4² + 2² + 4² + 2²) = √(16+4+16+4) = √40 = 6.3246

|Kabir| = √(1² + 0.5² + 1² + 0.5²) = √(1+0.25+1+0.25) = √2.5 = 1.5811

cos θ = 10 / (6.3246 × 1.5811) = 10 / 10.0000 = 1.00

A perfect match. That makes sense once you notice Kabir's vector is exactly Ananya's vector scaled by 0.25 — he is simply a far more sparing rater (maybe he never gives 5-star reviews) who nonetheless prefers exactly the same films in exactly the same relative amounts. Now compute Ananya against Zara = (2, 4, 2, 4):

a·b = (4)(2) + (2)(4) + (4)(2) + (2)(4) = 8+8+8+8 = 32

|Zara| = √(4+16+4+16) = √40 = 6.3246

cos θ = 32 / (6.3246 × 6.3246) = 32/40 = 0.80

Zara's taste pattern is the mirror image of Ananya's — she rates Interstellar and Drishyam highly and 3 Idiots and ZNMD low, the reverse of Ananya's preference — so 0.80 correctly signals "less similar than Kabir, but not unrelated."

Now check what Euclidean distance would have told you. Distance from Ananya to Kabir: √((4−1)²+(2−0.5)²+(4−1)²+(2−0.5)²) = √(9+2.25+9+2.25) = √22.5 = 4.74. Distance from Ananya to Zara: √((4−2)²+(2−4)²+(4−2)²+(2−4)²) = √(4+4+4+4) = √16 = 4.00.

Common misconception, corrected: "the user with numerically closer ratings is more similar in taste." By raw distance, Zara (4.00) looks closer to Ananya than Kabir (4.74) does — the opposite of the truth. Euclidean distance is dominated by overall rating scale: Kabir's habit of rating everything low inflates his distance from Ananya even though his preference pattern is identical to hers, while Zara's coincidentally similar overall numbers mask a genuinely inverted taste. Cosine similarity ignores vector length entirely and measures only direction — which is precisely what "taste" means mathematically — and gets the ranking right: Kabir 1.00, Zara 0.80. This is exactly why every major collaborative-filtering system (the technique behind Amazon's "customers who bought this also bought," Spotify's Discover Weekly seed step, and Netflix's original recommendation engine) uses cosine similarity or a mean-centered variant of it, never raw Euclidean distance, to compare users.

The Vector Picture

3 Idiots rating → Interstellar rating → 0 1 2 3 4 θ = 36.87° Ananya (4, 2) Kabir (1, 0.5) Zara (2, 4) cosθ to Ananya Kabir: 1.00 (same ray) Zara: 0.80 length ignored, angle only

Kabir's vector sits exactly on the dashed ray through Ananya's vector — same direction, shorter length — which is the geometric picture of "same taste, harsher scale." Zara's vector sits 36.87° away, the same angle you meet in a classic 3-4-5 right triangle, where cos θ = 4/5 = 0.8. Only two of the four movies are plotted here because a page can't draw a 4-axis graph, but because the pattern is proportional across all four films in this constructed example, the two-movie angle happens to match the full four-movie cosine similarity exactly. With real, noisier data, using more shared items generally gives a more reliable similarity estimate than using fewer.

From Similarity to Prediction: User-Based Collaborative Filtering

Knowing who is similar to Ananya is only half the job — the system must also predict what she'd rate a film she hasn't seen, using her similar neighbours' ratings of it. The natural first guess is a similarity-weighted average:

r̂(Ananya, item) = Σᵥ sim(Ananya, v) · r(v, item) / Σᵥ sim(Ananya, v)

Suppose a new release, Pathaan, has been rated by Kabir (1) and Zara (4), and we already know sim(Ananya, Kabir) = 1.00, sim(Ananya, Zara) = 0.80. Plugging in:

r̂ = (1.00 × 1 + 0.80 × 4) / (1.00 + 0.80) = (1 + 3.2) / 1.8 = 4.2/1.8 = 2.33

This predicts Ananya will rate Pathaan a mediocre 2.33 out of 5. But look at what actually happened: Kabir's rating of "1" is above his own personal average of 0.75 — for a rater as sparing as him, 1 is practically a rave review. The naive formula doesn't know that; it just sees a small raw number and drags the prediction down. This is the same scale problem that broke Euclidean distance, resurfacing inside the prediction step.

The Fix: Mean-Centering

The repair is to stop asking "what did my neighbour rate this?" and instead ask "how did this rating compare to what my neighbour usually gives?" — then apply that same relative swing to the target user's own average. Let μᵥ denote neighbour v's mean rating and μᵤ the target user's mean rating:

r̂(u, item) = μᵤ + Σᵥ sim(u, v) · (r(v, item) − μᵥ) / Σᵥ |sim(u, v)|

Compute the means first: μ(Ananya) = (4+2+4+2)/4 = 3. μ(Kabir) = (1+0.5+1+0.5)/4 = 0.75. μ(Zara) = (2+4+2+4)/4 = 3.

Kabir's deviation on Pathaan: 1 − 0.75 = +0.25 (he rated it above his own norm). Zara's deviation: 4 − 3 = +1 (she also rated it above her norm). Now:

r̂ = 3 + (1.00 × 0.25 + 0.80 × 1) / (1.00 + 0.80) = 3 + (0.25 + 0.80)/1.8 = 3 + 1.05/1.8 = 3 + 0.583 = 3.58

A predicted 3.58, not 2.33 — a swing of more than a full point on a 5-point scale, purely from correcting for scale. Both of Ananya's neighbours liked Pathaan relative to their own habits, so the corrected model predicts she will too, appropriately weighted toward Kabir since he is her closer taste-match. This single correction — mean-centering before combining, then adding the target user's own mean back — is standard in every production collaborative-filtering system and is worth remembering as a formula in its own right for board-exam and applied-ML questions alike.

Content-Based Filtering: What to Do With No Neighbours

Collaborative filtering has an obvious weak point: a brand-new film with zero ratings has no rating vector to compare against anyone. Content-based filtering sidesteps this by building the vector from the item's own attributes instead of from user ratings. Represent each film as a vector of genre weights, say (Comedy, Drama, Romance, Sci-fi), each between 0 and 1:

3 Idiots = (0.8, 0.9, 0.2, 0.0)
Dangal = (0.1, 0.9, 0.0, 0.0)
Interstellar = (0.0, 0.4, 0.1, 1.0)

cos(3 Idiots, Dangal) = [(0.8)(0.1)+(0.9)(0.9)+(0.2)(0)+(0)(0)] / (|3 Idiots| × |Dangal|). Numerator = 0.08 + 0.81 = 0.89. |3 Idiots| = √(0.64+0.81+0.04) = √1.49 = 1.221. |Dangal| = √(0.01+0.81) = √0.82 = 0.906. cos θ = 0.89/(1.221×0.906) = 0.89/1.106 = 0.805 — high similarity, correctly flagging two character-driven Hindi dramas as alike despite different sub-genres.

cos(3 Idiots, Interstellar): numerator = (0.8)(0)+(0.9)(0.4)+(0.2)(0.1)+(0)(1) = 0.36+0.02 = 0.38. |Interstellar| = √(0+0.16+0.01+1) = √1.17 = 1.082. cos θ = 0.38/(1.221×1.082) = 0.38/1.321 = 0.288 — correctly low. A user's "taste profile" vector, in this scheme, is just the average of the feature vectors of everything they've rated highly, and new items get recommended the moment they're tagged with genres — no other user needs to have watched them first. Real systems (YouTube, Spotify, most e-commerce sites) run content-based and collaborative filtering together in a hybrid, precisely because each covers the other's blind spot: collaborative filtering captures taste patterns no genre tag could ever describe, content-based filtering handles items and users too new to have any rating history at all — the "cold-start problem."

Scaling Up: Matrix Factorization and Latent Factors

Genre tags are a human guess at what drives taste. A more powerful idea, and the one that won the 2009 Netflix Prize, is to let the data discover the underlying factors itself. Arrange every user's ratings into one big matrix R (rows = users, columns = movies), mostly empty because no one has rated everything. The goal is to find two much smaller matrices, P (users × k) and Q (movies × k), whose product approximates the known entries of R:

r(u, i) ≈ pᵤ · qᵢ

Here k is a small number of "latent factors" — the algorithm doesn't label them, but after training, one factor might end up loosely tracking something like "how much action" and another something like "how emotionally heavy," discovered purely from rating patterns rather than assigned by a human tagger. Each user gets a personal coordinate on every factor (pᵤ), each movie gets a coordinate too (qᵢ), and their dot product is the predicted rating — this is exactly the cosine-similarity dot product from earlier, repurposed to generate a rating rather than compare two existing vectors.

The Calculus Underneath: Fitting the Factors With Gradient Descent

P and Q start as random guesses and must be corrected using the known ratings. Define the squared error for one known rating as a function of a single latent factor value p (holding q fixed, the simplest case, k = 1):

L(p) = (r − pq)²

This is a composite function — an "outer" square applied to an "inner" linear expression — so differentiate with the chain rule. Let f = r − pq, so L = f². Then dL/dp = 2f · df/dp. Since r and q are held constant while differentiating with respect to p, df/dp = −q. Substituting:

dL/dp = 2(r − pq)(−q) = −2q(r − pq)

By identical reasoning, differentiating with respect to q instead: dL/dq = −2p(r − pq). Gradient descent moves each variable a small step opposite to its derivative (opposite, because the derivative points toward increasing loss, and we want to decrease it), scaled by a learning rate α:

p ← p − α · dL/dp = p + 2αq(r − pq)
q ← q − α · dL/dq = q + 2αp(r − pq)

Trace one concrete step. Suppose the true rating is r = 5, both factors start at the naive guess p = q = 1, and α = 0.05. Predicted rating = pq = 1. Error term (r − pq) = 4.

dL/dp = −2(1)(4) = −8, so p_new = 1 − 0.05(−8) = 1 + 0.4 = 1.4
dL/dq = −2(1)(4) = −8, so q_new = 1 − 0.05(−8) = 1 + 0.4 = 1.4

New predicted rating = 1.4 × 1.4 = 1.96 — up from 1, so the error has shrunk from 4 to 5 − 1.96 = 3.04 after a single step. Repeat this update across every known rating in the matrix, over many passes, and the error keeps shrinking (a regularization term, λ(p² + q²), is usually added to the loss to stop the factors from growing arbitrarily large and overfitting to noise — conceptually the same penalty idea you'll meet again in Class 12 optimization problems). This is genuinely the mechanism — gradient descent on a squared-error loss — that trained the winning Netflix Prize model and still underlies large-scale matrix-factorization recommenders today.

def cosine_similarity(u, v):
    dot = sum(u[i] * v[i] for i in range(len(u)))
    norm_u = sum(x ** 2 for x in u) ** 0.5
    norm_v = sum(x ** 2 for x in v) ** 0.5
    return dot / (norm_u * norm_v)

def predict_rating(user_mean, neighbours):
    # neighbours: list of (similarity, neighbour_mean, neighbour_rating)
    num = sum(sim * (rating - n_mean) for sim, n_mean, rating in neighbours)
    den = sum(abs(sim) for sim, n_mean, rating in neighbours)
    return user_mean + num / den

def sgd_step(r, p, q, alpha=0.05):
    error = r - p * q
    p_new = p + 2 * alpha * q * error
    q_new = q + 2 * alpha * p * error
    return p_new, q_new

Exam Connections

Every formula in this chapter sits directly on your Class 11–12 mathematics syllabus, which is why this topic shows up, in disguise, across competitive exams. Vector Algebra (dot product, magnitude, direction cosines) is exactly the machinery behind cosine similarity — JEE Main and BITSAT regularly ask you to find the angle between two vectors using cos θ = (a·b)/(|a||b|), which is the identical computation you just did for Ananya and Zara. The law-of-cosines derivation above is a good self-test: if you can reproduce it without looking, you've genuinely internalized vector algebra rather than memorized a formula. Matrices and Determinants underlie the P, Q factorization; and Limits, Continuity and Differentiability (Class 11–12) supply the chain rule used to derive the gradient descent update — a question phrased as "differentiate (r − pq)² with respect to p, treating q as constant" is a completely standard Class 12 differentiation exercise wearing a machine-learning costume. KVPY and olympiad-style problems often reward exactly this kind of "derive it, don't just quote it" approach, which is why the derivations here are worth re-doing from memory rather than just reading once.

Test Yourself

  1. Two users have rating vectors u = (5, 0, 5, 0) and v = (0, 5, 0, 5) over four movies. Compute cos θ between them using the derived formula, and explain in one sentence what a value of 0 means about their taste overlap.
  2. A third user w = (2.5, 0, 2.5, 0) joins. Without recomputing the dot product from scratch, predict what cos(u, w) will be, and explain why — using the "same ray" idea from the Ananya/Kabir example.
  3. For a target user with mean rating 4.0 and two neighbours — neighbour A (similarity 0.9, own mean 3.0, rated the target item 4.0) and neighbour B (similarity 0.3, own mean 4.5, rated the target item 5.0) — compute the mean-centered predicted rating. Show the deviation for each neighbour before combining.
  4. In the gradient descent step worked above, redo one more iteration starting from p = q = 1.4 (the values after step 1), with the same r = 5 and α = 0.05, and report the new predicted rating and error.
  5. Explain, using one sentence tied to the matrix-factorization section, why a movie released yesterday with zero ratings cannot get a useful collaborative-filtering prediction, and name the technique from this chapter that can still recommend it.

Summary

Recommendation math starts by turning each user's ratings into a vector, then measures taste-similarity not by raw distance but by the angle between vectors — a formula, cos θ = (a·b)/(|a||b|), derived directly from the law of cosines rather than handed down. That angle-only view is what correctly identifies a sparing rater as a taste-twin even when a generous rater with an accidentally similar rating scale looks numerically closer. Turning similarity into an actual predicted rating requires one further correction — mean-centering — because raw weighted averages inherit the same scale distortion that broke Euclidean distance in the first place. Content-based filtering, using item feature vectors instead of rating vectors, plugs the gap collaborative filtering leaves for brand-new items and users. And matrix factorization, trained by gradient descent on a squared-error loss using nothing more exotic than the chain rule, lets a system discover the hidden factors driving taste directly from data rather than from hand-picked genre tags — the same core technique, scaled up, that decides what a billion people see first when they open an app.

Think About It

Think about this: How would you explain the mathematics of recommendation systems to a friend who has never seen a computer? What real-world analogy would you use? Imagine you had to build a system using these concepts — what would be your first step? Try this: before moving on, write down three things you learned and one question you still have.

← Kernel Methods: Transforming Feature SpacesBayesian Inference: Updating Beliefs with Evidence →

Found this useful? Share it!

📱 WhatsApp 🐦 Twitter 💼 LinkedIn