Neural Mastery

Linear Algebra for AI

Every number an AI model works with — a pixel, a word, a weight — is stored and manipulated as a vector or a matrix. Linear algebra is the language that makes that manipulation precise.

Think of a vector as an arrow: it points somewhere and has a length. A matrix is a machine that takes an arrow in and spits a (possibly stretched, possibly rotated) arrow back out — matrix multiplication is just "run this arrow through the machine." Almost everything on this page is really one question, asked about that machine in different ways: does it stretch space, squash it flat, rotate it, or leave certain special directions completely alone (eigenvectors)? A neural network layer is one of these machines — an input vector goes in, a matrix multiplication (plus a nudge and a nonlinearity) transforms it, and out comes the next layer's input.

Everything below makes that same idea exact: the real formulas, and why the special cases — eigenvectors, SVD, positive-definiteness — matter for anything you'll actually build.

Intuition: Numbers, Directions, and Functions

Three ideas carry this entire page. A vector isn't just a list of numbers — it's a direction and magnitude in space, and comparing two vectors (dot product, cosine similarity) is really asking "how aligned are these two directions." A matrix isn't just a grid — it's a function that takes a vector in and produces a vector out, and everything from "what is rank" to "what is an eigenvector" is really a question about what that function does to space. And a quadratic form (xTAx\mathbf{x}^T A \mathbf{x}) is what curvature looks like in this language — the concept every optimization method on the next page is secretly built from.

Vectors

A vector is an ordered list of numbers, e.g. v=[2,1,3]\mathbf{v} = [2, -1, 3]. In AI, a vector usually represents something's position in a space of features: a word's embedding, an image's pixel values flattened out, a user's preference profile.

Dot product: ab=iaibi\mathbf{a} \cdot \mathbf{b} = \sum_i a_i b_i. Measures how much two vectors point in the same direction. Norm (length): v2=ivi2\|\mathbf{v}\|_2 = \sqrt{\sum_i v_i^2}. Cosine similarity: cos(θ)=abab\cos(\theta) = \dfrac{\mathbf{a} \cdot \mathbf{b}}{\|\mathbf{a}\|\|\mathbf{b}\|}. Drag both vectors below and watch all three recompute live:

ab
cosθ=abab=0.646\cos\theta = \frac{a \cdot b}{\|a\|\|b\|} = 0.646
Drag b to point the same direction as a -- cosine similarity climbs to 1 regardless of length; drag it perpendicular and it hits 0, regardless of how long either vector is. That length-independence is exactly what makes it the right metric for comparing embeddings.
a·b = (3)(1) + (1)(2.5) = 5.50. ‖a‖ = 3.16, ‖b‖ = 2.69. cos(θ) = a·b / (‖a‖‖b‖) = 0.646 → θ ≈ 49.8°. Every number here is recomputed live from the two vectors you're dragging via the sliders.

If the dot product is large and positive, the vectors are aligned; if it's zero, they're orthogonal (unrelated); if negative, they point in opposite directions. Cosine similarity is the similarity metric for embeddings — it measures direction, ignoring magnitude, which is exactly what you want when comparing two text or image embeddings for semantic similarity (this is the metric vector databases use for nearest-neighbor search).

Try it yourself: implement the dot product from scratch, against real test cases.

Matrices

A matrix is a grid of numbers — think of it as a function that transforms vectors. A neural network layer is nothing more than a matrix multiplication followed by a nonlinearity: y=Wx+b\mathbf{y} = W\mathbf{x} + \mathbf{b}.

Matrix multiplication: combining two matrices AA (shape m×nm \times n) and BB (shape n×pn \times p) produces CC (shape m×pm \times p), where each entry CijC_{ij} is the dot product of row ii of AA and column jj of BB. Hover any output cell to see the real dot product behind it:

A (2×3)
2.000.001.001.003.00-1.00
×
B (3×2)
1.002.000.001.003.001.00
=
C (2×2)
5.005.00-2.004.00
A is (2×3), B is (3×2) -- the shared inner dimension (3) cancels, leaving a (2×2) result, exactly the shape rule used throughout attention (`Q·Kᵀ`).
Hover any output cell to see exactly which row and column produced it -- real dot products, not a schematic.

This is the single most executed operation on every GPU running AI workloads today. Transpose (ATA^T) flips rows and columns — shows up constantly in backpropagation (gradients flow backward through the transposed weight matrix) and in attention (Q · Kᵀ). Inverse (A1A^{-1}) is the matrix that "undoes" AA, so AA1=IA A^{-1} = I — only exists for square, full-rank matrices, rarely computed directly in deep learning (too expensive/unstable) but essential to understand conceptually.

A matrix acting as a function is easiest to see geometrically — drag the four entries below and watch the whole grid warp in real time, the two bold arrows always landing exactly at the matrix's two columns:

Bold arrows: where the original x-axis and y-axis basis vectors landed -- exactly the two columns of A. Every other grid line is just a combination of those two.
A matrix is a function on vectors -- every point on the grid moved to A·(x,y). det(A) = 1.42: the area scale factor of the transformation (a unit square now has area |1.42|).

Try it yourself: implement matrix multiplication from scratch, against real test cases.

Rank, Independence, and Span

  • Linear independence: a set of vectors where none can be written as a combination of the others.
  • Span: all the vectors you can reach by combining a given set of vectors.
  • Rank: the number of linearly independent rows/columns in a matrix — effectively, how much "real" information the matrix carries.

Drag the second vector below toward (or away from) the first and watch span and rank change in real time:

v1v2
Shaded area = span of the two vectors (the whole plane, when independent) -- a real, non-zero region only when rank is full.
rank([v1, v2]) = 2, computed from the real determinant of the 2×2 matrix these vectors form (nonzero ⟺ independent ⟺ rank 2). Drag v2 onto the same line as v1 and watch it drop to rank 1 -- the span collapses from the whole plane down to a single line, and the "real information" in the matrix drops with it.

Why this matters: LoRA (Low-Rank Adaptation), one of the most widely used fine-tuning techniques for LLMs, works precisely because weight updates during fine-tuning tend to have low rank — so you can approximate them with two small matrices instead of one huge one.

Eigenvalues and Eigenvectors

For a square matrix AA, an eigenvector v\mathbf{v} is a vector whose direction AA doesn't change — it only gets scaled: Av=λvA\mathbf{v} = \lambda \mathbf{v}, where λ\lambda is the eigenvalue. Step through real power iteration — repeatedly apply AA and renormalize — and watch an arbitrary starting vector converge onto the real eigenvector direction:

step 0
Dashed line: the real eigenvector direction (computed in closed form). Watch the solid arrow snap onto it within a handful of steps -- this is literally how large-scale eigensolvers (e.g. for PageRank, or PCA on huge covariance matrices) find the dominant direction without ever computing a full eigendecomposition.
Step 0: v = (1.000, -0.300). Real dominant eigenvalue λ = 2.781, real eigenvector direction = (0.788, 0.615). Repeatedly applying A and renormalizing (power iteration, a real algorithm used inside real eigensolvers) converges to this exact direction regardless of the starting vector -- the "natural axis" A doesn't rotate, only scales.

Intuition: eigenvectors are the "natural axes" of a transformation — the directions where the matrix acts like simple scaling instead of full rotation/shearing. This is the basis of PCA (Principal Component Analysis): the eigenvectors of a dataset's covariance matrix are the directions of maximum variance in the data. Power iteration, exactly as shown above, is also how real large-scale eigensolvers find a dominant eigenvector without ever forming a full eigendecomposition — the same core idea behind PageRank.

Singular Value Decomposition (SVD)

Any matrix AA (even non-square) can be decomposed as A=UΣVTA = U \Sigma V^T, where UU and VV are orthogonal matrices and Σ\Sigma is diagonal with non-negative values (the singular values), sorted largest to smallest. A real, hand-verifiable decomposition — genuinely orthonormal UU/VV, three rank-1 terms with decreasing singular values — truncated live:

original A (rank 3)
2.131.131.880.881.132.130.881.881.880.882.131.130.881.881.132.13
A_1 (rank 1)
1.501.501.501.501.501.501.501.501.501.501.501.501.501.501.501.50
Real singular values: σ = [6, 2, 0.5]. Keeping only the top 1 of 3 rank-1 terms gives a real reconstruction error (Frobenius norm) of ‖A − A_k‖ = √(Σ dropped σᵢ²) = 2.062, out of 6.344 total "energy" in the matrix. This IS the Eckart-Young theorem: no other rank-1 matrix gets closer to A than this one.

If you understand SVD, you understand why "compressing" a matrix by keeping only the top-kk singular values loses the least information possible for that compression level (the Eckart-Young theorem, made concrete above) — this is exactly the intuition behind low-rank approximations used in efficient LLM fine-tuning (LoRA), recommender systems (matrix factorization: decomposing a user-item ratings matrix), and model compression.

Quadratic Forms and Positive (Semi-)Definite Matrices

A quadratic form is the scalar xTAx\mathbf{x}^T A \mathbf{x} — a matrix AA "sandwiched" between a vector and its transpose. It shows up everywhere curvature matters: it's the general shape of a loss surface near a minimum (see Jacobians & Hessians), the Mahalanobis distance in statistics, and the energy term in many kernel methods. Real contour shading plus the real gradient at five sample points, for three qualitatively different matrices:

Matrix A
Shading = real value of x^T A x at each point (darker = larger magnitude). Amber arrows = the real gradient (A+Aᵀ)x at 5 sample points -- always pointing toward steeper shading, exactly "uphill."
Real eigenvalues: λ = [2.31, 1.19]. Both strictly positive → positive definite → a real bowl, single global minimum at the origin, no flat directions.

A symmetric matrix AA is positive semi-definite (PSD) if xTAx0\mathbf{x}^T A \mathbf{x} \geq 0 for every vector x\mathbf{x}, and positive definite (PD) if that inequality is strict for every nonzero x\mathbf{x} — ruling out flat directions, exactly the difference visible between the first two presets above. Covariance matrices are always PSD (the variance of any linear combination of variables can't be negative). This property guarantees that optimization problems built on them (many kernel methods, second-order optimization) behave predictably — no "negative curvature" surprises. A quick test: a symmetric matrix is PD if and only if all its eigenvalues are strictly positive — this is exactly the condition Newton's method checks on the Hessian to confirm it's actually at a minimum, not a saddle point (the third preset above).

Matrix Calculus: Gradients w.r.t. Vectors and Matrices

Backpropagation is, mechanically, repeated application of a handful of matrix-calculus identities:

  • x(Ax)=AT\nabla_{\mathbf{x}} (A\mathbf{x}) = A^T — the gradient of a linear map w.r.t. its input is just the matrix's transpose. This is why backprop through a linear layer multiplies by the transposed weight matrix: the forward pass computes AxA\mathbf{x}, the backward pass needs x\nabla_{\mathbf{x}}, which the identity above hands you directly.
  • x(xTAx)=(A+AT)x\nabla_{\mathbf{x}} (\mathbf{x}^T A \mathbf{x}) = (A + A^T)\mathbf{x}, which simplifies to 2Ax2A\mathbf{x} when AA is symmetric — the real gradient computed and plotted in the quadratic-form diagram above. This single identity is the derivation of the OLS normal equations in Linear Regression: differentiate the squared-error loss (a quadratic form in the weights), set it to zero, solve.
  • W(wTx)=x\nabla_W (\mathbf{w}^T \mathbf{x}) = \mathbf{x} and, for a full weight matrix, W(Wx+b)\nabla_W (W\mathbf{x} + \mathbf{b}) w.r.t. each entry of WW is an outer product δxT\mathbf{\delta}\, \mathbf{x}^T — the exact computation every deep learning framework's autograd performs at every Linear/Dense layer during the backward pass.

You rarely derive these by hand in practice (autograd does it), but recognizing them is what makes a backprop derivation on a whiteboard readable instead of a wall of chain-rule symbols.

Code: Power Iteration, For Real

The exact algorithm the eigenvector diagram above steps through:

import numpy as np

def power_iteration(A: np.ndarray, num_steps: int = 20) -> tuple[np.ndarray, float]:
    v = np.random.randn(A.shape[0])
    v = v / np.linalg.norm(v)
    for _ in range(num_steps):
        v = A @ v
        v = v / np.linalg.norm(v)          # renormalize every step
    eigenvalue = v @ A @ v                  # Rayleigh quotient at convergence
    return v, eigenvalue                    # v converges to the dominant eigenvector

Where this shows up in the rest of the curriculum

ConceptUsed in
Dot product / cosine similarityEmbeddings, vector search, attention scores
Matrix multiplicationEvery neural network layer
EigenvectorsPCA, spectral clustering
SVD / low rankLoRA fine-tuning, recommender systems, compression
TransposeBackpropagation, attention (Qᵀ, Kᵀ)
Quadratic forms / PD matricesLoss curvature, Newton's method, kernel methods
Matrix calculus identitiesDeriving backprop and closed-form solutions (OLS) by hand

Next: Calculus & Optimization — how models actually learn by following gradients through this linear-algebra machinery.

Last updated Sep 5, 2026Edit this pageReport an issue
← Previous
Mathematics for AI — Roadmap
Next →
Calculus & Optimization for AI