Almost every machine learning model is a pipeline of linear algebra: data is stored as matrices, models multiply those matrices by learned weights, and training adjusts the weights using gradients that are themselves vectors and matrices. You do not need a research-level background to work with these models, but you do need to recognize the handful of ideas that keep reappearing.
This guide collects 101 of those ideas in the order you would naturally learn them. Each entry gives a precise definition, explains where it shows up in machine learning and AI, and, where it helps, includes a small example. The NumPy snippets were run with NumPy 2.3, and the output shown under each snippet is what that code printed.
How to use this list: read the section headings first, then jump to whatever you are currently working on. If an entry uses an idea you have not met yet, it is almost always defined in an earlier entry.
Vectors and vector spaces
1. Scalars, vectors, matrices and tensors
A scalar is a single number, a vector is an ordered list of numbers, a matrix is a rectangular grid of numbers, and a tensor is the general name for an array with any number of axes. In machine learning the number of axes is often called the array's rank or ndim (not to be confused with matrix rank, entry 51).
A batch of 32 sentences, each 128 tokens long, with 768 numbers per token, is a tensor of shape .
2. A vector as a feature representation
A data point becomes a vector by listing its measurable features in a fixed order. A house with 3 bedrooms, 2 bathrooms and 140 square meters could be . Once data are vectors, "similar data points" can be measured with geometry, which is the premise behind nearest-neighbor methods, clustering and embeddings.
Feature order and scale matter: swapping two features changes the meaning of every weight, and a feature measured in large units can dominate distances (see entry 16).
3. Vector addition and scalar multiplication
Vectors of the same length add component by component, and multiplying by a scalar scales every component:
Every gradient-descent step (entry 92) is exactly these two operations: scale the gradient by the learning rate, then add it to the weights.
4. Linear combination
A linear combination of vectors is any sum . A linear model's prediction is a linear combination of features, and a matrix-vector product is a linear combination of the matrix's columns (entry 28).
5. Vector space
A vector space is a set of objects that can be added together and multiplied by scalars while staying in the set, with the usual rules (associativity, a zero vector, additive inverses, distributivity). is the vector space you will use most, but functions, polynomials and matrices of a fixed shape also form vector spaces.
6. Subspace
A subspace is a subset of a vector space that contains the zero vector and is closed under addition and scalar multiplication. A line or plane through the origin in is a subspace; a plane that misses the origin is not. Column spaces and null spaces (entries 49–50) are the subspaces that matter most in practice.
7. Span
The span of a set of vectors is the set of all their linear combinations. The span of and is the -plane in . In a linear regression, the predictions the model can possibly produce are exactly the span of the feature columns.
8. Linear independence
Vectors are linearly independent if the only combination that gives zero is the one with all coefficients zero:
If one feature column is a combination of others (for example, a "total price" column equal to "price" plus "tax"), the columns are dependent and regression weights are no longer uniquely determined (entry 53).
9. Basis
A basis is a linearly independent set that spans the space. Every vector in the space can be written in exactly one way as a combination of basis vectors, and those coefficients are its coordinates in that basis. The standard basis of is , , .
10. Dimension
The dimension of a space is the number of vectors in any of its bases. "Embedding dimension 768" means each token is represented by coordinates in a 768-dimensional space. Dimensionality reduction (entries 80–84) looks for a lower-dimensional subspace that keeps most of the useful information.
Norms and distances
11. The L2 (Euclidean) norm
The L2 norm is the ordinary length of a vector:
For , . It is the norm behind mean squared error, weight decay and Euclidean distance.
12. The L1 norm
The L1 norm sums absolute values: . For it is . Penalizing the L1 norm of model weights (lasso) tends to push many weights to exactly zero, which gives sparse, easier-to-interpret models.
13. The max (L-infinity) norm
The max norm is the largest absolute component: . It appears in adversarial machine learning, where an "-bounded" attack is often one that changes no single input value (for example, a pixel) by more than .
14. The general p-norm
All three norms above belong to one family:
import numpy as np
x = np.array([3.0, -4.0])
print(np.linalg.norm(x, 1), np.linalg.norm(x, 2), np.linalg.norm(x, np.inf))
7.0 5.0 4.0
15. Unit vectors and normalization
A unit vector has norm 1. Dividing a nonzero vector by its norm, , keeps its direction and discards its length. Normalizing embeddings to unit length turns the dot product into cosine similarity (entry 21), which is why many retrieval systems store normalized vectors.
16. Euclidean distance
The distance between two points is the norm of their difference: . k-nearest neighbors and k-means clustering both rely on it. Because distance mixes all features together, features are usually standardized first so that a feature measured in thousands does not drown out one measured in fractions.
17. Norm penalties as regularization
Adding a norm of the weights to the loss discourages large or unnecessary weights:
The hyperparameter controls the trade-off between fitting the training data and keeping the weights small. Ridge regression even has a closed-form solution (entry 67).
18. The Frobenius norm
The Frobenius norm treats a matrix as one long vector:
It measures reconstruction error in low-rank approximation (entry 80) and in matrix factorization recommenders (entry 85).
Dot products and similarity
19. The dot product
The dot product multiplies matching components and adds the results:
For and , . A single neuron computes a dot product between its weights and its inputs, then adds a bias.
20. The geometric meaning of the dot product
The dot product also equals the product of the lengths times the cosine of the angle between the vectors:
A large positive value means the vectors point in similar directions, zero means they are perpendicular, and a negative value means they point in roughly opposite directions.
21. Cosine similarity
Cosine similarity keeps only the angle:
It ranges from to and ignores vector length, which is useful when length reflects something like document size rather than meaning.
import numpy as np
u = np.array([1.0, 2.0, 3.0])
v = np.array([2.0, 4.0, 6.5])
w = np.array([-3.0, 0.0, 1.0])
def cosine(a, b):
return a @ b / (np.linalg.norm(a) * np.linalg.norm(b))
print(round(cosine(u, v), 4), round(cosine(u, w), 4))
0.9993 0.0
22. Orthogonal vectors
Two vectors are orthogonal when their dot product is zero. Orthogonal directions carry non-overlapping information, which is why principal components (entry 82) and the columns of orthogonal matrices (entry 57) are so convenient to work with.
23. Embeddings and nearest-neighbor search
An embedding maps an item such as a word, image or document to a vector so that related items end up close together. Word-vector models such as those of Mikolov et al. (2013) were evaluated on how well vector similarity captured syntactic and semantic word relationships. Semantic search, recommendation and retrieval-augmented generation all reduce to the same linear algebra: embed the query, then find the stored vectors with the highest dot product or cosine similarity.
24. The outer product
The outer product of and is the matrix , whose entry is . Every outer product has rank 1, and every matrix is a sum of rank-1 outer products, which is exactly what the SVD (entry 78) writes down.
25. The Hadamard (element-wise) product
The Hadamard product multiplies matching entries of two same-shaped arrays. It is not matrix multiplication. Gates in LSTMs, attention masks and dropout masks are all applied with element-wise products; in NumPy it is A * B, while matrix multiplication is A @ B.
26. The Cauchy–Schwarz inequality
For any two vectors,
This is why cosine similarity can never leave , and it is a workhorse in proofs about learning algorithms, for example bounding how much a prediction can change when the input changes.
Matrices as linear maps
27. The data (design) matrix
A dataset with examples and features is stored as an matrix : one row per example, one column per feature. Most libraries follow this "rows are samples" convention, so a whole batch of predictions from a linear model is the single product .
28. Matrix-vector product as a combination of columns
The product can be read two ways: each output entry is a dot product of a row of with , or, equivalently, the whole output is a linear combination of the columns of weighted by the entries of :
The column view explains why the possible outputs of form the column space of (entry 49).
29. Linear maps
A function is linear if and . Every linear map between finite-dimensional spaces can be written as multiplication by a matrix, so "matrix" and "linear transformation" are two views of the same object. Rotations, scalings, projections and shears are all linear maps.
30. Matrix multiplication is composition
If maps to and then maps that to , the combined map is the single matrix . The entry is the dot product of row of with column of , and the inner dimensions must match: an matrix times a matrix gives an matrix.
31. Matrix multiplication is not commutative
In general , and one of the two products may not even be defined. Order matters in code too: X @ W and W @ X are different computations, and shape errors in neural network code are very often a transposed or swapped product.
import numpy as np
A = np.array([[1, 2], [0, 1]])
B = np.array([[0, 1], [1, 0]])
print(A @ B)
print(B @ A)
[[2 1]
[1 0]]
[[0 1]
[1 2]]
32. The identity matrix
The identity matrix has ones on the diagonal and zeros elsewhere, and . Residual connections in deep networks compute , which is the identity map plus a learned correction; at initialization this makes it easy for a very deep network to behave close to the identity.
33. The transpose
The transpose swaps rows and columns: . Two rules come up constantly: , and . In backpropagation, gradients flow backward through a layer by multiplying with .
34. Symmetric matrices
A matrix is symmetric if . Covariance matrices, Gram matrices , kernel matrices and Hessians of smooth functions are all symmetric, and symmetric matrices have especially well-behaved eigenvalues (entry 73).
35. Diagonal matrices
A diagonal matrix has nonzero entries only on its main diagonal. Multiplying by simply scales coordinate by , so diagonal matrices are cheap to store, multiply and invert. Many matrix decompositions (eigendecomposition, SVD) exist precisely to turn a general matrix into a diagonal one in a well-chosen basis.
36. A fully connected layer
A dense (fully connected) neural network layer computes
where is a weight matrix, a bias vector and a nonlinearity applied element-wise. A layer mapping 784 inputs to 128 outputs has a weight matrix, which is weights plus 128 biases.
37. Linear versus affine maps
is linear, but is affine: it is linear plus a shift, and it does not map zero to zero. A common trick appends a constant 1 to every input so the bias becomes one extra column of , turning the affine map back into a purely linear one.
38. Why stacked linear layers collapse
Two linear layers with no nonlinearity between them are equivalent to one: . However many such layers you stack, the network can only represent linear functions. Nonlinear activations such as ReLU are what give depth its extra expressive power.
39. The trace
The trace is the sum of the diagonal entries, . It equals the sum of the eigenvalues, is unchanged by cyclic permutations (), and gives compact formulas such as . The cyclic property is used constantly when deriving matrix gradients.
40. Batched matrix multiplication
Deep learning frameworks apply the same matrix product to many inputs at once. With a batch of shape and weights of shape , X @ W has shape . For stacks of matrices, @ multiplies the last two axes and broadcasts over the leading ones.
import numpy as np
rng = np.random.default_rng(0)
X = rng.normal(size=(32, 10, 64)) # batch, sequence, features
W = rng.normal(size=(64, 16))
print((X @ W).shape)
(32, 10, 16)
Systems of equations, inverses and determinants
41. Linear systems Ax = b
A linear system asks for the with . It has exactly one solution, infinitely many, or none, depending on whether lies in the column space of and whether has a nontrivial null space. Fitting a model often amounts to solving (or approximately solving) such a system.
42. Gaussian elimination
Gaussian elimination solves by subtracting multiples of rows to create zeros below the diagonal, then back-substituting. It costs on the order of operations for an system and is the algorithm underneath most direct solvers.
43. LU decomposition
Elimination can be recorded as a factorization (usually with row swaps, ), where is lower triangular and is upper triangular. Once is factored, each new right-hand side costs only two cheap triangular solves.
44. The matrix inverse
A square matrix is invertible if there is a matrix with . For a matrix,
The inverse is mainly a theoretical tool; in code you rarely compute it explicitly (entry 47).
45. The determinant
The determinant is the factor by which the linear map scales area (in 2D) or volume (in higher dimensions), with a sign that records whether orientation flips. , and is invertible exactly when . Normalizing flows use log-determinants of Jacobians (entry 89) to track how a transformation stretches probability density.
46. Singular matrices
A square matrix with is singular: it squashes some direction to zero, so information is lost and the map cannot be undone. In practice, matrices that are nearly singular are the real danger, because they make solutions extremely sensitive to small errors (entry 69).
47. Solve, do not invert
Writing is fine on paper, but computing and then multiplying is slower and usually less accurate than solving the system directly with a factorization, as John D. Cook explains in "Don't invert that matrix" (2010). In NumPy, prefer np.linalg.solve(A, b) over np.linalg.inv(A) @ b.
import numpy as np
A = np.array([[4.0, 1.0], [2.0, 3.0]])
b = np.array([1.0, 2.0])
x = np.linalg.solve(A, b)
print(x, np.allclose(A @ x, b))
[0.1 0.6] True
48. The Moore–Penrose pseudoinverse
Non-square or singular matrices have no inverse, but every matrix has a pseudoinverse , computed from the SVD by inverting only the nonzero singular values. gives the least-squares solution of , and among all least-squares solutions it picks the one with the smallest norm. NumPy provides it as np.linalg.pinv.
Rank and the four fundamental subspaces
49. Column space
The column space of is the span of its columns, which is the set of all possible outputs . has a solution exactly when is in the column space. Least squares (entry 64) finds the point of the column space closest to when is not in it.
50. Null space
The null space of is the set of all with . If it contains a nonzero vector , then and produce identical outputs, so the inputs cannot be told apart from the outputs. For a model's weights, a nontrivial null space of the data matrix means different weight vectors make exactly the same predictions.
51. Rank
The rank of a matrix is the dimension of its column space, which always equals the dimension of its row space. A data matrix has rank at most 50; if its rank is lower, some features are redundant combinations of others.
import numpy as np
X = np.array([[1.0, 2.0, 3.0],
[2.0, 4.0, 6.1],
[0.0, 1.0, 1.0],
[1.0, 0.0, 1.0]])
X_dependent = X.copy()
X_dependent[:, 2] = X[:, 0] + X[:, 1] # third column = first + second
print(np.linalg.matrix_rank(X), np.linalg.matrix_rank(X_dependent))
3 2
52. The rank–nullity theorem
For an matrix,
Every input dimension either survives into the output (rank) or is lost in the null space. It is a quick sanity check: a matrix has rank at most 3, so its null space has dimension at least 2.
53. Full rank, multicollinearity and identifiability
When the columns of a data matrix are linearly independent ("full column rank"), the least-squares weights are unique. When features are exactly or nearly dependent, a situation statisticians call multicollinearity, the weights become non-unique or extremely unstable even though predictions may still look fine. Dropping redundant features or adding ridge regularization (entry 67) restores a unique, stable answer.
54. Low-rank matrices
A matrix of rank can be written as the product of an and an matrix, which takes numbers instead of . Many real matrices, such as user–item ratings or the weight updates during fine-tuning, are well approximated by low-rank matrices, which is the idea behind matrix factorization (entry 85) and LoRA (entry 100).
55. The four fundamental subspaces
Every matrix defines four subspaces: the column space and left null space (in ), and the row space and null space (in ). Within each pair the two subspaces are orthogonal complements. Gilbert Strang's MIT course 18.06 is organized around this picture, and it explains at a glance when systems are solvable and when solutions are unique.
Orthogonality and projections
56. Orthonormal bases
An orthonormal set of vectors is mutually orthogonal and each has length 1. In an orthonormal basis , coordinates are just dot products: . No system needs to be solved, which is why orthonormal bases make computations both simple and numerically stable.
57. Orthogonal matrices
A square matrix whose columns are orthonormal satisfies , so . Orthogonal matrices preserve lengths and angles (); they represent rotations and reflections. Orthogonal weight initialization is used in some deep and recurrent networks because repeatedly multiplying by an orthogonal matrix neither blows up nor shrinks the signal.
58. Projection onto a vector
The projection of onto the line through is
and the leftover is orthogonal to . For and , the projection is and the leftover is indeed perpendicular to .
59. Projection onto a subspace
If the columns of are independent, the matrix that projects onto the column space of is
is symmetric and satisfies (projecting twice changes nothing). The fitted values of linear regression are , which is why statisticians call the "hat matrix".
60. The Gram–Schmidt process
Gram–Schmidt turns independent vectors into an orthonormal basis for the same span: take each vector in turn, subtract its projections onto the vectors already processed, and normalize what is left. In floating-point arithmetic the classical version can lose orthogonality, so libraries use modified Gram–Schmidt or Householder reflections instead.
61. QR decomposition
Every matrix with independent columns factors as , with having orthonormal columns and upper triangular. QR is the numerically preferred way to solve least-squares problems (entry 66), and repeated QR steps are the basis of the classical algorithm for computing eigenvalues.
import numpy as np
A = np.array([[1.0, 1.0], [1.0, 0.0], [0.0, 1.0]])
Q, R = np.linalg.qr(A)
print(np.allclose(Q.T @ Q, np.eye(2)), np.allclose(Q @ R, A))
True True
62. Change of basis
The same vector has different coordinates in different bases. If the columns of are a basis, the coordinates of in that basis satisfy , and a linear map with matrix in standard coordinates has matrix in the new basis. PCA (entry 82) is a change to the basis of principal directions.
63. Rotations preserve geometry
Because orthogonal matrices preserve dot products, rotating every vector in a dataset changes no distances or angles. This is why embeddings are only meaningful up to rotation, and why you should compare two embedding spaces with methods that first align them (for example, orthogonal Procrustes) rather than coordinate by coordinate.
Least squares and regression
64. The least-squares problem
When has no exact solution (more equations than unknowns, plus noise), least squares picks the that minimizes the squared error:
Ordinary linear regression is exactly this problem, with the design matrix and the targets.
65. The normal equations
Setting the gradient of to zero gives the normal equations:
They are compact and good for derivations, but forming squares the condition number (entry 69), so numerical libraries usually avoid them.
66. Least squares in practice
np.linalg.lstsq minimizes using an SVD-based method, and returns the minimum-norm solution when several minimizers exist. Here it fits a line to five points:
import numpy as np
x = np.array([0.0, 1.0, 2.0, 3.0, 4.0])
y = np.array([1.1, 2.9, 5.2, 7.1, 8.8])
A = np.column_stack([x, np.ones_like(x)]) # columns: slope, intercept
(slope, intercept), *_ = np.linalg.lstsq(A, y)
print(round(slope, 3), round(intercept, 3))
1.96 1.1
67. Ridge regression in closed form
Adding an L2 penalty to least squares gives
The term makes the matrix invertible even when is singular, and it shrinks the weights toward zero. Larger means more shrinkage, lower variance and more bias.
68. Residuals are orthogonal to the features
At the least-squares solution, the residual is orthogonal to every column of : . That is the normal equations restated, and it is why, when the model includes an intercept column, linear-regression residuals always sum to zero.
69. The condition number
The condition number (the ratio of the largest to smallest singular value) measures how much relative errors in the input can be amplified in the solution of . A rough rule is that you can lose about digits of accuracy. Because , solving the normal equations can lose twice as many digits as a QR or SVD approach.
import numpy as np
A = np.array([[1.0, 1.0], [1.0, 1.0001]])
print(f"{np.linalg.cond(A):.3g}", f"{np.linalg.cond(A.T @ A):.3g}")
4e+04 1.6e+09
Eigenvalues and eigenvectors
70. Eigenvalues and eigenvectors
A nonzero vector is an eigenvector of a square matrix if multiplying by only scales it:
The scale factor is the eigenvalue. Eigenvectors are the directions a linear map stretches without turning, and they describe its long-run behavior when applied repeatedly.
71. The characteristic polynomial
The eigenvalues are the roots of . For this is , so and . This is a hand-calculation tool; numerical software computes eigenvalues with iterative algorithms instead of finding polynomial roots.
72. Eigendecomposition (diagonalization)
If an matrix has independent eigenvectors, collected as the columns of , then
with the eigenvalues on the diagonal of . Powers become easy, , which explains why repeated multiplication is dominated by the largest eigenvalues, a key idea behind exploding and vanishing gradients in recurrent networks.
73. The spectral theorem
A real symmetric matrix always has real eigenvalues and an orthonormal set of eigenvectors, so
with orthogonal. Covariance matrices are symmetric, which is what makes PCA (entry 82) work so cleanly.
import numpy as np
A = np.array([[2.0, 1.0], [1.0, 2.0]])
eigenvalues, Q = np.linalg.eigh(A) # eigh is for symmetric matrices
print(eigenvalues)
print(np.allclose(Q @ np.diag(eigenvalues) @ Q.T, A))
[1. 3.]
True
74. Positive definite and semidefinite matrices
A symmetric matrix is positive definite if for every nonzero (equivalently, all eigenvalues are positive), and positive semidefinite if . Covariance matrices and Gram matrices are always positive semidefinite, and a valid kernel in a support vector machine must produce positive semidefinite kernel matrices.
75. Cholesky decomposition
A positive definite matrix factors as with lower triangular. Cholesky is about twice as fast as LU, and it is the standard way to sample from a multivariate Gaussian: if has independent standard-normal entries and , then has mean and covariance . Gaussian-process libraries also rely on it.
76. Power iteration
Multiplying a vector by over and over, and renormalizing each time, converges (under mild conditions) to the eigenvector with the largest-magnitude eigenvalue. This power iteration is simple enough to run on enormous sparse matrices, and it is the classic way to compute PageRank-style scores on a link graph.
import numpy as np
A = np.array([[2.0, 1.0], [1.0, 2.0]])
v = np.array([1.0, 0.0])
for _ in range(50):
v = A @ v
v = v / np.linalg.norm(v)
print(np.round(v, 4), round(v @ A @ v, 4)) # eigenvector and its eigenvalue
[0.7071 0.7071] 3.0
77. Markov chains and stationary distributions
A Markov chain with transition matrix (each row sums to 1) has a stationary distribution with , which is a left eigenvector with eigenvalue 1. Long-run behavior in random-walk models, MCMC samplers and PageRank is governed by this eigenvector.
SVD, PCA and dimensionality reduction
78. Singular value decomposition (SVD)
Every real matrix, square or not, factors as
where and have orthonormal columns and is diagonal with nonnegative singular values . Equivalently, , a sum of rank-1 pieces ordered by importance. NumPy's np.linalg.svd returns U, S and Vh (that is, ), with the singular values sorted in descending order.
79. The geometry of the SVD
The SVD says every linear map is a rotation (or reflection) , followed by stretching each axis by , followed by another rotation . The largest singular value is the most any unit vector can be stretched, and the number of nonzero singular values is the rank.
80. Truncated SVD and the best low-rank approximation
Keeping only the top singular values gives
By the Eckart–Young theorem, is the closest rank- matrix to in both the Frobenius and spectral norms, and the Frobenius error is . This underlies image compression demos, latent semantic analysis and many model-compression methods.
import numpy as np
rng = np.random.default_rng(0)
A = rng.normal(size=(6, 4))
U, S, Vh = np.linalg.svd(A, full_matrices=False)
k = 2
A_k = (U[:, :k] * S[:k]) @ Vh[:k, :]
print(np.isclose(np.linalg.norm(A - A_k), np.sqrt(np.sum(S[k:] ** 2))))
True
81. The covariance matrix
For a data matrix whose columns have been centered (mean subtracted), the sample covariance matrix is
Entry is the covariance between features and , and the diagonal holds the variances. It is symmetric and positive semidefinite.
82. Principal component analysis (PCA)
PCA finds the orthogonal directions along which the centered data vary most. They are the eigenvectors of the covariance matrix, or equivalently the right singular vectors of the centered data matrix, and projecting onto the top of them gives the best -dimensional linear summary of the data in the squared-error sense. Mathematics for Machine Learning (Deisenroth, Faisal and Ong) devotes a full chapter to deriving it.
import numpy as np
rng = np.random.default_rng(1)
t = rng.normal(size=200)
X = np.column_stack([t, 2 * t + 0.1 * rng.normal(size=200)]) # nearly 1-D data
Xc = X - X.mean(axis=0)
_, S, Vh = np.linalg.svd(Xc, full_matrices=False)
explained = S**2 / np.sum(S**2)
print(np.round(np.abs(Vh[0]), 3), np.round(explained, 4))
[0.446 0.895] [9.996e-01 4.000e-04]
83. Explained variance
The variance captured by principal component is proportional to (or to the covariance eigenvalue ), so the explained variance ratio is . In the example above, the first component explains almost all of the variance because the data lie close to a line. Choosing so that the cumulative ratio passes a threshold such as 95% is a common heuristic, not a rule.
84. Whitening
Whitening transforms data so its covariance becomes the identity: rotate onto the principal axes, then divide each coordinate by its standard deviation, . Whitened features are uncorrelated with unit variance, which can make some learning algorithms better conditioned. Directions with tiny variance get hugely amplified, so a small constant is usually added to the eigenvalues first.
85. Matrix factorization for recommendations
A user–item rating matrix (users by items) can be approximated as , where each row of is a user's vector of latent factors and each row of is an item's. A predicted rating is a dot product . Because most ratings are missing, the factors are fitted only to observed entries, usually with gradient descent or alternating least squares rather than a plain SVD.
86. The spectral norm
The spectral norm is the largest factor by which can stretch a vector. A layer is Lipschitz with constant , so constraining spectral norms bounds how sensitive a network is to input changes. Spectral normalization, used to stabilize GAN discriminators, divides each weight matrix by an estimate of its spectral norm (computed with power iteration, entry 76).
Matrix calculus for training models
87. The gradient
For a scalar function of a vector, the gradient collects all partial derivatives:
It points in the direction of steepest increase, and its length is the rate of increase in that direction. Training a model means following the negative gradient of the loss.
88. Two gradients worth memorizing
Two identities cover a surprising amount of machine learning:
For symmetric the first becomes . Setting the second to zero gives the normal equations (entry 65).
import numpy as np
rng = np.random.default_rng(2)
X, y, w = rng.normal(size=(5, 3)), rng.normal(size=5), rng.normal(size=3)
loss = lambda w: np.sum((X @ w - y) ** 2)
analytic = 2 * X.T @ (X @ w - y)
h = 1e-6
numeric = np.array([(loss(w + h * e) - loss(w - h * e)) / (2 * h) for e in np.eye(3)])
print(np.allclose(analytic, numeric, atol=1e-5))
True
89. The Jacobian
For a vector-valued function , the Jacobian is the matrix of partial derivatives . It is the best linear approximation of near a point: . For a linear layer , the Jacobian is simply .
90. The Hessian
The Hessian of a scalar function is the symmetric matrix of second derivatives, . Its eigenvalues describe the curvature of the loss surface: large eigenvalues mean steep, narrow valleys where a big learning rate overshoots, and mixed-sign eigenvalues mean a saddle point. For least squares, the Hessian is the constant matrix .
91. The chain rule as Jacobian products (backpropagation)
For a composition , the Jacobians multiply: . Backpropagation evaluates this product from the loss backward, multiplying a row vector (the gradient so far) by one Jacobian at a time. That ordering is far cheaper than forming the full Jacobian matrices, because each step is a vector–matrix product rather than a matrix–matrix product.
92. Gradient descent
Gradient descent repeatedly updates the parameters with
where is the learning rate. For a quadratic loss the method converges only if , where is the largest Hessian eigenvalue, and it converges slowly when the condition number of the Hessian is large. Optimizers such as momentum and Adam were designed largely to cope with this ill-conditioning.
93. Convexity and positive semidefinite Hessians
A twice-differentiable function is convex exactly when its Hessian is positive semidefinite everywhere. Convex losses, such as least squares, ridge and logistic regression, have no bad local minima, so gradient descent can reach the global minimum. Deep network losses are not convex, which is one reason their training behavior is harder to analyze.
Tensors and efficient computation
94. Tensor shapes in deep learning
Most deep learning bugs are shape bugs, so it pays to name every axis. A transformer's hidden states typically have shape , image batches are in PyTorch's default layout, and attention scores have shape .
95. Broadcasting
Broadcasting lets arrays of different shapes combine without copying data. NumPy compares shapes from the last axis backward; two dimensions are compatible when they are equal or one of them is 1, and missing leading dimensions count as 1. Adding a bias vector to every row of a batch is the classic case; Deep Learning (Goodfellow, Bengio and Courville) describes the same convention for adding a vector to a matrix.
import numpy as np
X = np.arange(6.0).reshape(3, 2) # 3 examples, 2 features
mu = X.mean(axis=0) # shape (2,)
print(X - mu) # (3, 2) - (2,) broadcasts over rows
[[-2. -2.]
[ 0. 0.]
[ 2. 2.]]
96. Einstein summation (einsum)
einsum names each axis with a letter and sums over letters that disappear from the output. It expresses many linear algebra operations in one readable line: "ij,j->i" is a matrix-vector product, "ij,jk->ik" a matrix product, "bqd,bkd->bqk" a batched set of all query–key dot products.
import numpy as np
rng = np.random.default_rng(3)
Q = rng.normal(size=(2, 4, 8)) # batch, queries, dim
K = rng.normal(size=(2, 5, 8)) # batch, keys, dim
scores = np.einsum("bqd,bkd->bqk", Q, K)
print(scores.shape, np.allclose(scores, Q @ K.transpose(0, 2, 1)))
(2, 4, 5) True
97. The cost of matrix multiplication
Multiplying an matrix by a matrix takes multiply–add pairs, usually counted as floating-point operations. A single by product is therefore about operations. Because matrix products dominate the cost of training and running neural networks, hardware accelerators are built around fast matrix multiplication.
Linear algebra inside modern AI models
98. Scaled dot-product attention
The core of the Transformer (Vaswani et al., 2017) is a few matrix products:
Each row of holds one query's dot products with every key (entry 19), softmax turns each row into weights that sum to 1, and multiplying by takes weighted averages of the value vectors. The paper explains the factor: if query and key components are independent with mean 0 and variance 1, their dot product has variance , and large dot products push softmax into regions with extremely small gradients.
import numpy as np
def attention(Q, K, V):
scores = Q @ K.T / np.sqrt(K.shape[-1])
scores = scores - scores.max(axis=-1, keepdims=True) # stable softmax
weights = np.exp(scores)
weights = weights / weights.sum(axis=-1, keepdims=True)
return weights @ V, weights
rng = np.random.default_rng(4)
Q, K, V = rng.normal(size=(3, 8)), rng.normal(size=(5, 8)), rng.normal(size=(5, 16))
out, weights = attention(Q, K, V)
print(out.shape, np.allclose(weights.sum(axis=1), 1.0))
(3, 16) True
99. Multi-head attention
Instead of one attention operation, multi-head attention projects the inputs with several learned matrices and runs attention in parallel in each projected subspace:
The base model in the original paper used and heads, so each head works in a -dimensional subspace. Each head is free to attend to different relationships, and all of it is still just matrix multiplication.
100. Low-rank adaptation (LoRA)
LoRA (Hu et al., 2021) fine-tunes a large model by freezing a pretrained weight matrix and learning a low-rank update:
starts as random Gaussian and as zero, so the update is zero at the start of training, and the update is scaled by . For a matrix with , and together hold trainable numbers instead of about 16.8 million. The paper reports up to 10,000 times fewer trainable parameters than full fine-tuning of GPT-3 175B.
101. Numerical precision and stability
Real computations use floating-point numbers, so algebraically equal formulas can give different answers. A few habits prevent most problems: subtract the maximum before exponentiating in softmax (as in entry 98), solve systems instead of inverting (entry 47), prefer QR or SVD over normal equations for ill-conditioned problems (entry 69), and compare floats with tolerances (np.allclose) rather than ==. Lower-precision formats such as float16 and bfloat16 make these habits even more important.
import numpy as np
print(0.1 + 0.2 == 0.3, np.isclose(0.1 + 0.2, 0.3))
z = np.array([1000.0, 1001.0, 1002.0])
with np.errstate(over="ignore", invalid="ignore"):
naive = np.exp(z) / np.exp(z).sum()
stable = np.exp(z - z.max()) / np.exp(z - z.max()).sum()
print(naive, np.round(stable, 4))
False True
[nan nan nan] [0.09 0.2447 0.6652]
Common mistakes
- Confusing
*with@. In NumPy and PyTorch,*is the element-wise (Hadamard) product and@is matrix multiplication (entries 25 and 30). - Mixing up the two meanings of "rank". A tensor's number of axes and a matrix's linear-algebra rank are different things (entries 1 and 51).
- Computing inverses to solve systems. Use a solver or least-squares routine instead (entries 47 and 66).
- Forgetting to center data before PCA. Without subtracting the mean, the first component mostly points at the mean rather than along the direction of greatest variance (entry 82).
- Comparing raw distances between unscaled features. Standardize first, or the feature with the largest units dominates (entry 16).
- Assuming that a small error in the inputs means a small error in the output. Check the condition number when results look unstable (entry 69).
Next steps
- Practice the algebra behind these ideas with 150 algebra problems with solutions.
- Keep the core identities at hand with 100 mathematics formulas every student should know.
- See where covariance, regression and hypothesis tests show up in practice in 100 probability and statistics examples.
- Speed up hand calculations with 101 math tricks to solve problems faster.
- Browse more writing on mathematics and engineering, including external blogs in the community directory.
References
- Deisenroth, M. P., Faisal, A. A., & Ong, C. S. (2020). Mathematics for Machine Learning. Cambridge University Press. Free PDF: mml-book.github.io
- Goodfellow, I., Bengio, Y., & Courville, A. (2016). Deep Learning, Chapter 2: Linear Algebra. MIT Press. deeplearningbook.org
- Strang, G. 18.06SC Linear Algebra (Fall 2011). MIT OpenCourseWare. ocw.mit.edu
- Vaswani, A., Shazeer, N., Parmar, N., et al. (2017). "Attention Is All You Need." arXiv:1706.03762. arxiv.org
- Hu, E. J., Shen, Y., Wallis, P., et al. (2021). "LoRA: Low-Rank Adaptation of Large Language Models." arXiv:2106.09685. arxiv.org
- Mikolov, T., Chen, K., Corrado, G., & Dean, J. (2013). "Efficient Estimation of Word Representations in Vector Space." arXiv:1301.3781. arxiv.org
- Cook, J. D. (2010, January 19). "Don't invert that matrix." johndcook.com
- NumPy Developers. "Broadcasting." NumPy documentation. numpy.org
- NumPy Developers. "numpy.linalg.svd" and "numpy.linalg.lstsq." NumPy documentation. numpy.org