The maths of machine learning
The mathematics under machine learning, hands on — least squares with draggable points (residual squares, outliers, L1 vs L2, normal equations vs gradient descent and SGD), logistic regression and its cross-entropy bowl, a computation graph with forward and backward passes against dual numbers and finite differences, TF-IDF and BM25 search, entropy with a Huffman tree builder and KL divergence, and softmax temperature with an attention matrix.
Added · updated 14 October 2026
How to use it
Six tabs, each one idea from the book you can push around. Every setting can be put in a link, and every book example has a preset — see Linking to an example.
⛶ Full screen (or F) gives the open tab’s main picture — the draggable least-squares plot, the
sigmoid, the computation graph, the Huffman tree or the temperature chart — the whole screen, the
browser’s full screen where it is allowed, otherwise a full-window layer (iPhone); it is redrawn
as the window changes, and the controls stay below it. Escape leaves.
Least squares
Drag the points (or focus one and use the arrow keys). The line, the red residuals and their squares — whose total area is the SSE — update as you drag. Squared error fits by the normal equations, shown with the four sums Σx, Σy, Σx², Σxy and the solve; absolute error fits by iteratively reweighted least squares, with the squared-error line dashed for comparison. Make an outlier (or drag one point far away) shows squared error chasing it while absolute error barely moves. The points slider goes from 2 to 20; the first five are the book’s study-hours data.
Underneath, gradient descent walks downhill on the MSE from θ = 0 over a contour picture of the loss in (b, w), with the excess loss per step on a log scale and the book’s table of steps 0, 10, 100, 1000 and 2000 next to the normal-equations answer. Raise η until it diverges. SGD runs mini-batch stochastic gradient descent on 1000 noisy points from y = 3x + 2 (batch size, epochs and η are sliders) and shows how it jitters around the exact answer.
Logistic regression
The book’s ten students (hours studied, passed or not) and the curve σ(wx + b), with sliders for
w and b, the live cross-entropy and its gradient, the decision boundary −b/w, and the predicted
pass probabilities. The second panel is the cross-entropy over (w, b) as a contour picture with a
dot for the current setting; click to move it. Train runs gradient descent from the dot and
draws its path down the convex bowl. Edit the data as hours,passed pairs.
Backpropagation and dual numbers
Build a computation graph either from an expression (sin(x*x), exp(2*x)/(1+x*x) — parsed by
the site’s algebra parser) or step by step, one node per line: z = mul(w, x). The palette
buttons append a node (+, ×, −, ÷, x², sin, exp, tanh, σ, ReLU, ln) fed by the current output.
Names that are never defined are inputs; give them values below.
Forward ▶ animates the values flowing through the graph; ◀ Backward starts from 1 at the output and multiplies by the local derivative written on each edge, adding the contributions at nodes that feed several others — the result at each node is ∂output/∂node. Nodes can be dragged. The panels compare the reverse-mode gradient with forward-mode dual numbers (the table lists every node’s a + bε) and with a central finite difference.
Finding the sweet spot plots the error of forward and central differences against the step h on
log–log axes for the graph’s output, with the theoretical best h (√ε and ∛ε) marked. Switch to
32-bit floats — every operation rounded to single precision — and the sweet spot moves to much
larger h. Use f=sin(x), exp(x), x^3 or sqrt(x) near 0, as in the book’s lab.
TF-IDF and BM25
Type documents (one per line) and a query. The tool shows the vocabulary with document frequencies and idf = ln(N/df), the TF-IDF vectors as a table, and every document’s dot product, cosine and BM25 score, ranked by the one you choose. Raw counts turns off the idf weighting (the length-bias example). Stemming is a light suffix stripper (plurals, -ing, -ed), enough for “cats” to match “cat”. For BM25, move k₁ (term saturation) and b (length normalisation); the idf is the book’s ln(N/df) by default, or Lucene’s smoothed version.
Entropy and Huffman codes
Enter symbol probabilities (A:1/2,B:1/4,…) or paste text and count its letters. The tool gives
the entropy, the Huffman code with each codeword’s length beside its surprise −log₂p, the average
length against H, and a slider that builds the Huffman tree one merge at a time. Enter a wrong
distribution q to build the code for q and pay for it with p: the cross-entropy H(p, q), D_KL in
both directions, and the extra bits per symbol — exactly D_KL(p‖q) when the probabilities are
powers of ½.
Softmax and attention
Scores (logits) and a temperature T: the softmax as bars, its entropy, how the probabilities move as T goes from 0.05 to 20, and what the naive formula does with scores like 1000 (it overflows; subtracting the maximum does not). Below, a tiny attention layer: tokens and the matrices Q, K and V, with the score matrix QKᵀ/√d_k, the row-wise softmax as a heat map, and the output rows as weighted averages of V. Untick √d_k to see the softmax saturate. Tick causal mask to see a decoder’s attention: every score above the diagonal becomes −∞, so a token gives zero weight to the tokens after it.
The sampling T buttons set the temperature to the usual sampling settings (greedy, 0.2, 0.7, 1, 1.5); the readout says what greedy decoding would pick and how often sampling picks it.
Heads sharing keys and values shows multi-head (MHA), grouped-query (GQA) and multi-query (MQA) attention: the query heads in coloured groups, each group reading one K/V head, and what that does to the KV cache — 2 × layers × KV heads × head dimension × bytes per token, for a context length you choose. Llama 3 70B (64 query heads, 8 KV heads, head dimension 128, 80 layers, FP16) keeps 327,680 bytes = 0.3125 MiB per token, 8× less than without sharing.
Limits
-
Least squares fits a straight line in one variable; for polynomial and other fits, R² and residual plots on your own data use the Statistics tool.
-
Graph expressions use single-letter variables;
eis Euler’s number andpiis π. In the step form, names may be longer. Operations: add, sub, mul, div, pow, neg, sq, sin, cos, tan, exp, ln, log (base 10), sqrt, tanh, sigmoid, relu, abs. -
The book’s SGD data come from NumPy’s random generator, which this page does not reproduce: its 1000 points are different, so its SGD estimate is close to, not equal to, the book’s 3.11 and 1.93. Everything else matches the book’s printed numbers.
-
The dual-number derivative of exp(2x)/(1 + x²) at 0.5 can differ from the book’s 2.609550555320683 in the last digit: the quotient rule is evaluated in a different order.
-
Stemming here is deliberately simple; real search engines use Porter-style stemmers or lemmatisers.
Related: Neural network designer (build and train whole networks), Matrix calculator (XᵀX θ = Xᵀy and other systems), Statistics (regression on your data, distributions, tests), Eigenvectors at work (PCA, SVD, LSI), and AI hardware calculator (the KV cache against GPU memory).
Companion to Mathematics, Reconnected: How computers compute derivatives (chapter 17), Vectors (chapter 26, TF-IDF and cosine similarity), Statistics and Inference (chapter 31, simple linear regression), and Horizons: Optimisation, Machine Learning, and Information (chapter 33): linear regression, logistic regression, backpropagation, search, information theory and softmax and attention.
Companion to Part IX of AI Acceleration: From Transistors to Trillion-Parameter Models: what self-attention actually computes (the attention equation, GQA and MQA) and decode (a softmax over the vocabulary, then sample the next token).
Linking to an example
A link opens the tool with the given settings: /tools/ml-maths/?<parameters>#<tab>, where the
tab is regression, logistic, autodiff, search, info or softmax. Share link (top
right) builds one from whatever is on screen. Points are x,y pairs separated by semicolons;
documents are separated by |. A ` typed straight into a link reaches the page as a space: in
`f=` a space between two terms is turned back into `, so ?f=x^3+2*x works; elsewhere write
%2B, or leave the + out.
| Parameter | Meaning | Example |
|---|---|---|
|
a book preset (list below); other parameters in the same link override it |
|
|
points for least squares |
|
|
|
|
|
|
|
|
learning rate η for gradient descent or SGD |
|
|
gradient-descent steps |
|
|
SGD batch size |
|
|
SGD epochs |
|
|
logistic data as |
|
|
logistic weight |
|
|
logistic bias |
|
|
logistic learning rate |
|
|
expression for the computation graph (overrides |
|
|
graph steps |
|
|
input values |
|
|
input for dual numbers and finite differences |
|
|
log₁₀ of the finite-difference step h |
|
|
|
|
|
documents separated by |
|
|
search query |
|
|
ranking: |
|
|
|
|
|
BM25 k₁ |
|
|
BM25 b |
|
|
stemming on ( |
|
|
BM25 idf: |
|
|
probabilities, |
|
|
the wrong distribution q |
|
|
|
|
|
text whose letters are counted |
|
|
Huffman merges shown |
|
|
softmax scores |
|
|
temperature |
|
|
attention tokens |
|
|
attention matrices, rows separated by |
|
|
divide scores by √d_k ( |
|
|
causal mask on the attention matrix ( |
|
|
query heads and key/value heads ( |
|
|
head dimension and number of layers |
|
|
bytes per cached value ( |
|
|
context length in tokens for the cache total |
|
Presets for example=:
| Name | Tab | Shows |
|---|---|---|
|
regression |
Hours studied against score: ŷ = 2.2 + 0.6x by the normal equations, SSE 2.4 |
|
regression |
Gradient descent from θ = 0 with η = 0.05 and the book’s table of steps |
|
regression |
Mini-batch SGD on 1000 noisy points from y = 3x + 2 |
|
regression |
The lab: twelve points to drag, with residual squares and the SSE |
|
regression |
One point far away, fitted with absolute error (squared-error line dashed) |
|
regression |
Response time against load: ŷ = 46 + 4x, R² = 0.959 |
|
logistic |
The lab: pass/fail data from w = b = 0; press Train |
|
logistic |
The fitted model w = 1.353, b = −3.721: boundary 2.75 hours |
|
autodiff |
The one-weight network tanh(wx) with target 0.5: dL/dw = 0.1055 |
|
autodiff |
One sigmoid neuron: dL/dw = −0.5, dL/db = −0.25 |
|
autodiff |
The exercise x = 1, y = 0, w = 1, b = 0: dL/dw ≈ 0.2875 |
|
autodiff |
Dual numbers: x³ + 2x at 2 gives 14 |
|
autodiff |
sin(x²) at 1.5: −1.8845208681682175 |
|
autodiff |
exp(2x)/(1 + x²) at 0.5: 2.60955055532068 |
|
autodiff |
Forward and central differences of sin at 1 against h |
|
autodiff |
The same in 32-bit floats |
|
search |
“cat on mat”: q·d 2.578, 0.164, 0 and cosines 0.871, 0.056, 0 |
|
search |
The same with stemming: “cats” now counts as “cat” |
|
search |
BM25 with k₁ = 1.2 and b = 0.75 |
|
search |
“vector arrow”: cosines 0.078, 0.000, 0.421 |
|
search |
Raw counts: dot products 20, 2, 2 against cosines 1, 0.707, 1 |
|
info |
The skewed four-symbol source: H = 1.75 bits, code 0, 10, 110, 111 |
|
info |
The code built for uniform q costs 2 bits = 1.75 + D_KL 0.25 |
|
info |
Biased against fair coin: D(biased‖fair) = 0.531, D(fair‖biased) = 0.737 |
|
softmax |
softmax(2, 1, 0.1) = 0.659, 0.242, 0.099 |
|
softmax |
(1000, 999, 998.1): the naive formula overflows, the stable one does not |
|
softmax |
Attention weights and outputs for four tokens |
From AI Acceleration (Part IX):
| Name | Tab | Shows |
|---|---|---|
|
softmax |
softmax(QKᵀ/√d_k)V: every token attending to every token |
|
softmax |
The same with the causal mask: weights above the diagonal are 0 |
|
softmax |
GQA in Llama 3 70B: 64 query heads share 8 KV heads; 320 KiB (0.3125 MiB) per token, 2.5 GiB at 8K tokens |
|
softmax |
The same cache at 128K tokens: 40 GiB (42.9 GB) for one sequence |
|
softmax |
Without sharing (64 KV heads): 8× the cache |
|
softmax |
MQA: one KV head for all 64 query heads |
|
softmax |
Temperature 0.05 on five next-token logits (3, 2.5, 1.5, 0.5, −1): effectively greedy |
|
softmax |
T = 0.2: the top token 92 % of the time |
|
softmax |
T = 0.7: 61 % |
|
softmax |
T = 1, the model’s own distribution: 52 % |
|
softmax |
T = 1.5: 43 %, with more surprising picks |
For example, https://geekychris.github.io/tools/ml-maths/?example=ch17-backprop#autodiff opens the book’s backpropagation example, and https://geekychris.github.io/tools/ml-maths/?f=x^3+2*x&at=x=2#autodiff builds the graph of x³ + 2x at x = 2.
Feedback is a gift. Something to improve, a feature to add, or a bug? Tell me.
Runs entirely in your browser; nothing you type leaves this page.