Math Relearn/ Track 1 Β· Core tools/ Module 02

Linear algebra: the shape of data

Everything you will ever feed a model arrives as a rectangle of numbers, and everything you will ever do to it is one of three moves: sum over rows, combine columns, change the coordinate system. This is the biggest module in the course, because after this every algorithm is a variation on those three moves.

On this page
    Track 1 Β· Core tools

    02 Β· Linear algebra: the shape of data

    ⏱ ~2 hπŸ“Ž NumPy🎯 See every dataset as a matrix and every model as a transformation.

    You learned linear algebra as procedures on paper β€” row reduction, cofactor expansion, a list of identities to memorise. None of that survives contact with a dataset. What survives is the geometry: a vector is a point, a matrix is a transformation, a dot product is a measure of agreement, and a rank is how much of the space you can actually reach. This module rebuilds the subject that way, and attaches every idea to the exact line of ML where it does work.

    By the end you can

    • Read any dataset as $X \in \mathbb{R}^{n \times d}$ and say in English what a row, a column and a matrix product each mean.
    • Use the dot product to measure alignment, and explain exactly why the raw dot product confuses size with similarity.
    • Decide from the shapes alone whether two matrices multiply, what the result is, and what it computes.
    • Explain rank, determinant and norm geometrically β€” and name the ML algorithm each one props up.
    • Derive PCA in three lines from "maximise the variance", using eigenvectors, and say what PCA is not.
    • State what SVD factorises, what a truncated SVD guarantees, and where you meet it in ML.

    Why this module exists

    Machine learning has exactly one data structure. Images, text, audio, spreadsheets, graphs β€” all of them get flattened into a matrix where rows are examples and columns are features, and every model is a function that eats that matrix. If you do not own linear algebra you can still call the library, but you cannot read the shape error, cannot say what a layer computes, cannot follow the PCA chapter, and cannot understand why one training run is stable and another diverges. Those are not advanced topics; they are the floor.

    There is also a historical reason to take it seriously as applied mathematics. Linear algebra was the practical machinery of science long before anyone taught it as abstract theory: least squares (Gauss, announced 1795; Legendre, 1805) was invented to drag orbit parameters out of noisy telescope readings, and the determinants, eliminations and tables that followed were the spreadsheets of their era. The elegant "vector space" framing is a twentieth-century coat of paint on a tool built for engineers with pencil stubs. Learn it as a tool.

    This module is the largest in the notebook because everything downstream is a variation on it: gradient descent is a direction in vector space (Module 03), a Gaussian is a shape defined by a covariance matrix (Module 04), regularisation is a norm (Module 07), and PCA is an eigendecomposition (derived here, rebuilt as an algorithm in Module 08). Pay the cost once, properly.

    Pass 1

    Remember β€” retrieve before you read

    Six questions, ten minutes, no notes

    Cold retrieval β€” answer first, then open the cards

    1. Compute the dot product of $(1,2,3)$ and $(4,5,6)$.
    2. What is the shape of a $2 \times 2$ matrix times a $3 \times 2$ matrix? Does the product exist?
    3. In one sentence: what does it mean for a matrix $A$ to have an inverse?
    4. What does "orthogonal" mean for two vectors? What does it imply about their dot product?
    5. Give three different ways a matrix can fail to be invertible.
    6. What is the span of two vectors in $\mathbb{R}^3$ that are not parallel? And what is the rank of a matrix whose columns all live in that plane?

    Model answers

    1–2. Dot product of $(1,2,3)$ and $(4,5,6)$? Shape of $(2\times2)$ times $(3\times2)$?
    32, and the product does not exist. $1\cdot4 + 2\cdot5 + 3\cdot6 = 4 + 10 + 18 = 32$. For the shapes: multiplication is defined only when the inner dimensions agree β€” the $2$ columns of the left matrix must match the $3$ rows of the right matrix. They do not, so the expression is undefined (NumPy raises ValueError: … mismatch in its core dimension … (size 3 is different from 2)). The general rule: $(m \times p)(p \times n) = (m \times n)$.
    3. What does "A has an inverse" mean?
    There is a matrix that undoes it. $A^{-1}$ with $A^{-1}A = AA^{-1} = I$. Practically: the equation $Ax = b$ has exactly one solution ($x = A^{-1}b$) for every $b$. Geometrically, if $A$ rotates and stretches space, $A^{-1}$ rotates and unstretches it back. This requires $A$ to be square and to act without collapsing anything β€” see the next card.
    4. What does "orthogonal" mean?
    Perpendicular: the angle between the vectors is 90Β°, so their dot product is zero. $u \perp v \iff u \cdot v = 0$ (and neither vector is the zero vector). "Orthonormal" adds unit length. A matrix whose columns are orthonormal is an orthogonal matrix, the best kind of matrix in the subject: $A^{-1} = A^\top$ and it never changes any vector's length.
    5. Three ways a matrix fails to be invertible
    (a) It is not square β€” a two-sided inverse is only defined for $n \times n$. (b) Its columns are dependent β€” the determinant is zero, the rank is below $n$, the transformation squashes space into a lower dimension, and some $b$'s have no solution while others have infinitely many. (c) It is numerically singular β€” an inverse technically exists, but two columns are so close to parallel that dividing by a near-zero quantity blows the answer up in floating point. (b) is theory, (c) is what bites you in practice.
    6. Span of two non-parallel vectors in $\mathbb{R}^3$? Rank of a matrix whose columns live in that plane?
    The whole plane through the origin that they define β€” every point you can reach by scaling and adding them. And the rank is 2: rank is the dimension of the span of the columns, no matter how many columns the matrix has. A $5 \times 5$ matrix of vectors living in one plane has rank 2, is singular, and collapses 3-D space onto a sheet.
    What does $A\mathbf{x}$ compute, geometrically?
    A weighted combination of the columns of $A$. If $a_1, \dots, a_d$ are the columns, then $A\mathbf{x} = x_1a_1 + \dots + x_da_d$ β€” the coefficients are the entries of $\mathbf{x}$. So multiplying by a matrix means "reach into the menu of directions that $A$'s columns provide, and mix them in the proportions $\mathbf{x}$ gives you". That one sentence explains linear models, neural layers, PCA projections and change of basis.
    What is an eigenvector, in one sentence?
    A non-zero direction that a matrix does not turn β€” it only scales it: $A\mathbf{v} = \lambda\mathbf{v}$. Almost every other vector gets knocked off its own span; an eigenvector stays on it, stretched by $\lambda$, squashed by $\lambda$, or flipped if $\lambda$ is negative.
    State the shapes in $A = U\Sigma V^\top$ when $A$ is $1000 \times 50$.
    $U$ is $1000 \times 1000$, $\Sigma$ is $1000 \times 50$ (the same shape as $A$), $V$ is $50 \times 50$ so $V^\top$ is $50 \times 50$. $\Sigma$ is diagonal-ish: only its first 50 diagonal slots can be non-zero, and those hold the singular values $\sigma_1 \ge \sigma_2 \ge \dots \ge 0$.
    Why is the raw dot product a bad similarity score?
    Because it multiplies agreement by size. $u \cdot v = \|u\|\|v\|\cos\theta$, so a vector pointing in exactly the same direction scores ten times higher if it is ten times longer. Normalise both sides β€” divide by the lengths β€” and you get cosine similarity, which depends on direction alone. Retrieval systems and word embeddings normalise for exactly this reason.
    Pass 2

    Understand β€” the shape of the idea

    Thirteen turns: data β†’ vectors β†’ products β†’ structure β†’ eigen β†’ PCA β†’ SVD
    A dataset is a matrix, a model is a transformation, and "learning" is choosing which transformation to apply. Nothing in classical machine learning escapes that sentence.

    1 Β· Why linear algebra is the language of data

    A dataset is a rectangle with a convention attached: one row is one sample, one column is one feature. $n$ customers, $d$ measurements each, and entry $(i,j)$ is feature $j$ of sample $i$:

    $$X = \begin{bmatrix} x_{11} & x_{12} & \cdots & x_{1d} \\ x_{21} & x_{22} & \cdots & x_{2d} \\ \vdots & \vdots & \ddots & \vdots \\ x_{n1} & x_{n2} & \cdots & x_{nd} \end{bmatrix} \in \mathbb{R}^{n \times d}$$ row i = sample i, column j = feature j β€” this one object is every dataset you will ever see

    Once you accept that convention, you can read the whole field as three operations. Almost every formula in machine learning is a sum over rows, a combination of columns, or a change of basis:

    $$\underbrace{\frac{1}{n}\sum_{i=1}^{n} L\big(f(x_i),\, y_i\big)}_{\text{a sum over rows}} \qquad \underbrace{w^\top x = \sum_{j=1}^{d} w_j x_j}_{\text{a combination of columns}} \qquad \underbrace{X_c = U\Sigma V^\top}_{\text{a change of basis}}$$ the training loss, one prediction, and PCA β€” three moves, three shapes

    Say them in English and the ML appears: the loss averages an error over samples; a prediction is a weighted mix of the features; PCA rotates the data into coordinates where the axes mean something. A "sum over rows" is written $n$ times in a loop or once as a matrix product β€” and writing it once is what makes it run on a GPU. That is the entire practical difference between a script and a framework.

    Where this came from

    Linear algebra was invented as bookkeeping for observations. Gauss announced least squares in 1795 to fit the orbits of planets and asteroids to noisy positional data; Legendre published the same method in 1805. For a century afterwards, determinants, elimination and matrix identities were working tools of astronomers, surveyors and statisticians β€” computed by hand, in tables, for money. The abstract machinery you may remember (vector spaces, bases, linear maps as first-class objects) only settled into standard form in the early twentieth century, layered on top of a subject that had already been earning its keep for a hundred years. When you meet the abstraction, remember it is packaging for the tool, not the other way round.

    2 Β· Vectors: not lists, points with direction

    A vector is a list of numbers that belong together as one object β€” but the useful picture is geometric: a point in space, or an arrow from the origin to that point. Two operations build everything else. Addition places the arrows head-to-tail (the diagonal of the parallelogram they span); scalar multiplication stretches ($c \gt 1$), shrinks ($0 \lt c \lt 1$) or, if $c$ is negative, flips the arrow through the origin. Feed a vector set to both operations and you get linear combinations, and the set of everything you can build is the span:

    $$\operatorname{span}\{v_1, \dots, v_k\} = \left\{ \sum_{i=1}^{k} c_i v_i \;:\; c_i \in \mathbb{R} \right\}$$ every point reachable by scaling and adding the given vectors β€” a subspace, and the smallest one containing them

    Two non-parallel vectors in the plane span the whole plane. Three vectors in 3-D that all lie in one plane span only that plane β€” no combination of them escapes it, no matter how you weight them. Hold that image; it is the whole of the next three sections.

    1. A feature vector is a point. A customer with (age, income, clicks) = (34, 52000, 7) is a single point in $\mathbb{R}^3$. "Similar customers" is literally "nearby points" β€” every clustering, nearest-neighbour and recommendation method is a distance function applied to these points.
    2. A linear combination is a reachable output. $f(x) = w^\top x + b$ is a weighted mix of the features; a model that only ever returns sums of its inputs can only ever reach the span of what you gave it.
    3. Embeddings are vectors you can do arithmetic on. The classic (approximate) result in word embeddings: $\text{king} - \text{man} + \text{woman} \approx \text{queen}$. That only works because addition and scalar subtraction in the vector space correspond to real relationships in the data.
    A vector is a point; the span of a set of vectors is the subspace those points can reach; the rank of your data is the dimension of that subspace.

    3 Β· The dot product: alignment, not just multiplication

    The dot product is the one number that turns two vectors into one scalar, and it has a definition that looks mechanical and a meaning that is geometric β€” they are the same fact:

    $$u \cdot v = \sum_{i=1}^{d} u_i v_i = \|u\| \, \|v\| \cos\theta$$ multiply component-wise and add up ⟺ multiply the lengths by the cosine of the angle between them

    Take three readings of it, because all three show up in ML:

    1. Projection. $\|u\|$ times the component of $v$ along $u$. How much of $v$ points the same way as $u$? Ask a question in one language, measure an answer in another β€” this is how a linear classifier scores a point against a weight direction.
    2. Pairwise feature products. $\sum_i u_i v_i$: feature 1 with feature 1, feature 2 with feature 2… It is one number summarising two aligned feature vectors β€” the score $w^\top x + b$ of every linear model, the similarity $q \cdot k$ of every attention head.
    3. Agreement. Positive when they lean the same way, exactly zero when they are perpendicular, negative when opposed. Orthogonality $\Rightarrow$ dot product zero $\Rightarrow$ "these two features carry no linear relationship" β€” which is precisely what PCA tries to manufacture.

    Worked by hand: $(1,2,3) \cdot (4,5,6) = 4 + 10 + 18 = 32$, with $\|u\| = \sqrt{14} \approx 3.742$ and $\|v\| = \sqrt{77} \approx 8.775$. So $\cos\theta = 32 / \sqrt{14 \cdot 77} = 32/\sqrt{1078} \approx 0.975$ β€” the two vectors are about $13Β°$ apart, strongly aligned. Strip the lengths off and you have the similarity score that retrieval actually wants:

    $$\cos(u,v) = \frac{u \cdot v}{\|u\| \, \|v\|} \in [-1, 1]$$ the raw dot product divided by both lengths β€” direction only, magnitude discarded
    Why everyone normalises embeddings

    The raw score is $\|u\|\|v\|\cos\theta$: agreement times both lengths. Scale one embedding by ten and its score rises tenfold with zero change in meaning β€” length bias. That is not a theoretical worry: document length, user activity and word frequency all inflate vector norms, so a raw dot product happily ranks a long, irrelevant item above a short, perfect one. Fix: normalise every vector to unit length (store v / np.linalg.norm(v)), after which the dot product is the cosine similarity. You will see this in word embeddings and search/retrieval systems, and β€” with a twist β€” in attention: the transformer scales $q^\top k$ by $1/\sqrt{d}$ before the softmax, because the variance of a dot product grows with the dimension $d$, and an uncorrected score explodes and saturates the softmax. Same disease, same family of cure.

    4 Β· Matrices are transformations

    Stop reading a matrix as a table of numbers and start reading it as an instruction. Multiplying $A$ by a vector $x$ produces a weighted combination of $A$'s columns, with the entries of $x$ as the weights:

    $$A x = x_1 a_1 + x_2 a_2 + \dots + x_d a_d$$ $a_j$ = column j of A: the matrix offers a menu of directions, the vector orders the mix

    Three shapes to keep straight. The identity $I$ (ones on the diagonal) changes nothing, exactly like the number 1. The transpose $A^\top$ flips rows and columns, $(A^\top)_{ij} = A_{ji}$, and it satisfies $\left(AB\right)^\top = B^\top A^\top$ β€” note the order reversal. The inverse $A^{-1}$ satisfies $A^{-1}A = AA^{-1} = I$; for a two-sided inverse $A$ must be square ($n \times n$) and its columns must be independent.

    Non-square matrices are not broken β€” they change the dimension of space. A $k \times d$ matrix maps $\mathbb{R}^d \to \mathbb{R}^k$: feed it $d$ numbers, get $k$ numbers back. When $k \lt d$ that is a compression, and it is the shape of every layer that reduces: 784 pixels into 10 hidden units, 512 features into 64, a whole vocabulary into a dense embedding. Reading shapes tells you what an operation does before you read a line of code.

    The classical use is the linear system $Ax = b$: find the coefficients that build $b$ out of the columns of $A$. If $b$ lies in the span of $A$'s columns there are solutions (unique if the columns are independent, infinitely many if they are not); if $b$ is outside that span, there are none β€” only a least-squares compromise, which is exactly what regression computes. Singular matrices are precisely those whose columns do not span the space they live in:

    $$\underbrace{\begin{bmatrix} 1 & 2 \\ 2 & 4 \end{bmatrix}}_{\text{column 2 = 2} \times \text{column 1}} \begin{bmatrix} x_1 \\ x_2 \end{bmatrix} = b \quad\Longrightarrow\quad \text{only } b \text{ on the line } b_2 = 2 b_1 \text{ is reachable}$$ parallel columns span a line, not a plane: $b=(3,6)$ is fine ($x=(3,0)$), $b=(0,1)$ is impossible

    5 Β· Matrix multiplication, properly

    The definition is one line: take row $i$ of the left matrix and column $j$ of the right, dot them.

    $$(AB)_{ij} = \sum_{k=1}^{p} A_{ik} B_{kj} = \text{row}_i(A) \cdot \text{col}_j(B) \qquad (m \times p)(p \times n) = (m \times n)$$ the inner dimensions $p$ must match; the outer dimensions are the shape of the answer

    So $\begin{bmatrix} 1 & 2 \\ 3 & 4 \end{bmatrix}\begin{bmatrix} 5 & 6 \\ 7 & 8 \end{bmatrix}$ has top-left entry $1\cdot5 + 2\cdot7 = 19$, top-right $1\cdot6 + 2\cdot8 = 22$, and the product is $\begin{bmatrix} 19 & 22 \\ 43 & 50 \end{bmatrix}$. The definition is correct but useless for thinking. Use one of these three readings instead β€” they are all the same operation:

    1. Columns. Column $j$ of $AB$ equals $A$ times column $j$ of $B$: each output column is a combination of $A$'s columns, mixed with the weights sitting in that column of $B$.
    2. Rows. Row $i$ of $AB$ equals row $i$ of $A$ times $B$: each output row is a combination of $B$'s rows. If the rows of $B$ are data samples, row $i$ of $A$ decides how to blend them.
    3. Composition. $(AB)x = A(Bx)$: apply $B$ first, then $A$. Two layers stacked in one matrix. This is why order matters and why $AB \ne BA$ in general.
    The two mistakes that cause most shape bugs

    (1) Matrix multiplication is not commutative. $AB$ and $BA$ are usually different matrices β€” and often only one of them is even defined. The composition reading tells you which is which: the rightmost factor is applied first. Getting this backwards is how a correctly-shaped program computes something meaningless. (2) Shapes are the type system. $(n \times d)(d \times k) = (n \times k)$ β€” check it on paper before you run it. If your loss comes out $k \times k$ when you expected a scalar, the error was three lines earlier, not in the loss.

    Why the obsession with this one operation? Cost and hardware. Multiplying two square $1000 \times 1000$ matrices costs about $n^3 = 10^9$ multiply–add operations; training a deep network runs an enormous number of such products, and the overwhelming majority of wall-clock training time is spent inside general matrix multiply kernels. The other reason is batching. With $X$ an $n \times d$ batch of samples and $W$ a $d \times k$ weight matrix:

    $$Y = XW \in \mathbb{R}^{n \times k} \qquad \text{β€œ}n\text{ samples} \times d\text{ features”} \longrightarrow \text{β€œ}n\text{ samples} \times k\text{ outputs, one call”}$$ the loop over samples disappears β€” this is why GPUs changed the field

    One giant multiply instead of $n$ tiny ones. GPUs have thousands of cheap cores and very high memory bandwidth, which is exactly the shape of $XW$ β€” and nothing else. Before BLAS-style batched matrix multiplication, a neural net trained on a handful of examples per second; after it, the same code runs on billions of tokens, because the arithmetic did not change, only its packaging.

    ProductLeftRightResultWhat it is in ML
    $X W$$n \times d$$d \times k$$n \times k$Batched scoring / one neural layer: every sample, every output unit
    $X^\top X$$d \times n$$n \times d$$d \times d$Feature covariance & the normal equations of regression
    $X X^\top$$n \times d$$d \times n$$n \times n$Pairwise sample similarity β€” kernel matrices, attention scores
    $A x$$m \times n$$n$$m$Transform one point: one layer, one projection, one change of basis
    $AB$$m \times p$$p \times n$$m \times n$Compose two transformations β€” apply $B$ first
    $(2{\times}2)(3{\times}2)$$2 \times 2$$3 \times 2$undefinedInner dimensions $2$ vs $3$ disagree β€” this is your Pass 1 question 2

    6 Β· Rank, span and collinearity

    The rank of a matrix is the number of linearly independent columns β€” equivalently, the dimension of the span they generate, equivalently the number of independent rows (rows and columns always agree). It is the honest size of the information in your data:

    $$\operatorname{rank}(A) \le \min(m, n), \qquad \text{full rank} \iff \operatorname{rank} = n \text{ (for a square } A\text{)} \iff A^{-1} \text{ exists}$$ rank deficiency means redundancy: some column is a combination of the others, so it adds no new direction

    A rank deficiency is not an abstract defect β€” it is a duplicate or a derived feature hiding in your dataset. Two columns that are proportional (metres and centimetres), or one column that is the sum of others, and your matrix has collapsed. Three places you will meet it immediately:

    • The dummy-variable trap. One-hot encode a 4-category feature into 4 indicator columns and add an intercept column of ones β€” the ones column is exactly the sum of the four indicators. $X^\top X$ is singular, the regression has no unique solution. Fix: drop one level, or drop the intercept.
    • Multicollinearity. When two features are nearly (not exactly) collinear the model can still fit, but the coefficients become unstable and huge β€” tiny changes in the data swing them wildly. Ridge regression adds $\lambda I$ precisely to put a floor under those directions (Section 9 shows why that works).
    • Why PCA exists. Real datasets are strongly correlated, so their effective rank is far below $d$: a 1 000-feature sensor rig driven by 8 physical quantities has rank 8 in the ways that matter. Low rank is not a problem to fix β€” it is structure to exploit, and it is what Section 11 and Section 12 harvest.
    Numerical rank is a tolerance, not a fact

    Exact rank is a theorem about exact numbers; your data has decimal places. np.linalg.matrix_rank counts singular values above a tolerance, which means the same matrix can be "rank 5" or "rank 50" depending on measurement noise. When a result flips with the tolerance, you are looking at near-collinearity, not rank β€” and that is the case where numerical stability (condition numbers, Module 07) matters more than the algebra.

    7 Β· Determinant: volume scaling and invertibility

    The determinant is a single number that answers: if I feed the unit square (or cube, or hypercube) through this matrix, how does the volume change? Not the direction, just the factor. The two-dimensional case is worth memorising because it carries the whole intuition, $\det\begin{bmatrix} a & b \\ c & d \end{bmatrix} = ad - bc$: it is the signed area of the parallelogram spanned by the two columns.

    $$\det\begin{bmatrix} 2 & 0 \\ 0 & 3 \end{bmatrix} = 6 \qquad \det\begin{bmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{bmatrix} = 1 \qquad \det\begin{bmatrix} 1 & 2 \\ 2 & 4 \end{bmatrix} = 0$$ unit square β†’ 2Γ—3 rectangle (area Γ—6) Β· a rotation preserves area Β· parallel columns collapse to a line

    Read the three cases as a rule. Absolute value = scaling factor: $|\det A| = 6$ means every volume in the space is multiplied by 6. Sign = orientation: $\det A \lt 0$ means space got flipped inside out, like a reflection β€” areas still grow, but handedness is reversed. Zero = collapse: the matrix sends a full-dimensional chunk of space onto a plane or a line, volume becomes 0, and no inverse can undo that (you cannot un-flatten a pancake). For square matrices, all three collapse into one equivalence:

    $$A^{-1} \text{ exists} \iff \det A \ne 0 \iff \operatorname{rank}(A) = n \iff \text{the columns span } \mathbb{R}^n$$ four ways of saying "this transformation does not crush anything"

    Two caveats that prevent the usual damage. First, the determinant is only defined for square matrices β€” a $4 \times 7$ matrix has no determinant, so "the determinant is non-zero, therefore it is invertible" is meaningless until you know the shape. Second, do not compute it by cofactor expansion: computers use elimination (LU), and in practice you almost never compute a determinant directly β€” you ask a library whether the matrix is singular. What you do use is its meaning: the determinant of a covariance matrix controls the volume of the uncertainty ellipsoid in a Gaussian density (it appears as $\log|\Sigma|$ in Module 04), and it equals the product of the eigenvalues, $\det A = \prod_i \lambda_i$ β€” the volume scaling is just all the per-axis stretch factors multiplied together. That is the bridge to Section 10.

    8 Β· Norms and distances

    A norm is a length measurement β€” a function that turns a vector into a non-negative number, zero only for the zero vector, and that grows predictably when you scale the vector. There is a family of them, indexed by $p$:

    $$\|x\|_p = \left( \sum_{i=1}^{d} |x_i|^p \right)^{1/p}, \qquad \|x\|_2 = \sqrt{\textstyle\sum_i x_i^2}, \qquad \|x\|_1 = \textstyle\sum_i |x_i|, \qquad \|x\|_\infty = \max_i |x_i|$$ the usual length Β· the taxicab sum Β· the worst single coordinate

    Worked: $x = (3,-4)$ gives $\|x\|_2 = 5$, $\|x\|_1 = 7$, $\|x\|_\infty = 4$. To see why the three differ, draw the set of vectors with norm exactly 1 β€” the "unit circle" of each norm:

    • $p = 2$: a circle. Smooth, no corners, every direction is equivalent. This is the length we mean when we say "length".
    • $p = 1$: a diamond. A square stood on its corner, with its four vertices on the axes β€” points like $(1,0)$ and $(0,1)$. Every point on the diamond's edges is on the way to a vertex that lies on an axis.
    • $p = \infty$: a square. Flat sides at $\pm 1$; the norm just watches the worst coordinate. The three nest: $\|x\|_\infty \le \|x\|_2 \le \|x\|_1$.

    That diamond is why $L_1$ does something $L_2$ cannot. When you minimise a smooth objective over the unit ball, the answer tends to land where the constraint's corners are β€” and the diamond's corners sit exactly on the axes, where some coordinate is exactly zero. The circle has no corners, so its solutions land generically in the middle of nowhere: every coordinate survives, just a bit smaller. This is the entire mechanism of Lasso sparsity versus the gentle shrinkage of $L_2$ weight decay β€” you will derive it again in Modules 07 and 08, and it reappears as feature selection and as pruning.

    For distances between data points, two metrics do nearly all the work. Euclidean distance $\|u - v\|_2$ measures how far apart two points are β€” k-means minimises exactly this (the "k" is not negotiable: change the norm and you have a different algorithm), and it is right when magnitude is meaningful: pixels, prices, sensor readings. Cosine distance, $1 - \cos(u,v)$, measures the angle and ignores the length β€” right for text and embeddings, where document length or user activity inflates the norm without adding meaning. The two are not rivals either β€” for unit vectors the whole distance collapses to the angle:

    $$\|u - v\|^2 = \|u\|^2 + \|v\|^2 - 2\, u \cdot v = 2 - 2\cos\theta \qquad (u, v \text{ both of unit length})$$ once you normalise, ranking by Euclidean distance and ranking by cosine similarity give the same order
    Distance is not similarity, and neither is the dot product

    Euclidean distance is small = close. Cosine similarity is large = close. Dot product is large = close and large. Three quantities, three different scales, and mixing them up silently ruins ranking quality: a retrieval system that sorts by raw dot product when it meant cosine will surface popular long documents over relevant short ones. Before you compare two scores, name the metric and say what it rewards β€” magnitude, angle, or both.

    9 Β· Special matrices you will meet in ML

    Four matrix types do almost all the work. Each has a one-line definition, a picture, and a specific place it shows up:

    TypeDefinitionPictureYou will meet it here
    Symmetric$A = A^\top$Ellipse-like shape aligned with the axes; no shearCovariance matrices, $X^\top X$, the Hessian β€” and, crucially, real eigenvalues with orthogonal eigenvectors
    Diagonal$A_{ij} = 0$ for $i \ne j$Stretch each axis, mix nothingFeature standardisation, a covariance with independent features, Adam's per-parameter rescaling
    Orthogonal$A^\top A = I$ (square)Rotation or reflection: lengths and angles survive untouched$A^{-1} = A^\top$; QR factorisation, PCA's rotation, weight orthogonalisation in deep nets
    Positive definite$x^\top A x \gt 0$ for all $x \ne 0$Bowl-shaped quadratic: one unique bottomThe Hessian at a minimum, Gaussian covariances, and why $X^\top X + \lambda I$ is invertible

    The last row deserves its working shown, because it answers a question you will hit the moment you add regularisation. Take any matrix $X$ (possibly rank-deficient) and any $\lambda \gt 0$:

    $$x^\top (X^\top X + \lambda I) x = \|Xx\|^2 + \lambda \|x\|^2 \ge \lambda \|x\|^2 \gt 0 \quad (x \ne 0)$$ every direction costs at least $\lambda$ β€” so nothing can be flat, so the matrix is invertible

    Positive definiteness is "the function has a bowl shape": $f(x) = \tfrac{1}{2}x^\top A x$ with $A$ positive definite decreases in every direction you move away from zero, so zero is the unique minimum. That is why convexity arguments in Modules 03 and 07 keep asking whether a Hessian is positive definite, and why a covariance matrix must be at least positive semi-definite β€” a direction with zero variance is a direction the data never varies in.

    10 Β· Eigenvalues and eigenvectors: the directions that do not turn

    Feed a matrix a generic vector and it comes back rotated off its own span β€” no scalar multiple of the input can equal the output. Eigenvectors are the exceptions, the rare directions where the matrix behaves like plain arithmetic:

    $$A v = \lambda v, \qquad v \ne 0$$ the matrix only scales the vector: $\lambda \gt 1$ stretch, $0 \lt \lambda \lt 1$ squash, $\lambda \lt 0$ flip through the origin

    The length of $v$ is irrelevant β€” if $Av = \lambda v$ then $A(cv) = \lambda(cv)$ for any scalar $c$, so every line through an eigenvector is full of eigenvectors. Only the direction and the factor $\lambda$ carry meaning. The eigenvector is not "the longest" or "the most important" vector in any sense; importance, if you need it, comes from the associated $\lambda$ and from what the matrix is.

    A quick intuition check: a rotation matrix in 2-D. If $A$ rotates every vector by $30Β°$, is there any direction it leaves on its own span? No β€” and the algebra agrees. The characteristic equation $\det(A - \lambda I) = 0$ for $R(\theta)$ expands to

    $$\det\big(R(\theta) - \lambda I\big) = \lambda^2 - 2\lambda\cos\theta + 1 = 0 \;\Longrightarrow\; \lambda = \cos\theta \pm i\sin\theta$$ complex eigenvalues of unit magnitude β€” the rotation was hiding in the "scaling" factor all along

    For $\theta \ne 0, \pi$ there are no real eigenvectors: the roots are complex. That is a genuine diagnostic β€” complex eigenvalues mean the matrix contains rotation. The general recipe is the same for any $n \times n$ matrix: build $\det(A - \lambda I)$, a degree-$n$ polynomial, and its roots are the eigenvalues (counted with multiplicity, possibly complex). Work the trivial case to keep it grounded: for $A = \begin{bmatrix} 2 & 0 \\ 0 & 3 \end{bmatrix}$ the equation is $(2-\lambda)(3-\lambda) = 0$, giving $\lambda = 2, 3$ with eigenvectors $e_1, e_2$ β€” the axes, because a diagonal matrix never mixes them.

    The payoff of finding them all is that the matrix becomes trivial in that basis. Stack the eigenvectors as columns of $P$ and put the eigenvalues on the diagonal of $D$, and you get a diagonalisation:

    $$A = P D P^{-1} \quad\Longrightarrow\quad A^k = P D^k P^{-1} \quad\text{with } D^k = \operatorname{diag}(\lambda_1^k, \dots, \lambda_n^k)$$ powers of a matrix become powers of numbers β€” raise each diagonal entry, do not multiply k times

    For $A = \operatorname{diag}(2,3)$, $A^{10} = \operatorname{diag}(2^{10}, 3^{10}) = \operatorname{diag}(1024, 59049)$ β€” one line instead of ten matrix multiplications. This is exactly how long-run behaviour is analysed. In a Markov chain with row-stochastic transition matrix $P$ (rows sum to 1, entries are probabilities), the distribution after many steps is $\pi_0 P^k$, and the steady state is the distribution that applying $P$ does not change:

    $$\pi^\top P = \pi^\top \quad\Longleftrightarrow\quad \pi^\top \text{ is a left eigenvector of } P \text{ with eigenvalue } 1$$ steady state = the direction the transition matrix refuses to turn

    Concretely, $P = \begin{bmatrix} 0.9 & 0.1 \\ 0.4 & 0.6 \end{bmatrix}$ has steady state $\pi = (0.8, 0.2)$: check $0.8 \times 0.9 + 0.2 \times 0.4 = 0.8$ and $0.8 \times 0.1 + 0.2 \times 0.6 = 0.2$. PageRank is the same idea with 10 million states, plus a damping trick to keep the matrix well behaved.

    Eigenvectors β‰  singular vectors, and length means nothing

    Three separate misconceptions to kill now. "The eigenvector is the longest vector" β€” false: length is arbitrary (scale $v$ and it is still an eigenvector); only the direction and $\lambda$ are content. "Every matrix has real eigenvectors" β€” false: a rotation has none, and even for symmetric matrices the eigenvalues can be negative. "Eigenvectors and singular vectors are the same" β€” false in general: singular vectors come from SVD, which for a non-symmetric matrix gives different directions than the eigendecomposition. If a matrix is symmetric they coincide (up to sign), and that coincidence is what makes Section 11 work.

    11 Β· Covariance matrix and PCA, derived

    The covariance matrix collects how every pair of features co-varies across samples. Centre the data first ($X_c = X - \bar{x}$, each column minus its mean), then:

    $$\Sigma = \frac{1}{n-1} X_c^\top X_c \in \mathbb{R}^{d \times d}, \qquad \Sigma_{jj} = \operatorname{Var}(\text{feature } j), \qquad \Sigma_{ij} = \operatorname{Cov}(i, j)$$ $d \times d$ no matter how many samples: it describes feature relationships, not samples

    Now the question PCA answers. Take a unit direction $u$ (say, "the direction from the origin to (0.83, 0.55)") and project every sample onto it β€” that gives one number per sample, $X_c u$. How variable is that projection? Its variance is a dot-product identity away from $\Sigma$:

    $$\operatorname{Var}(X_c u) = \frac{1}{n-1}(X_c u)^\top (X_c u) = u^\top \Sigma u$$ the variance of the data seen from direction $u$ β€” "how much room is there along this line?"

    So PCA is an optimisation: pick the unit direction that maximises $u^\top \Sigma u$, subject to $u^\top u = 1$. Solve it with a Lagrange multiplier β€” watch how the constraint folds into the objective (this exact move returns in Module 07):

    $$\mathcal{L}(u, \lambda) = u^\top \Sigma u - \lambda\,(u^\top u - 1)$$ $$\nabla_u \mathcal{L} = 2\Sigma u - 2\lambda u = 0 \quad\Longrightarrow\quad \Sigma u = \lambda u$$ the best direction must be an eigenvector of $\Sigma$ β€” and the variance it achieves is exactly $\lambda$

    That is the whole derivation: maximise variance under a unit-length constraint and you get an eigenvector. Order the eigenvalues $\lambda_1 \ge \lambda_2 \ge \dots$, and the corresponding eigenvectors are the principal components β€” direction 1 holds the most variance, direction 2 the most of what is left, and they are orthogonal (because $\Sigma$ is symmetric). Worked example: for $\Sigma = \begin{bmatrix} 2 & 1.2 \\ 1.2 & 1 \end{bmatrix}$ the eigenvalues are exactly $2.8$ and $0.2$ (trace $3$, determinant $0.56$), and the first component is $u_1 = (3,2)/\sqrt{13} \approx (0.832,\, 0.555)$, explaining $2.8/3 = 93.3\%$ of the variance.

    1 Β· Centre$X - \bar{x}$ β†’ 2 Β· Eigendecompose$\Sigma = V\Lambda V^\top$, or SVD of $X_c$ β†’ 3 Β· Sort$\lambda_1 \ge \lambda_2 \ge \dots$ β†’ 4 Β· Project$Z = X_c V_k$ β†’ 5 Β· Keep $k$explained $= \lambda_i / \sum_j \lambda_j$
    What PCA is not

    Not supervised. PCA never looks at $y$; it cannot "find the features most correlated with the target", because there is no target. If you want predictive directions you need PLS, LDA, or a supervised model. Not feature selection. PC1 is a weighted combination of all features β€” you get new axes, not a subset of the old ones, so you cannot say "PCA picked feature 7". Not scale-invariant. A feature measured in euros dominates one measured in radians purely because of units, so standardise the columns first (zero mean, unit variance) unless the units are genuinely comparable β€” otherwise your components measure your unit choices, not your data. And it is linear: it will not untangle a curved manifold (for that you want kernels or an autoencoder).

    12 Β· SVD: the fundamental theorem of linear algebra

    The eigendecomposition needs a square matrix. The singular value decomposition does not: every matrix, any shape, factors into an orthogonal basis on each side and a diagonal stretch in the middle:

    $$A_{m \times n} = U_{m \times m} \, \Sigma_{m \times n} \, V^\top_{n \times n}$$ V and U are orthogonal (rotations), $\Sigma$ holds the singular values $\sigma_1 \ge \sigma_2 \ge \dots \ge 0$

    The geometric story is three moves: $V^\top$ rotates the input so the coordinate axes line up with the data's natural directions; $\Sigma$ scales along those axes, stretching by $\sigma_1, \sigma_2, \dots$ and sending the extra dimensions to zero; $U$ rotates the result into the output's frame. Every matrix is a rotation–scaling–rotation (when the scaling sends dimensions to zero, it is also a collapse β€” which is how rank deficiency shows up). Written as a sum of rank-1 pieces, the structure is explicit:

    $$A = \sum_{i=1}^{r} \sigma_i \, u_i v_i^\top, \qquad r = \operatorname{rank}(A)$$ the biggest singular value carries the most structure β€” chop the tail and you have compressed $A$

    Chopping the tail is not a hack; it is provably optimal. The Eckart–Young theorem states that the matrix built from the top $k$ singular values is the closest rank-$k$ matrix to $A$ in the Frobenius norm β€” no other matrix of rank $k$ does better:

    $$\min_{\operatorname{rank}(B) \le k} \| A - B \|_F = \sqrt{\sum_{i \gt k} \sigma_i^2}$$ best possible rank-k approximation β€” stated here, proved in a numerical linear algebra course

    Three applications, in decreasing order of how often you will meet them:

    1. Image compression. A greyscale image is a matrix; store only the top $k$ singular triplets β€” $k(m + n + 1)$ numbers instead of $mn$ β€” and reconstruct. Rank 20 on a 128Γ—128 image is a 3Γ— saving with a few percent error (you will run this below).
    2. Latent factors in recommender systems. A users Γ— items matrix with a few hidden tastes behind it is low-rank: "this user is a 0.9 action fan", "this film is 0.8 action" β€” the product predicts the rating. Missing entries are filled from the low-rank reconstruction, which is exactly the exercise below.
    3. PCA itself. Centre the data and take its SVD, $X_c = USV^\top$; then $\Sigma = \frac{1}{n-1}X_c^\top X_c = \frac{1}{n-1} V S^2 V^\top$, so the right singular vectors are the principal components and the explained variances are $s_i^2/(n-1)$. One algorithm, two entrances.
    Why libraries take the SVD, not the eigendecomposition of $X^\top X$

    You might compute PCA via the eigenvalues of $X^\top X$ β€” it works algebraically. Numerically it is a trap: forming $X^\top X$ squares the condition number, $\kappa(X^\top X) = \kappa(X)^2$, so if $X$ is mildly ill-conditioned (say $\kappa = 10^6$), the squared matrix is at the edge of double precision ($10^{12}$ against $10^{16}$) and small singular values turn into rounding noise. Compute the SVD of $X$ directly instead β€” one squaring of error avoided β€” and the same reasoning is why solvers use QR/SVD rather than normal equations. You will meet this again in Module 07.

    13 Β· The ML map

    Close the loop: every concept in this module, and the machine it drives. Keep this table as the index β€” when an algorithm seems opaque, find its row here and name the load-bearing math before reading the code.

    ConceptGeometryThe ML thing it powers
    Dot productAlignment, projected lengthSimilarity in embeddings; attention scores $QK^\top$; every linear/logistic classifier score $w^\top x + b$; the kernel trick
    Matrix multiplyComposition of transformations, batched at onceNeural layers $XW$; batched scoring; the chain of Jacobians in backpropagation
    Rank & low-rank structureRedundancy; hidden factorsMulticollinearity & the dummy trap; LoRA fine-tuning ($W + BA$); recommender matrix completion; PCA
    EigendecompositionDirections the matrix does not turnPCA; spectral clustering; PageRank & Markov steady states; stability of dynamical systems
    SVDBest rank-$k$ approximationPCA via SVD; image compression; latent semantic analysis; recommender latent factors
    Positive definitenessBowl-shaped quadraticsConvex losses; the Hessian at a minimum; ridge $X^\top X + \lambda I$; Gaussian log-determinants
    Norms & distancesSize of a vector; proximity of points$L_1$ sparsity (Lasso) vs $L_2$ shrinkage (weight decay); k-means / k-NN distances; gradient-norm clipping
    Orthogonal matricesLength-preserving rotationQR factorisation & Householder solvers; PCA's rotation; orthogonal weight initialisation to keep activations stable
    DeterminantVolume scaling; orientationSingularity tests; the $\log|\Sigma|$ term in Gaussian densities; change-of-variables in normalising flows
    If you can state, for any algorithm, which row of this table holds it up β€” you understand the algorithm's mathematics.
    Pass 3

    Implement β€” make it move

    Type it, then change one number and predict the effect

    Four blocks: alignment, transformation, PCA, compression

    Every output below is verified β€” run the code and check the printed numbers against the comments. Then break something: scale a vector, change the angle, drop a component, and predict what moves before you run it.

    Block 1 β€” length bias. The same query against four candidates, scored two ways: raw dot product and cosine. Watch the rankings disagree.

    import numpy as np
    
    u = np.array([1., 2., 3.])          # the query embedding
    v = np.array([4., 5., 6.])          # a candidate: long, and roughly the same direction
    s = 0.1 * u                         # identical direction to u, 10x shorter
    t = np.array([10., 0., 0.])         # long, but almost perpendicular to u
    
    def dot(a, b):    return float(a @ b)
    def cosine(a, b): return dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
    
    print("u . v     =", dot(u, v))                 # 32.0
    print("cos(u, v) =", round(cosine(u, v), 4))    # 0.9746  -> about 12.9 degrees apart
    print()
    print(f"{'candidate':10s} {'raw dot':>9s} {'cosine':>9s}")
    for name, w in [("v", v), ("10 * v", 10 * v), ("s = 0.1 u", s), ("t", t)]:
        print(f"{name:10s} {dot(u, w):9.2f} {cosine(u, w):9.4f}")
    
    # raw dot ranks: 10*v (320) > v (32) > t (10) > s (1.4)  -- size wins
    # cosine ranks:    s (1.000) > v = 10*v (0.9746) > t (0.2673)  -- direction wins
    # s and t swap places: the raw dot product sends the WRONG candidate to the top

    The raw score and the cosine score disagree on which candidate is best. Neither is "wrong": the raw dot product measures alignment times magnitude, cosine measures alignment alone. If your ranking task cares about direction, you must normalise before you sort.

    Block 2 β€” matrices as transformations. An orthogonal matrix (rotation) must preserve every length; a rank-deficient matrix must collapse space onto a plane and refuse to invert.

    import numpy as np
    
    # --- an orthogonal matrix: rotation by 30 degrees ---
    th = np.pi / 6
    R = np.array([[np.cos(th), -np.sin(th)],
                  [np.sin(th),  np.cos(th)]])
    print("R @ R.T = I :", np.allclose(R @ R.T, np.eye(2)))   # True -> inverse is the transpose
    print("det R   =", round(float(np.linalg.det(R)), 12))     # 1.0   -> area preserved
    
    pts = np.array([[1., 0.], [3., 4.], [-2., 5.]])
    before = np.linalg.norm(pts, axis=1)
    after  = np.linalg.norm(pts @ R.T, axis=1)   # rows are points, so rotate with R.T
    print("lengths before:", np.round(before, 6)) # [1.  5.  5.385165]
    print("lengths after :", np.round(after, 6))  # identical
    print("max change    =", np.abs(before - after).max())   # 0.0
    
    # --- a rank-deficient matrix: 3-D points collapse onto a plane ---
    A = np.array([[1., 2., 3.],
                  [2., 4., 6.],
                  [1., 0., 1.]])                  # row 2 = 2 * row 1 -> rank 2
    print("rank(A) =", np.linalg.matrix_rank(A))  # 2
    print("det(A)  =", np.linalg.det(A))          # 0.0
    
    y = A @ np.array([1., 2., 3.])
    print("A x =", y, "-> 2nd coord is 2 x 1st:", np.isclose(y[1], 2 * y[0]))   # [14. 28.  4.] True
    rand3 = np.random.default_rng(1).normal(size=(4, 3))
    images = rand3 @ A.T
    print("all images on the plane y2 = 2*y1:",
          np.allclose(images[:, 1], 2 * images[:, 0]))            # True
    try:
        np.linalg.inv(A)
    except np.linalg.LinAlgError as err:
        print("np.linalg.inv ->", err)                           # Singular matrix

    Three facts in one run: $R^\top R = I$ with $\det R = 1$ (a rotation: no length is gained or lost), rank 2 with determinant 0 (a collapse β€” every image lands on the plane $y_2 = 2y_1$, a two-dimensional sliver inside 3-D), and np.linalg.inv refusing to work. Singular matrices are not an inconvenience libraries hide; they are a geometric fact you can watch.

    Block 3 β€” PCA from scratch, then checked against scikit-learn. The covariance matrix is built with known eigenvalues ($2.8$ and $0.2$) so you can compare the answer to the truth.

    import numpy as np
    rng = np.random.default_rng(0)
    
    # population covariance chosen so the true eigenvalues are exactly 2.8 and 0.2
    Sigma_true = np.array([[2.0, 1.2],
                           [1.2, 1.0]])
    X = rng.multivariate_normal([1.0, -2.0], Sigma_true, size=500)
    
    # 1) centre: PCA is about spread, not location
    Xc = X - X.mean(axis=0)
    # 2) sample covariance, shape (d, d)
    Sigma = Xc.T @ Xc / (len(Xc) - 1)
    # 3) eigh is for symmetric matrices: ascending eigenvalues, orthonormal eigenvectors
    lam, V = np.linalg.eigh(Sigma)
    lam, V = lam[::-1], V[:, ::-1]                     # largest eigenvalue first
    
    print("eigenvalues  :", np.round(lam, 3))          # [2.719 0.188]  (truth: 2.8, 0.2)
    print("PC1          :", np.round(V[:, 0], 3))       # [0.833 0.555] up to sign (truth: (3,2)/sqrt(13))
    print("explained    :", np.round(lam / lam.sum(), 3))  # [0.935 0.065]
    print("eigen eq holds:", np.allclose(Sigma @ V[:, 0], lam[0] * V[:, 0]))   # True
    
    # 4) project onto PC1, then rebuild a rank-1 version of the data
    z = Xc @ V[:, 0]                                   # one score per sample
    X_hat = np.outer(z, V[:, 0])                       # n x 2 reconstruction
    print("reconstruction MSE:", round(float(np.mean((Xc - X_hat) ** 2)), 4))  # 0.0936 ~ lam2/2
    
    # 5) sanity check: same direction as scikit-learn?
    from sklearn.decomposition import PCA
    p = PCA(n_components=1).fit(X)
    print("sklearn PC1  :", np.round(p.components_[0], 3))       # [0.833 0.553]
    print("same direction:", abs(float(p.components_[0] @ V[:, 0])) > 0.999)   # True

    Read the output against the theory: the sample eigenvalues sit close to the true $2.8$ and $0.2$; PC1 is $\pm(0.833, 0.555)$, which is $(3,2)/\sqrt{13}$ β€” the direction of maximal spread; the explained ratio $0.935$ matches $2.8/3 = 0.933$; and the reconstruction error $0.094$ is almost exactly half of the discarded eigenvalue $0.188/2$ (half, because the MSE is averaged over both coordinates). The sign of an eigenvector is arbitrary β€” only the line matters.

    Block 4 β€” truncated SVD on an image. Build a smooth synthetic texture (natural images have this frequency spectrum), then reconstruct it from the top 5, 20 and 100 singular values.

    import numpy as np
    
    # a synthetic 128x128 grayscale texture: smooth fields compress, noise does not
    rng = np.random.default_rng(4)
    n = 128
    F = np.fft.fft2(rng.normal(size=(n, n)))
    fy, fx = np.fft.fftfreq(n)[:, None], np.fft.fftfreq(n)[None, :]
    r = np.hypot(fx, fy); r[0, 0] = 1e-6               # divide by frequency -> cloudy, low-rank-ish field
    img = np.real(np.fft.ifft2(F / r ** 1.6))
    img = (img - img.min()) / (img.max() - img.min())
    
    U, sv, Vt = np.linalg.svd(img, full_matrices=False)
    for k in (5, 20, 100):
        low = (U[:, :k] * sv[:k]) @ Vt[:k]             # best rank-k approximation (Eckart-Young)
        err = np.linalg.norm(img - low) / np.linalg.norm(img)
        cost = n * n / (k * (n + n + 1))               # numbers stored now vs. the full image
        print(f"rank {k:3d}   rel. error {err:.4f}   compression {cost:5.2f}x")
    # rank   5   rel. error 0.0989   compression 12.75x
    # rank  20   rel. error 0.0359   compression  3.19x
    # rank 100   rel. error 0.0025   compression  0.64x   (worse than useless: keep the pixels)

    The trade curve is the lesson: rank 5 costs 10% of the energy for a 12.75Γ— saving, rank 20 costs 3.6% for 3.19Γ—, and rank 100 is nearly lossless but costs more storage than the original (compression below 1Γ— means you should not have bothered). Compression only pays when the singular values decay β€” which is a statement about your data, not about your algorithm.

    Exercise Β· low-rank completion of a ratings matrix

    Here are ratings from 5 users on 6 films (1–5), with np.nan where a user has not seen a film. Users 1–3 mostly watch films 1–3; users 4–5 mostly watch films 4–6. Your job: predict the missing ratings, and say which unseen pair is actually worth recommending.

    • Fill the NaNs with column means, then iterate: fit a rank-2 matrix by SVD, keep the observed entries fixed, repeat until the fills stop moving.
    • Print the singular values of the fit β€” is rank 2 justified by the data, or did you pick it by hand?
    • Which missing (user, film) pair gets the highest score? Which gets the lowest? Does that match what you would predict from the block structure?
    • Two things to notice: some predictions come out below 1.0, outside the valid rating scale β€” what should a production system do about that? And what happens to the recommendations if you use rank 1? Rank 3?
    import numpy as np
    
    R = np.array([
        [5, 5, 4, 1, 1, np.nan],
        [5, 4, 5, 1, np.nan, 1],
        [4, 5, np.nan, 3, 3, np.nan],
        [np.nan, 1, 2, 5, 5, 4],
        [1, np.nan, 1, 5, 4, 5],
    ], float)                              # 5 users x 6 films, NaN = not yet seen
    mask = np.isnan(R)
    missing = list(zip(*(a.tolist() for a in np.where(mask))))
    
    M = R.copy()
    M[mask] = np.take(np.nanmean(M, axis=0), np.where(mask)[1])   # start from column means
    for _ in range(200):
        U, s, Vt = np.linalg.svd(M, full_matrices=False)
        low = (U[:, :2] * s[:2]) @ Vt[:2]                         # rank-2 model of the ratings
        new = low.copy()
        new[~mask] = R[~mask]                                     # observed ratings are facts: never move them
        if np.allclose(new, M, atol=1e-10):
            M = new
            break
        M = new
    
    print("singular values:", np.round(s, 2))   # [16.81 8.96 1.22 1.04 0.63] -> big gap after 2
    for u, j in missing:
        print(f"user {u + 1} -> film {j + 1}:  {low[u, j]:.2f}")
    
    # user 1 -> film 6:  0.66     user 3 -> film 6:  2.61
    # user 2 -> film 5:  1.35     user 4 -> film 1:  1.43
    # user 3 -> film 3:  4.53     user 5 -> film 2:  0.54

    The singular values fall off a cliff β€” $16.81,\ 8.96$, then $1.22$ β€” so two hidden tastes really do explain this matrix, and rank 2 is a property of the data rather than a guess. The recommendation is unambiguous: user 3 β†’ film 3 at 4.53 is the only missing pair the model likes; every other unseen combination is a rejection, and two of them (0.66, 0.54) are so negative the model has left the 1–5 scale entirely β€” clip predictions to the valid range in anything you ship. This is exactly how matrix completion works on real recommender systems, only with $10^6 \times 10^5$ instead of $5 \times 6$.

    Checkpoint

    Prove it, then start Module 03

    Answer first, then open the feedback

    Multiple choice β€” instant feedback

    1. Which statement about eigenvectors is correct?

    2. $A$ is a $4 \times 7$ matrix. A colleague says "the determinant of $A$ is non-zero, so $A$ is invertible." What is wrong with the statement?

    3. PCA finds…

    4. Which statement about eigendecomposition and SVD is true?

    5. Two embeddings score $u \cdot v = 48$. Which claim is justified?

    6. $X$ is $n \times d$, $W$ is $d \times k$, and $b$ is a vector of length $k$. What is row $i$ of $XW + \mathbf{1}b^\top$?

    Open questions β€” answer aloud, without notes

    1. $X$ is $5000 \times 200$ and $W$ is $200 \times 64$. What is the shape of $XW$? What does row $i$ of it contain, in English?
    2. A dataset has 200 features. What is the shape of the covariance matrix, and of $X_c^\top X_c$? Which one has one entry per feature pair?
    3. $A$ is $3 \times 5$ with full row rank. What is the shape of $AA^\top$? For a given $b \in \mathbb{R}^3$, does $Ax = b$ have a solution? Is it unique?
    4. Write the Lagrange step that turns "maximise $u^\top \Sigma u$ subject to $\|u\|=1$" into $\Sigma u = \lambda u$. Why must $\Sigma$ be symmetric for the argument to give real directions?
    5. Why does squaring a matrix β€” computing $X^\top X$ instead of working with $X$ β€” make numerical problems worse? Give the condition-number relation.
    6. You have 10 000 text documents as vectors. When do you reach for cosine distance, and when is Euclidean the right metric? What breaks if you pick wrong?
    7. Explain in one sentence why a 2-D rotation matrix has no real eigenvectors, and say what the complex eigenvalues of unit magnitude represent.
    8. You double every entry of a dataset. What happens to the covariance matrix, its eigenvalues, its eigenvectors, and the PCA directions? Which quantities are unchanged?

    Re-answer these in 1 day, then 3 days, then 7 days β€” from memory, in writing. Ten minutes of recall on day three beats an hour of re-reading today.

    Continue in your ML notebook

    This module is the theory; the algorithms that use it live next door. ML module 02 Β· The math you actually use shows the same vectors, dot products and matrix products as working code in the modelling workflow. ML module 09 Β· Unsupervised learning & PCA is the practical twin of Sections 11–12: fit, choose $k$, visualise, and know when PCA is the wrong tool. ML module 10 Β· Neural networks & deep learning is where "$A\mathbf{x}$ as a transformation" becomes a layer, where $XW$ becomes a batched forward pass, and where the shapes you checked here keep you from shipping a silent bug.