S018 · Linear Algebra II — Matrices, Transforms, Eigenvalues
Matrices as linear transformations, matrix multiplication as function composition, and eigenvalues as the axes a transform respects — the shape of every neural net.
🎯 Read a matrix as a linear transformation, compose transformations by multiplying matrices, and know what eigenvalues/eigenvectors tell you about the transform's behaviour.
Why this session exists
A neural network is nothing but stacked matrix multiplications and non-linearities. A rendered 3-D scene is a sequence of matrix transformations. PCA, SVD, PageRank, JPEG, quantum states — all matrices. The reason matrices show up everywhere is that they are the only way to write down a linear transformation of a vector space. Get past "matrix = grid of numbers" to "matrix = function that stretches, rotates, and squashes space" and every downstream ML paper stops feeling like a wall of Greek letters.
- Read a matrix as a function that maps input vectors to output vectors.
- Multiply two matrices by hand for 2×2 and 3×3 cases (and know why row × column).
- Recognise identity, transpose, inverse, and diagonal — and say what each does geometrically.
- Explain eigenvalues and eigenvectors as the ‘axes the transform respects’ with a picture.
- Use NumPy to multiply matrices, solve linear systems, and find eigenvalues.
Prerequisites
- S017 · Vectors — dot product IS the atom of matrix multiplication.
- Comfortable with element-wise math and Σ notation.
(a) Intuition · 5 min
Imagine a rubber sheet with a grid drawn on it. You pinch two corners and stretch it — the grid deforms. Straight lines stay straight, parallel lines stay parallel, the origin stays put. That constrained stretch is a linear transformation, and it is entirely described by where the two basis vectors [1,0] and [0,1] end up. Those two ending points are the two columns of a 2×2 matrix.
Multiply the matrix by any point on the original sheet and it tells you where that point moved to. Rotate the sheet 90°? Matrix. Stretch it 2× vertically? Matrix. Shear it? Matrix.
In code, a matrix is a 2-D array. But its meaning is a function. A @ x in NumPy takes vector x and returns Ax — the transformed vector. Every operation you'll use — matrix-matrix multiply, inverse, eigendecomposition — is a fact about that function.
The columns of A are literally "where the basis vectors go." That's the one sentence that unlocks the whole subject.
The three views of a matrix
- A grid of numbers — m rows × n columns. This is the storage view.
- A linear function ℝⁿ → ℝᵐ — takes a length-n vector, returns a length-m vector. This is the transformation view.
- A composition of column vectors — the k-th column of A is where the k-th basis vector of the input space lands. This is the ‘how do I build one?’ view.
A quick history
- 200 BCEThe Nine Chapters (China)Chinese mathematicians solve simultaneous linear equations with a proto-matrix method 2000 years before Europe.
- 1858Cayley · Memoir on the Theory of MatricesArthur Cayley writes down matrix multiplication and inverse. The name ‘matrix’ was Sylvester's.
- 1929von Neumann · quantum mechanics as matricesJohn von Neumann formulates QM as linear operators on Hilbert space. Matrices become central to physics.
- 1947SVD · Beltrami/Jordan much earlier, but computable nowThe Singular Value Decomposition — the single most-used matrix factorisation in ML.
- 1998PageRank · Brin & PageThe internet ranked by the principal eigenvector of a hyperlink matrix. Google is born.
- 2017+Transformers · attention as matrix multipliesGPT/BERT do trillions of matrix multiplications per training step. GPUs exist because matrices do.
(b) Visual walkthrough · 15 min
A matrix transforms space
The columns of A are exactly where the basis vectors land. Every other vector's destination is a weighted combination of those two column-destinations.
The matrix multiplication formula, unpacked
(m × k) · (k × n) → (m × n). Inner k must match; outer m and n are the output shape.
Entry (i, j) of the result = dot product of row i of A with column j of B.
Every cell of the product is a scalar; it's the ‘answer’ to ‘what does row i of A × column j of B evaluate to?’
A · B is the function ‘first apply B, then apply A.’ Order matters and reads right-to-left.
The special matrices worth memorising
Six matrices you'll see every day
Solving Ax = b: three interpretations, one answer
Intersection of hyperplanes
- Each row of A is a linear equation
- Each equation is a hyperplane in ℝⁿ
- Solution x is where they all meet
- Sensitive to picture-blowing-up in high dims
Linear combination of columns
- b is a linear combination of columns of A
- Solve for the weights
- Cleaner geometric intuition
- Preferred view for ML
Undo the transform
- A maps x → b
- We want x such that A applies to it gives b
- x = A⁻¹ b (when A is invertible)
- Numerical: `np.linalg.solve(A, b)` (never invert!)
Eigenvalues and eigenvectors — geometric meaning
Eigenvector: a vector whose direction A does NOT change — A only stretches or shrinks it. Eigenvalue λ: the stretch factor.
"A matrix is a 2D array of numbers — a grid, like a spreadsheet or a table. Matrix multiplication is a slightly odd rule you memorise: rows times columns."
A matrix is a linear transformation written in coordinates. Its columns are where the basis vectors land. Matrix multiplication is function composition — AB means "do B, then A" — and every property that looks arbitrary (why the inner dimensions must match, why it isn't commutative, why the identity looks like that) falls out of that single fact.
Because the grid model is sufficient for storage and for the mechanics of computing a product, and because in data work you genuinely do use matrices as tables of records. The model fails the moment you need to reason rather than compute. Under the grid view, AB ≠ BA is a strange quirk to remember; under the transformation view it is obvious, because rotating-then-stretching is visibly not the same as stretching-then-rotating. Similarly "singular" sounds like a numerical accident, when it actually means the transformation collapsed a dimension and destroyed information — which is why it cannot be inverted, and why a near-singular matrix makes a regression's coefficients wildly unstable. Everything mysterious about linear algebra becomes mechanical once you stop seeing grids.
The columns literally are the images of the basis vectors — check it:
import numpy as np
A = np.array([[0., -1.], [1., 0.]]) # 90 degree rotation
print(A @ np.array([1., 0.])) # [0, 1] <- column 1 of A
print(A @ np.array([0., 1.])) # [-1, 0] <- column 2 of A
B = np.array([[2., 0.], [0., 1.]]) # stretch x by 2
print(A @ B)
print(B @ A) # different: order is composition orderWhy does a matrix fail to be invertible exactly when its determinant is zero? These look like unrelated facts — one about solving equations, one about a strange alternating sum.
- 1A matrix maps input vectors to output vectors. Inverting it means recovering the unique input that produced a given output.forced by · an inverse function must be well defined, so each output needs exactly one preimage
- 2The determinant measures how the transformation scales volume: the unit cube maps to a parallelepiped whose signed volume is
det(A).forced by · linearity means the volume scaling factor is the same everywhere, so one number suffices - 3If
det(A) = 0, the output volume is zero — the entire input space has been flattened onto a lower-dimensional subspace (a plane, a line, a point).forced by · only a degenerate shape has zero volume, which means the columns became linearly dependent - 4Flattening is many-to-one: infinitely many distinct inputs map to the same output, because an entire direction was crushed to zero.forced by · reducing dimension cannot be injective — that is the pigeonhole argument in continuous form
- 5Therefore no inverse function can exist. There is no rule that recovers which of infinitely many preimages you started from; the information was genuinely destroyed, not merely hidden.forced by · an inverse must map each output back to a single input, and there isn't one
Therefore "determinant zero" and "not invertible" are the same statement viewed geometrically and algebraically: the transformation lost a dimension. And det(AB) = det(A)det(B) stops being a formula to memorise — composing two transformations multiplies their volume scalings, which is the only thing it could possibly do.
And note what this predicts, and it is the practically important part: a determinant near zero means nearly flattened, so a tiny change in output corresponds to a huge change in input. That is ill-conditioning, and it is exactly why perfectly collinear features make X'X singular and near-collinear features make regression coefficients enormous, unstable, and sign-flipping between refits. It also predicts the fix: ridge regularisation adds λI, pushing the eigenvalues away from zero and restoring invertibility by construction.
Read every matrix as an action on space. Its columns tell you where the basis vectors go, and because the transformation is linear, that's enough to determine where everything goes. Multiplying Ax is applying the verb to a vector; multiplying AB is chaining two verbs, applied right to left.
Once matrices are verbs, the vocabulary decodes itself: the identity is "do nothing", the inverse is "undo", the determinant is "how much does this squash or expand", singular is "collapsed a dimension", transpose swaps the roles of input and output space, and eigenvectors are the directions the verb only stretches without turning.
- Inner dimensions must match because the output space of the first transformation must be the input space of the second. Shape errors are type errors about which space you're in.
AB ≠ BAbecause composition order matters. This is not a quirk; it is why the order of operations in a neural network layer stack is meaningful.- Never compute an explicit inverse to solve
Ax = b. Use a solver (np.linalg.solve, or a decomposition) — it's faster and far more numerically stable, since forming the inverse amplifies error. - Eigen/SVD decompositions answer "what does this transformation do, in its own natural coordinates?" — which is why SVD underlies PCA, low-rank approximation, and recommender factorisation alike.
Fire this model the moment you see: a shape mismatch error · LinAlgError: Singular matrix · regression coefficients that are huge or flip sign between runs · a condition number in a warning · PCA, SVD, or embedding factorisation · a transformer's attention as QK'.
You need to solve a large least-squares problem Ax ≈ b. Normal equations, QR/SVD decomposition, or iterative methods?
A'A is small when features are far fewer than rows, and it can be accumulated in one streaming pass over the dataA'A squares the condition number, so it roughly halves the precision you have to work with — near-collinear features that QR handles fine will produce garbage hereA, so the condition number is never squared; SVD additionally reveals rank and provides the pseudo-inverse for genuinely rank-deficient problemsUse a library's least-squares routine (which will pick QR or SVD) unless scale forces you elsewhere, and check the condition number before trusting any coefficient. The recurring production mistake is not choosing the wrong solver — it's reporting coefficients from an ill-conditioned fit as though they were meaningful, when collinearity has made their individual values essentially arbitrary while the predictions remain fine.
That distinction is worth holding onto: ill-conditioning corrupts interpretation long before it corrupts prediction. A model can score well and still have coefficients you must not explain to a stakeholder.
(c) Hands-on · 25 min
You'll implement matrix multiplication from scratch, compare to NumPy, solve a real linear system, and compute eigenvalues to find principal directions of a 2-D dataset. Save as matrices_demo.py.
Run it:
uv run --with numpy python matrices_demo.pyExpected output:
What each block does
Anatomy of the code
import numpy as np
R = np.array([[0.0, -1.0], [1.0, 0.0]]) # 90° rotation
print("R @ R.T =")
print(R @ R.T) # should be identity
print("det(R) =", np.linalg.det(R)) # should be 1
theta = np.pi / 4 # 45°
R45 = np.array([[np.cos(theta), -np.sin(theta)],
[np.sin(theta), np.cos(theta)]])
v = np.array([1.0, 0.0])
print("R45 v =", R45 @ v) # should have length 1
print("length =", np.linalg.norm(R45 @ v)) # exactly 1 — rotations preserve length(d) Production reality · 15 min
Larry Page and Sergey Brin needed to rank the whole web. Their idea: a page's importance is the sum of the importances of pages linking to it, weighted by how many links each source has. This is a system of equations: importance vector r = M · r, where M is a huge stochastic matrix of link probabilities.
The solution is the dominant eigenvector of M (eigenvalue 1). For 150M pages, computing that directly is impossible.
x = np.linalg.inv(A) @ b to solve Ax = b. On tiny well-conditioned problems, it works. On a 5000 × 5000 problem with realistic data, they get gibberish answers or NaN. Blames the algorithm.np.linalg.solve(A, b) or (for repeated solves) lu, piv = scipy.linalg.lu_factor(A); scipy.linalg.lu_solve((lu, piv), b). The inverse amplifies floating-point noise; solve doesn't. For overdetermined systems, use np.linalg.lstsq. For symmetric positive definite (covariance matrices), use np.linalg.cholesky.W @ x for x @ W. Shapes still match. Training runs, loss goes down more slowly than before, model accuracy drops 5 points. Nobody notices until much later.y = W @ x # W: (d_out, d_in), x: (batch, d_in) → transpose? — use W.T.Where this shows up in the rest of the plan
(e) Recall + stretch · 10 min
Explain-out-loud test
- What does a matrix do to a vector, in plain English?
- Why is
A @ Bnot the same asB @ A? - What is an eigenvector, and why does that word appear in every PCA paper?
What comes next
Hub: The 6-Month Learning Plan
Part of a 130-session evergreen learning series. Session structure: intuition → visual → hands-on → production war stories → recall. Duration: 90 minutes.