Math Relearn/ Core tools/ Module 01

Mathematical thinking & notation

Notation is a compression language, not a ritual. Fifty minutes to install a reading method β€” objects, shapes, sums, direction of good, home in code β€” that every later module and every ML paper assumes you have.

On this page
    Track 1 Β· Core tools

    01 Β· Mathematical thinking & notation

    ⏱ 50 minπŸ“Ž NumPy🎯 Read any formula in an ML paper without fear.

    You have spent years moving symbols around a page without ever reading them. That skill got you through exams and left you with nothing you could reuse: a formula you can manipulate but cannot read aloud as a sentence is a string, not knowledge. This module replaces the manipulation habit with a reading method β€” five questions, asked in the same order, of every formula you meet from here on.

    By the end you can

    • Read a formula aloud as an English sentence, naming what each symbol does.
    • State the standard letter conventions ($x$, $y$, $\theta$, $n$, $d$, $i$, $j$) without looking them up.
    • Write the shape next to every symbol and predict the shape of any expression before coding it.
    • Expand $\sum_i$, $\prod_i$, $\mathbb{1}[\cdot]$ and $\arg\min$ into plain words.
    • Explain what a parameterised family $f(x;\theta)$ is, and why learning is impossible without one.
    • Show that the Gaussian log-likelihood and mean squared error are the same objective, up to constants.

    Why this module exists

    Every formula in machine learning is a compressed paragraph. $\hat{\theta} = \arg\min_\theta \frac{1}{n}\sum_i L(f(x_i;\theta), y_i) + \lambda\Omega(\theta)$ is about two hundred words of prose squeezed into one line, and the compression only works if both sides speak the same language. When you cannot read it, you do what you did at university: memorise the shape, pattern-match to a known problem type, execute. That works on an exam paper. It fails the moment a paper changes one symbol β€” which they all do.

    The second reason is engineering. Most implementation bugs are not logic bugs, they are reading bugs: a transpose that was not there, a sum over features mistaken for a sum over samples, an $\arg\min$ treated as if it returned a number. Each of those is a symbol that was moved but never read. So this module is short on purpose. It teaches no new mathematics β€” it teaches you to read the mathematics you are about to meet, and it is the only module whose content you will reuse in every single one that follows.

    Pass 1

    Remember β€” retrieve before you read

    Six questions, five minutes, no notes

    Cold warm-up: answer these before scrolling

    You learned all of this before, and you half-remember some of it. That is the point. Write a short answer to each β€” a word, a shape, a number. If you blank on one, mark it and move on; the answers are in the recall cards underneath, but only after your own attempt is on paper.

    1. What is a function, in one sentence? What does the notation $f:\mathbb{R}^{d}\to\mathbb{R}$ promise?
    2. What does $f(x;\theta)$ add over $f(x)$?
    3. Expand and interpret $\frac{1}{3}\sum_{i=1}^{3} i$. What number comes out?
    4. You have 500 customers with 12 features each. What shape is the data matrix $X$?
    5. What does $\arg\min$ return β€” a number, or something else?
    6. What is the derivative of $x^2$ at $x = 3$? (Half-remembering is fine β€” write what you've got.)
    1. What is a function? What does $f:\mathbb{R}^{d}\to\mathbb{R}$ promise?
    A rule that assigns every input exactly one output. Two promises are baked into the arrow: every legal input gets an answer (no gaps), and each input gets only one answer (no ambiguity). $f:\mathbb{R}^{d}\to\mathbb{R}$ therefore says: hand me $d$ real numbers β€” one data point β€” and I hand you back a single real number. If $f$ is a model, that single number is the prediction: a price, a score, a logit.
    2. What does $f(x;\theta)$ add over $f(x)$?
    A set of knobs, and with them, something to learn. Plain $f(x)$ is one fixed rule β€” it never changes, so there is nothing to train. $f(x;\theta)$ is a whole family of functions: every setting of $\theta$ picks a different member. Machine learning is exactly the act of choosing $\theta$ from data. No $\theta$, no learning β€” you would just be calling a fixed function.
    3. Expand and interpret $\frac{1}{3}\sum_{i=1}^{3} i$
    The sum means "add up"; the $\frac{1}{3}$ means "then average". $\sum_{i=1}^{3} i = 1 + 2 + 3 = 6$, and $\frac{1}{3}\times 6 = 2$. So the expression reads: the average of 1, 2 and 3 is 2. Notice the index $i$ never appears in the answer β€” it is a bookkeeping label, not a variable with a value you are solving for.
    4. Shape of $X$ for 500 customers with 12 features
    $X \in \mathbb{R}^{500 \times 12}$ β€” 500 rows, 12 columns. Convention: rows are samples, columns are features. Each row is one customer as a 12-dimensional point; each column is one feature across all customers. This matters more than it looks: the moment you transpose, "sum over samples" and "sum over features" swap places, and almost every silent bug in ML code starts there.
    5. What does $\arg\min$ return?
    The argument β€” the input, the setting β€” not the value. $\arg\min_\theta J(\theta)$ answers "which $\theta$ makes $J$ smallest?", and its output is a $\theta$ (a vector of weights, a set of parameters). $\min_\theta J(\theta)$ answers "how small does $J$ get?", and its output is a number. $\arg\min$ of a list of losses gives you an index; $\min$ of that list gives you the loss. Confusing the two is why people print a loss where they meant to save weights.
    6. Derivative of $x^2$ at $x = 3$
    6. The rule is $\frac{d}{dx}x^2 = 2x$, and $2 \times 3 = 6$. Read it as sensitivity: at $x=3$, nudging the input by $+0.01$ moves the output by about $+0.06$. If you only half-remembered the rule, you can still get there with the difference quotient: $\frac{3.01^2 - 3^2}{0.01} = \frac{9.0601-9}{0.01} = 6.01$, which is 6 plus a rounding error. That computation is the whole of Section 6 β€” and it is all of Module 03 needs to start from.
    Pass 2

    Understand β€” the shape of the idea

    Nine sections: why notation, what the letters mean, and how to read a formula

    Why notation exists at all

    Notation is a technology, and like every technology it exists because something was hard before it. Before symbols, algebra was written out in words β€” the rhetoric of quantities β€” and every calculation had to be held in your head while you read the sentence describing it. Writing $\sum_{i=1}^{n}$ instead of "add up the terms from the first to the $n$-th" moves the bookkeeping out of your working memory and onto the page. That is the entire job: notation buys you working memory.

    Which gives you a clean test for whether you actually know a symbol. Can you read it aloud as a sentence? $\frac{1}{n}\sum_{i=1}^{n} L(f(x_i;\theta), y_i)$ says "the average, over all $n$ training examples, of how wrong the model's prediction is for each one." If that sentence comes out easily, the symbol is yours. If you can only say "it's the loss function thing", you have the shape but not the meaning β€” you can manipulate it, and you cannot read it. The first is exam skill; the second is the thing that survives.

    The symbols were designed by people who thought about this hard. Leibniz's $\frac{d}{dx}$ is the famous case: it literally spells out the operation (divide the differential of the top by the differential of the bottom), so you can see how the chain rule must behave before you prove it: the chain rule $\frac{dy}{dx} = \frac{dy}{du}\frac{du}{dx}$ cancels like a fraction. Newton's notation for the same derivative could not do that. A century later, matrix notation let someone write an entire regression model on one line. Every symbol you meet was chosen to make one specific thought cheaper.

    Leibniz vs Newton, and why the winner won

    Newton wrote derivatives as $\dot{y}$ (a dot over the variable); Leibniz wrote $\frac{dy}{dx}$. Newton's is compact for mechanics, where you differentiate the same one or two quantities with respect to time over and over. Leibniz's is better for everything else, because it names both the output and the input β€” and because it looks like a fraction, which is exactly how the chain rule behaves. Leibniz won the notation war, which is why 300 years later backpropagation reads as fractions cancelling. Notation is not neutral decoration: pick a bad one and the hard steps stay hard.

    Notation is a compression language, not a ritual: if you cannot read a formula aloud as a sentence, you are only moving symbols around.

    The cast of characters: what the letters mean

    Four kinds of object, and then a set of letters that mean the same thing nearly everywhere in ML. Learn the letters once and an unfamiliar paper becomes mostly familiar: you will not know what the paper invented, but you will know what it did not have to explain.

    scalarone number β†’ vectora column / a data point β†’ matrixa grid, or a transformation β†’ tensorany number of axes
    SymbolRead it asTypical shapeWhere it lives
    $x$one input, one data point$\in \mathbb{R}^{d}$X[i]
    $y$the target β€” what we are trying to predictscalar, or a class labely[i]
    $X$the whole training set$\in \mathbb{R}^{n \times d}$X
    $\theta$ or $w$the parameters β€” the knobs being learned$\in \mathbb{R}^{p}$model.coef_
    $n$how many training samplesscalarX.shape[0]
    $d$how many featuresscalarX.shape[1]
    $i$sample index, runs over $1 \dots n$scalarthe outer loop
    $j$feature index, runs over $1 \dots d$scalarthe inner loop
    $f(\cdot)$the model β€” a rule from inputs to predictionsa functionmodel.predict
    $L$ or $\mathcal{L}$loss β€” how wrong one prediction isscalarloss(y, yhat)
    $\eta$learning rate β€” how big a step to takesmall positive scalarlr=
    $\lambda$regularisation strength β€” the dial between fit and simplicitynon-negative scalaralpha= / C=

    The single most useful habit in this whole module is shape discipline: never write a symbol without writing where it lives. Not "$X$ times $w$" but "$X \in \mathbb{R}^{n \times d}$ times $w \in \mathbb{R}^{d}$, giving $Xw \in \mathbb{R}^{n}$".

    $$X \in \mathbb{R}^{n \times d},\qquad w \in \mathbb{R}^{d},\qquad Xw \in \mathbb{R}^{n}$$ the dataset times the weights gives one number per sample β€” n scores, n predictions
    Shape-checking catches most bugs before they run

    Write the shape of every intermediate on a piece of paper and the arithmetic mostly checks itself: $(n \times d) \times (d)$ β€” the inner $d$'s match, they cancel, and you are left with $n$. When they do not match, you have found the bug without executing anything. In practice this settles transposes, "sum over samples vs sum over features", broadcasting surprises, and the classic "$Xw$ came out as length $d$ instead of length $n$" β€” which is really a wrong mental picture of what the model is computing. Habit: write shapes in comments on every line that creates an array.

    Sets, spaces and quantifiers

    A small alphabet of logic that shows up in every paper, and that exists so claims can be short instead of hedged. This is a reading tool, not a set theory course β€” you need to recognise the symbols, not prove anything with them.

    SymbolRead it asExample claim
    $\mathbb{R}$the set of all real numbers β€” one axis$x \in \mathbb{R}$ means "$x$ is a single number"
    $\mathbb{R}^{d}$all lists of $d$ reals β€” a $d$-dimensional space$x \in \mathbb{R}^{d}$ means "$x$ has $d$ coordinates"
    $\in$"is an element of" / "lives in"$w \in \mathbb{R}^{d}$ β€” the weights live in feature space
    $\subseteq$"is a subset of" / "contained in"a validation set $\subseteq$ the full dataset
    $\forall$"for all" β€” no exceptions$\forall x$: the rule holds everywhere
    $\exists$"there exists" β€” at least one$\exists\, w$ such that the training error is 0
    $\{1,\dots,n\}$the index set β€” the labels you sum over$i \in \{1,\dots,n\}$ means $i$ counts samples

    Put together, the standard claim about a data set reads like this β€” every sample is a $d$-vector, and stacked they give the matrix:

    $$\forall\, i \in \{1,\dots,n\}, \qquad x_i \in \mathbb{R}^{d}, \qquad X \in \mathbb{R}^{n \times d}$$ "for every sample i, that sample is a d-vector; and all of them stacked give the n by d matrix"

    The point worth internalising: $x \in \mathbb{R}^{d}$ is a complete claim about a data point. From it you know how many numbers are in $x$, that they are finite reals, that $x$ is a point in a $d$-dimensional space (so "distance", "direction" and "angle" between data points are even meaningful), and that the only legal partners for it are other $d$-vectors β€” $x + y$ only makes sense if $y \in \mathbb{R}^{d}$ too. Nothing more is claimed: not that the coordinates are normalised, not that they are independent, not that they are in any particular order. Papers state exactly this much, and reading it as exactly this much is the skill.

    "$\forall$" and "$\exists$" are cheap words to get backwards

    $\forall$ is a strong claim β€” one counterexample kills it β€” while $\exists$ is weak: one example proves it. That asymmetry is why papers write "$\exists$ a setting of $\theta$ with zero training error" (easy, you can always interpolate) but "$\forall$ distributions $P$" (essentially impossible to guarantee). When you skim, both look like "for something / for everything". Slow down on them: one is a bulletproof statement, the other is barely a hint.

    Sums, products and the shape of an average

    Almost every ML formula is a sum wearing different clothes. Learn to expand one and the rest decode themselves. Take the variance numerator and read it as a sentence first: "add up, for every data point, how far that point sits from the mean, squared."

    $$\sum_{i=1}^{n}(x_i-\bar{x})^2 = (x_1-\bar{x})^2 + (x_2-\bar{x})^2 + \cdots + (x_n-\bar{x})^2$$ the sigma is an instruction, not a symbol: substitute i = 1, then i = 2, … then add

    Three things to notice about that expansion. The index $i$ is bound β€” it only exists inside the sum and vanishes in the answer, exactly like a loop variable. The upper limit $n$ tells you how many terms, which is a shape statement ($n$ terms from a dataset of $n$ samples). And the $\frac{1}{n}$ that usually sits in front is what turns "total" into "average" β€” the most common single symbol in ML objectives.

    The workhorse pattern, which you will see in every single model: an ML objective is an average over samples. The loss $L$ judges one pair of prediction and truth; the sum collects all the judgements; the $\frac{1}{n}$ makes the result independent of how much data you happened to train on.

    $$\frac{1}{n}\sum_{i=1}^{n} L\big(f(x_i;\theta),\, y_i\big) \qquad \text{average loss over the training set}$$ "how wrong is this model, on average, across the n examples we have?"

    $\prod_{i=1}^{n}$ is the same idea with multiplication instead of addition β€” the probability of all $n$ independent outcomes happening, $\prod_i p(y_i)$. Products are why we take logarithms: a log turns that product into the sum $\sum_i \log p(y_i)$, which is nicer to differentiate and far nicer in floating point (a million small probabilities multiplied together underflow to zero; their logs merely add up).

    Double sums $\sum_i \sum_j$ appear whenever two indices are needed β€” pairwise quantities over samples or features. The covariance between feature $j$ and feature $k$ is the archetype: for each sample $i$, take how far feature $j$ sits from its mean, multiply by how far feature $k$ sits from its mean, then add that up across all samples and average.

    $$\Sigma_{jk} = \frac{1}{n}\sum_{i=1}^{n}\big(X_{ij}-\bar{X}_j\big)\big(X_{ik}-\bar{X}_k\big)$$ i runs over samples (outer), j and k run over features β€” the ordering is the whole point

    Two more symbols you will meet constantly. $\max$ and $\min$ with an index ask which element, not how big β€” that is $\arg\max$ again, and it is how a classifier turns probabilities into a predicted class. And the indicator $\mathbb{1}[\cdot]$ is an on/off switch that returns 1 when the condition inside is true and 0 when it is false; multiplying by it means "only count the cases where…".

    $$\hat{y}_i = \arg\max_{k \in \{1,\dots,K\}} \; p(y = k \mid x_i) \qquad \text{β€œthe class with the biggest probability”}$$ the answer is a class label k β€” an index β€” not the probability itself
    Read every $\sum$ as a for-loop and every $\frac{1}{n}$ as "make it an average": that translation is 80% of reading an ML objective.

    Functions, parameters and families

    A function with a declared domain and codomain tells you its whole contract: what it eats, what it returns.

    $$f:\mathbb{R}^{d}\to\mathbb{R}$$ "f takes one data point (d numbers) and returns one number" β€” a model that scores, not classifies yet

    Now the idea that makes machine learning possible at all. If $f$ is fixed, there is nothing to learn β€” you would just be calling a function. So we do not study one function; we study a parameterised family: $f(x;\theta)$ where the input $x$ is the data and $\theta$ is a separate slot that selects one member of the family. For linear regression the family is "all straight lines", and $\theta = (w, b)$ picks which one. Training is the search over $\theta$; the model you ship is the winning member.

    $f(x;\theta)$ is not $f$ times $\theta$

    The semicolon is doing deliberate work: everything before it is the data (changes per example, never optimised), everything after it is the parameters (fixed during a forward pass, changed only by the optimiser). Writing $f(x, \theta)$ with a comma is common and harmless; reading $f(x;\theta)$ as multiplication is not β€” it turns a lookup into an arithmetic operation and makes the whole of gradient descent inexplicable. Data: given. Parameters: chosen. That split is the entire contract.

    Functions combine. The composition $(f \circ g)(x) = f\big(g(x)\big)$ means "run $g$, then feed its output into $f$". A neural network is nothing but a long composition β€” one layer's output is the next layer's input β€” and writing it as $\circ$ is what lets you talk about a 100-layer model without writing 100 formulas.

    Linearity: the test, not the appearance

    A function is linear exactly when it satisfies the following, for all scalars $\alpha, \beta$ and all inputs $x, z$:

    $$f(\alpha x + \beta z) = \alpha f(x) + \beta f(z) \qquad \text{for all } \alpha,\beta \in \mathbb{R} \text{ and all } x,z$$ "scaling inputs before the function = scaling the output; adding inputs before = adding outputs"

    Test both candidates from the warm-up. Take $f(x) = x^2$ with $\alpha = \beta = 1$: the left side is $(x+z)^2 = x^2 + 2xz + z^2$, the right side is $x^2 + z^2$. They differ by $2xz$, so $x^2$ is not linear β€” the cross term is exactly what breaks it. Now take $f(x) = wx + b$ with $\alpha = \beta = 1$: the left side is $w(x+z) + b$, the right side is $(wx+b) + (zx+b) = wx + zx + 2b$. They differ by $b$, so $wx+b$ is not linear either β€” unless $b = 0$. In ML it is common to call $wx+b$ "linear" (it is affine: linear in the parameters, straight line on paper) and to reserve the word for the rule above.

    That distinction explains the architecture of every model you will meet. Lines and planes are linear and well-behaved but cannot represent a curve, a threshold or an XOR. So models are built as linear parts + non-linear glue: linear layers do the mixing, a non-linearity ($\mathrm{ReLU}$, $\sigma$, $\tanh$) between them provides the bends, and the composition of many linear-plus-non-linear pieces can approximate anything. Drop the glue and a deep network collapses into one flat line β€” which is a theorem you will meet again in Modules 08 and 10.

    Put it together and you get the equation that every model in this notebook is an instance of. Read it aloud before you look at the table: "the best parameters are the ones that make the average training loss smallest, plus a penalty term for complicated parameters."

    $$\hat{\theta} = \arg\min_{\theta} \; \frac{1}{n}\sum_{i=1}^{n} L\big(f(x_i;\theta),\, y_i\big) \;+\; \lambda\,\Omega(\theta)$$ find the parameters ΞΈ that make the model's predictions least wrong, plus a penalty that keeps them sane
    PieceRead it aloud asThe line of code it becomes
    $\hat{\theta}$"the winning parameters" β€” the thing you savemodel.coef_, torch.save(state_dict)
    $\arg\min_{\theta}$"which setting of $\theta$ makes the rest smallest"the optimiser: opt.step()
    $\frac{1}{n}\sum_{i=1}^{n}$"average over the $n$ training samples"np.mean(...)
    $f(x_i;\theta)$"the model's prediction for sample $i$"X @ w, model.predict(X)
    $y_i$"the truth for sample $i$"y[i]
    $L(\hat{y}, y)$"the penalty for one wrong prediction"(yhat - y)**2
    $+\,\lambda\Omega(\theta)$"plus a fee for parameters that are too large or too complex"+ lam * np.sum(w**2)

    $\lambda$ is a dial, not a mystery: $\lambda = 0$ means "fit the data, whatever it takes" and large $\lambda$ means "prefer simple parameters even if the fit gets worse". $\Omega$ is the definition of "simple" β€” squared weights for ridge and most neural nets, tree count for forests, sparsity for lasso. Every regularisation method is choosing an $\Omega$.

    Rates of change, previewed

    One section, no theory β€” just enough to show that "how sensitive is the output to a nudge in the input" is a number you can compute today, with no calculus. Shrink the step $h$, divide the change in output by the change in input.

    $$\frac{f(x+h)-f(x)}{h} = \frac{f(3.01)-f(3)}{0.01} = \frac{9.0601-9}{0.01} = 6.01$$ on f(x) = xΒ² at x = 3: a +0.01 nudge moves the output by ~0.06, so sensitivity β‰ˆ 6

    The exact derivative of $x^2$ at $3$ is $6$, and the finite difference gives $6.01$ β€” the gap is the price of using a step of $0.01$ instead of $0$. Halve $h$ and you will land around $6.005$. That convergence is the derivative, and it is also how you will check your hand-written gradients against automatic differentiation in Module 03: compute the finite difference, compute the analytic gradient, and confirm they agree to a few decimals. Sensitivity is not mysterious β€” it is one division away from something you already know how to write.

    Where this shows up immediately

    Gradient descent needs $\nabla_\theta L$ β€” the sensitivity of the loss to each parameter β€” and that is exactly this quotient, one axis at a time. When a training run stalls, the first diagnostic is numerical: is the gradient finite-difference consistent? When it explodes, the second is: how large is the sensitivity, and should $\eta$ be smaller? Both questions are the expression above with $f$ replaced by $L$.

    Reading rituals: five questions for any formula

    The orientation module introduced these; here they become muscle memory, run twice on real formulas. Same order every time β€” the order is what makes it fast.

    1. What are the objects? Which letters are data, which are parameters, which are outputs, which are indices? A $y$ that appears with a subscript is a sample; a $\theta$ is a knob.
    2. What is the shape? Write $n \times d$, $d$, $n$, scalar β€” next to every symbol. If the shapes on the two sides of an equals sign disagree, you have already found a bug.
    3. What is summed or averaged? Over samples, over features, over classes? And is there a $\frac{1}{n}$ turning a total into an average? Nearly always: yes.
    4. What is the direction of good? $\min$ or $\max$? Which terms fight each other? What does $\lambda$ trade off? If you cannot say which way is better, you do not know what the formula optimises.
    5. Where does it live in code? Point at the NumPy line. If you cannot find one, the understanding is not finished.

    Run 1 β€” mean squared error. First the formula, then the questions.

    $$\mathrm{MSE} = \frac{1}{n}\sum_{i=1}^{n}\big(\hat{y}_i - y_i\big)^2$$ "the average squared distance between what we predicted and what was true"

    Objects: $\hat{y}_i$ is the prediction for sample $i$, $y_i$ is its target, both scalars; $n$ counts samples. Shapes: $\hat{y}, y \in \mathbb{R}^{n}$, so the difference is a vector and the sum collapses it to a scalar. Summed over: samples. Direction: smaller is better, zero only when every prediction is exact. In code: np.mean((yhat - y) ** 2). Thirty seconds, all five.

    Run 2 β€” the Gaussian log-likelihood. Same ritual, on a formula that looks far more intimidating.

    $$\sum_{i=1}^{n} \log \mathcal{N}\big(y_i \mid \mu, \sigma^2\big)$$ "the total log-probability that our model assigned to the data we actually saw"

    Objects: $\mathcal{N}$ is the Gaussian (bell curve) density, $\mu$ is where it is centred, $\sigma^2$ is how wide it is, $y_i$ is an observed value. Shapes: everything inside is scalar; the sum produces one scalar. Summed over: samples again. Direction: larger is better β€” this is a log-probability, and you want the model to find the observed data likely. In code: a sum of -0.5*np.log(2*np.pi*sigma**2) - (y - mu)**2/(2*sigma**2).

    Now the surprise. That scary-looking log-likelihood and the friendly MSE are the same objective, once $\sigma$ is fixed. Five steps:

    1. Write down the density. $$\mathcal{N}(y_i \mid \mu, \sigma^2) = \frac{1}{\sqrt{2\pi\sigma^2}}\,\exp\!\left(-\frac{(y_i-\mu)^2}{2\sigma^2}\right)$$ It says: a value far from $\mu$ (in units of $\sigma$) is exponentially unlikely.
    2. Take the log of one term. The log kills the exponential and turns the prefactor into an additive constant: $$\log \mathcal{N}(y_i \mid \mu, \sigma^2) = -\tfrac{1}{2}\log(2\pi\sigma^2) - \frac{(y_i-\mu)^2}{2\sigma^2}$$
    3. Sum over all samples. The constant no longer depends on $i$, so it becomes $\frac{n}{2}\log(2\pi\sigma^2)$, and the second term collects all the squared errors: $$\sum_{i=1}^{n} \log \mathcal{N}(y_i \mid \mu, \sigma^2) = -\frac{n}{2}\log(2\pi\sigma^2) - \frac{1}{2\sigma^2}\sum_{i=1}^{n}(y_i-\mu)^2$$
    4. Drop what does not depend on $\mu$. When you optimise over $\mu$, the first term is a constant β€” adding a constant shifts the answer but never moves where the peak is: $$\arg\max_{\mu} \sum_{i=1}^{n} \log \mathcal{N}(y_i \mid \mu, \sigma^2) = \arg\max_{\mu} \left(-\sum_{i=1}^{n}(y_i-\mu)^2\right)$$
    5. Read the sign and the constant. Maximising $-\sum(\cdot)^2$ is minimising $\sum(\cdot)^2$, and $\frac{1}{2\sigma^{2}}$ is a positive constant that cannot change which $\mu$ wins: $$\hat{\mu} = \arg\max_{\mu} \sum_{i=1}^{n} \log \mathcal{N}(y_i \mid \mu, \sigma^2) \;=\; \arg\min_{\mu} \underbrace{\frac{1}{n}\sum_{i=1}^{n} (\mu - y_i)^2}_{\text{MSE}}$$
    Maximum-likelihood estimation of a Gaussian mean is least squares β€” which is why "fit by minimising squared error" is a statistical assumption, not a neutral choice.

    That is not a trick specific to Gaussians. It is the reason squared error shows up everywhere: it is what you get when you say "the noise around my predictions is Gaussian and I want the most probable parameters". Change the assumed noise distribution and you get a different loss β€” Laplace noise gives absolute error, a Bernoulli gives cross-entropy. Module 04 derives that pipeline properly; Module 06 does it for log-loss.

    One ritual, two very different-looking formulas

    Both formulas passed the five questions in under a minute, and both collapsed to the same answer. That is the method working: the appearance of a formula tells you nothing, the five answers do. When a paper formula looks terrifying, that is a signal to run the ritual slowly, not to skip it.

    Notation traps that waste hours

    Every one of these has cost somebody a debugging session. Most are collisions β€” the same glyph doing double duty β€” plus a couple of genuine semantic traps.

    TrapWrong readingRight reading
    $x^{\top} y$ vs $xy$treating them the sameFor vectors, $x^{\top} y$ is the dot product: a scalar. Bare $xy$ is not defined (or means an outer product / elementwise product, depending on the paper). Shapes: $(1\times d)(d\times 1) \Rightarrow$ scalar.
    $(AB)^{-1}$$A^{-1}B^{-1}$$(AB)^{-1} = B^{-1}A^{-1}$ β€” the order reverses. Do the undoing in reverse order, like taking off shoes then socks. (Transposes reverse too: $(AB)^{\top} = B^{\top}A^{\top}$.)
    $\frac{\partial f}{\partial x}$ vs $\Delta$ vs $d$using them interchangeably$\partial$ = partial derivative (many inputs, one axis), $d$ = total derivative, $\Delta$ = a finite change β€” a difference, not a rate. In code: $\partial$ is a gradient element, $\Delta$ is a subtraction.
    $|A|$, $\|x\|$, $|S|$all "absolute value"$|A|$ = determinant (one scalar from a square matrix), $\|x\|$ = norm (length), $|S|$ = cardinality (how many elements). Three different objects, one glyph.
    $\log$ baseassuming one baseBase $e$ (natural log, "nats") is the default in ML derivations; base 2 ("bits") is used in information theory and compression. The minimiser is the same β€” only the reported numbers scale.
    $\arg\min$ vs $\min$expecting a number$\arg\min$ returns the argument ($\theta$, an index); $\min$ returns the value (a loss). Saving weights vs printing a loss.
    $X_{ij}$ row vs columnguessingML convention: $i$ indexes samples (rows), $j$ indexes features (columns) β€” so $X_{ij}$ is "sample $i$, feature $j$". Some maths and physics texts use the opposite. Check one entry against your code before trusting anything.
    $\mathbb{E}[X]$ vs $\bar{x}$treating them as synonyms$\mathbb{E}[X]$ is the population expectation β€” a property of the true distribution you do not have. $\bar{x} = \frac{1}{n}\sum_i x_i$ is the sample mean β€” a number computed from data you do have, and an estimate of the former.
    $f = O(g)$reading it as equalityBig-O is an upper bound on growth, not an equality and not a value. $O(n^2)$ says "grows no faster than $n^2$ up to a constant, for large $n$" β€” and $O(n^2)$ is compatible with $3n^2 + 7n$.
    The two that actually cost days

    $\arg\min$ vs $\min$. $\hat\theta = \arg\min_\theta J(\theta)$ gives you a vector of weights. $J(\hat\theta) = \min_\theta J(\theta)$ gives you a scalar loss. Writing "$\theta = \min J(\theta)$" β€” which you will do, in a hurry β€” assigns a vector to a number, and the bug appears three functions later as a broadcasting error that has nothing to do with its cause. Draw the arrow: argmin β†’ what you plug in; min β†’ what comes out.

    Big-O is not equality. "$O(n)$" does not mean "equals $n$", does not mean "equals something with $n$", and does not license dropping the constant β€” when that constant is $n$ training epochs or the cost of a GPU, it is the whole ballgame. Read it as growth class: what happens as the input gets large, ignoring multiplicative constants and lower-order terms.

    "Linear" does not mean "no exponents"

    The common guess is that a linear function is any formula without powers or roots. The actual definition is the identity $f(\alpha x + \beta z) = \alpha f(x) + \beta f(z)$. $x^2$ fails it (the $2xz$ cross term). $wx + b$ also fails it whenever $b \ne 0$. So: linear in the parameters is what regression usually means, and a straight line with an intercept is affine, not linear. Being strict here is not pedantry β€” "the model is linear in $\theta$" is exactly the condition that guarantees a single, unique minimum with no local traps, and Module 07 leans on it.

    The one equation every model is

    Close the pass by proving the claim from the orientation module: classical ML is one statement, and the algorithms differ only in which three pieces they plug in. Linear regression, logistic regression, a gradient-boosted ensemble of decision stumps and a deep network are all

    $$\hat{\theta} = \arg\min_{\theta} \; \frac{1}{n}\sum_{i=1}^{n} L\big(f(x_i;\theta),\, y_i\big) \;+\; \lambda\,\Omega(\theta)$$ identical structure β€” only f, L and Ξ© change
    fthe hypothesis β€” what family of rules + Lthe loss β€” what "wrong" means + Ξ©the regulariser β€” what "too complex" means β†’ arg minthe optimiser β€” how you search
    Algorithm$f$ β€” the hypothesis$L$ β€” the loss$\Omega$ β€” the regulariser
    Linear regression $f(x;w,b) = w^{\top}x + b$ β€” one straight hyperplane $(\hat{y} - y)^2$ β€” squared error $\|w\|^{2}$ (ridge); $0$ for plain least squares
    Logistic regression $f(x;w,b) = \dfrac{1}{1+e^{-(w^{\top}x+b)}}$ β€” a squashed line $-\big[y\log \hat{y} + (1-y)\log(1-\hat{y})\big]$ β€” cross-entropy $\|w\|^{2}$
    Stump ensemble $f(x) = \sum_{m=1}^{M} \alpha_m h_m(x)$ β€” sum of threshold rules (teaser, Module 08) same cross-entropy or squared error (Module 08) the number and depth of stumps (Module 08)
    Neural network $\sigma\big(W_{3}\,\sigma(W_{2}\,\sigma(W_{1}x))\big)$ β€” a deep composition (teaser, Modules 08–10) cross-entropy, or MSE for regression (Module 10) $\sum_{\ell}\|W_{\ell}\|^{2}$, plus dropout and early stopping (Module 10)

    Read down the columns instead of across the rows. The $f$ column is where the inductive bias lives β€” what the model is able to express. The $L$ column is where the probabilistic assumption lives (Gaussian $\Rightarrow$ squared error, Bernoulli $\Rightarrow$ cross-entropy). The $\Omega$ column is where the fight against overfitting lives. And $\arg\min$ is shared, which is why a single optimiser β€” gradient descent β€” serves all four. Swap a row and you have a different algorithm; swap nothing and you have a different paper.

    Every classical model = a family $f$ + a definition of wrong $L$ + a definition of too complex $\Omega$, minimised the same way. Learn to name those three and you can read any algorithm abstract.
    Pass 3

    Implement β€” make the notation move

    Type it, do not copy it; then change one number and predict

    Three blocks: shapes, sums, and the MSE / likelihood bridge

    NumPy only. The point of each block is not the library call β€” it is that the array on screen has the shape the formula promised.

    import numpy as np
    rng = np.random.default_rng(0)
    
    # 5 customers, 3 features: the whole dataset is ONE matrix, rows = samples.
    n, d = 5, 3
    X = rng.normal(size=(n, d))
    w = rng.normal(size=d)          # parameters: one number PER FEATURE, not per sample
    
    print("X    :", X.shape)        # (5, 3)   n x d
    print("w    :", w.shape)        # (3,)     d
    print("X @ w:", (X @ w).shape)  # (5,)     n  -- one score per sample, exactly n numbers
    
    # Two rows are two customers; their dot product is one number measuring how
    # aligned their feature vectors are (positive = similar, near 0 = unrelated).
    print("row0 . row1 =", round(float(X[0] @ X[1]), 4))   # ~0.32 with this seed
    
    # Row i of X dotted with w is EXACTLY entry i of X @ w -- the score for sample i.
    print("X[2] @ w == (X @ w)[2]:", np.isclose(X[2] @ w, (X @ w)[2]))   # True

    The last line is the whole point of shape discipline: $(n \times d)$ times $(d)$ gives $(n)$, and matrix–vector multiplication is just $n$ dot products, one per row, stacked. A model's "score every sample at once" is not a special operation β€” it is a loop you never had to write.

    import numpy as np
    rng = np.random.default_rng(1)
    
    n    = 8
    y    = rng.normal(loc=3.0, scale=1.0, size=n)   # targets
    yhat = y + rng.normal(scale=0.5, size=n)        # predictions: close, not perfect
    
    # NumPy way: the whole average in one expression (this is what you ship)
    mse_vec = np.mean((yhat - y) ** 2)
    
    # Formula way: the SAME object, written as (1/n) * sum_i (...)^2
    mse_sum = 0.0
    for i in range(n):          # this loop IS the sum over i = 1..n
        mse_sum += (yhat[i] - y[i]) ** 2
    mse_sum /= n                # the 1/n in front
    
    print(f"{mse_vec:.10f}")    # 0.0524715613 with this seed
    print(f"{mse_sum:.10f}")    # 0.0524715613 -- identical
    print("identical:", np.isclose(mse_vec, mse_sum))   # True

    That is the translation you should be able to do in both directions on sight: symbol β†’ loop, loop β†’ vectorised call. When a paper formula will not run, writing the loop version is usually how you find which index you had wrong.

    import numpy as np
    rng = np.random.default_rng(2)
    
    n, sigma = 200, 1.0
    y = rng.normal(0.0, 1.0, n)
    
    # Three candidate models for the SAME data; only the residual scale differs.
    models = {
        "A (good)": y + rng.normal(0, 0.4, n),
        "B (meh)" : y + rng.normal(0, 1.0, n),
        "C (bad)" : y + rng.normal(0, 2.0, n),
    }
    
    rows = []
    for name, yhat in models.items():
        sse = np.sum((yhat - y) ** 2)
        mse = sse / n
        # log N(y | yhat, sigma^2) summed over i, with sigma FIXED and shared
        ll  = np.sum(-0.5*np.log(2*np.pi*sigma**2) - (yhat - y)**2 / (2*sigma**2))
        # the same number rewritten as a straight line in MSE -- they must agree
        ll2 = -n/2*np.log(2*np.pi*sigma**2) - n*mse/(2*sigma**2)
        assert np.isclose(ll, ll2)
        rows.append((name, mse, ll))
    
    for name, mse, ll in sorted(rows, key=lambda r:  r[1]):
        print(f"{name:9s} MSE    = {mse:8.4f}")      # A 0.1771, B 0.9570, C 4.2481
    print()
    for name, mse, ll in sorted(rows, key=lambda r: -r[2]):
        print(f"{name:9s} loglik = {ll:10.3f}")      # A -201.502, B -279.486, C -608.597
    # Same order both times: with sigma shared, loglik = const - (n / (2 sigma^2)) * MSE,
    # a strictly decreasing line in MSE, so the ranking CANNOT differ.
    Exercise Β· break the agreement, then find ΟƒΜ‚
    • Give each model its own Οƒ. Re-run the loop with sig = {"A (good)": 1.0, "B (meh)": 0.10, "C (bad)": 4.0} and compute each model's log-likelihood with its own value. The MSE order is still A, B, C β€” but the log-likelihood order becomes A, C, B. Model B, which fits better than C, now ranks worse. Write down why before you read on: Οƒ is a promise about how wrong you will be, and B promises Οƒ = 0.10 while routinely missing by about 1. Every squared error gets divided by 2σ² = 0.02, so overconfidence is punished quadratically. MSE only measures fit; log-likelihood measures fit calibrated against a claimed uncertainty.
    • Now fit Οƒ instead. Take model A alone and evaluate its log-likelihood across np.linspace(0.1, 3.0, 2901). The best Οƒ is β‰ˆ 0.421 β€” and np.sqrt(mse) for model A is β‰ˆ 0.421 too. Predict the rule in one line: the maximum-likelihood ΟƒΜ‚ is the square root of the MSE.
    • Why this matters for Module 04. You just did maximum-likelihood estimation twice β€” once over ΞΌ (the MSE derivation, step 5) and once over Οƒ β€” by maximising a log-likelihood. Nothing in that process was probabilistic hand-waving; it was an $\arg\max$ on the same objective you have been minimising all along. MLE is this, always.
    Checkpoint

    Prove it, then start Module 02

    Answer first, then open the feedback

    Multiple choice β€” instant feedback

    1. What does the semicolon in $f(x;\theta)$ mean?

    2. $\hat{\theta} = \arg\min_{\theta} J(\theta)$. What is $\hat{\theta}$?

    3. Which statement is the actual definition of a linear function?

    4. Someone writes "this algorithm runs in $O(n^2)$". What are they entitled to claim?

    5. $X \in \mathbb{R}^{500 \times 12}$ and $w \in \mathbb{R}^{12}$. What is the shape of $Xw$, and what does it contain?

    6. With $\sigma$ fixed, maximising $\sum_{i} \log \mathcal{N}(y_i \mid \mu, \sigma^{2})$ over $\mu$ is equivalent to…

    Open questions β€” answer aloud, without notes

    Short and honest. If an answer will not come, mark the module for a re-read rather than guessing.

    1. Explain "notation is a compression language" to a colleague, then name one symbol you used to be able to manipulate but not read.
    2. A dataset has 10 000 rows and 50 features. Write the shapes of $X$, $w$ and $Xw$, and say what the $k$-th entry of $Xw$ means in English.
    3. Expand $\frac{1}{n}\sum_{i=1}^{n}(\hat{y}_i - y_i)^2$ as a loop, and then as a single NumPy line. Which symbol became which?
    4. What does $f(x;\theta)$ add over $f(x)$? What would machine learning be without it?
    5. Test $f(x) = wx + b$ against $f(\alpha x + \beta z) = \alpha f(x) + \beta f(z)$. Which term breaks it, and why does that push every model to be "linear parts + non-linear glue"?
    6. Say the generic objective out loud as one English sentence, naming every symbol as you pass it.
    7. Why does maximising the Gaussian log-likelihood give you squared error? One sentence, no formulas.
    8. Which of the five reading questions do you skip most often β€” and what bug has it already cost you?

    Re-answer these in 1, 3 and 7 days. Open the recall cards only after your own answer is written down.

    Continue in your ML notebook

    The notation you just installed is the notation used in ML module 02 Β· the math you actually use, where these symbols start appearing in pandas and scikit-learn lines instead of on paper β€” same letters, real datasets. And the generic objective from Section 5 becomes an actually trained model in ML module 05 Β· regression & gradient descent, where $\arg\min$ stops being a symbol and starts being a loop you watch converge.