← Tensor by Tensor
§ Math Fundamentals for AI
Tensor by Tensor · Complete Guide

Singular value decomposition

Fourteen lessons that connect high-school mathematics to AI. Start with the plain-language explanation and a small example. Then read the full formulas, derivations, and Python code at your own pace.

How to study a lesson

Read the opening example. Try the question before revealing its answer. Then work through the detailed notes below it. You do not need to understand every proof on the first reading.

Symbols: a subscript such as xi identifies one entry. Σ means add a collection of terms. ∈ means “belongs to”. The symbol ≈ means “approximately equal”, not exactly equal. A parameter is an adjustable number in a model.

01.13 · Singular Value Decomposition (SVD)

Introduction

A large matrix may contain a simpler structure than its number of entries suggests. Singular value decomposition separates its action into a rotation or reflection, axis scaling, and another rotation or reflection.

Learning goal

Interpret the three SVD matrix factors and use singular values to reason about useful low-rank approximation.

Before you start

Matrices, matrix multiplication, transpose operations, vectors, dimensions, and basic geometric transformations.

Lesson plan

  1. Read the factor shapes and apply the three transformations from right to left.
  2. Interpret singular values as strengths along special input and output directions.
  3. Keep leading components for approximation, then inspect applications and NumPy output.

Predict what compression removes. Keeping the largest singular values preserves the strongest matrix directions. Dropping a small singular value removes its direction's contribution. This is a controlled approximation, not automatic removal of “unimportant meaning.”

The most useful matrix factorisation

The SVD decomposes any matrix into three interpretable pieces. It reveals the fundamental structure of a linear map and is used throughout ML for dimensionality reduction, compression, and analysis.

Definition · SVD

Any matrix $A \in \mathbb{R}^{m \times n}$ can be factored as:

$$A = U \Sigma V^\top$$

where:

  • $U \in \mathbb{R}^{m \times m}$ is orthogonal (left singular vectors)
  • $\Sigma \in \mathbb{R}^{m \times n}$ is diagonal with non-negative entries $\sigma_1 \geq \sigma_2 \geq \cdots \geq 0$ (singular values)
  • $V \in \mathbb{R}^{n \times n}$ is orthogonal (right singular vectors)

Geometric interpretation

Any linear map $A$ can be decomposed into three steps:

  1. Rotate or reflect the input space ($V^\top$)
  2. Scale each axis independently ($\Sigma$)
  3. Rotate or reflect into the output space ($U$)

The singular values $\sigma_i$ tell you how much $A$ stretches space along each principal direction.

Truncated SVD and low-rank approximation

Keeping only the top $k$ singular values gives the best rank-$k$ approximation:

$$A_k = \sum_{i=1}^k \sigma_i u_i v_i^\top$$

The Eckart-Young theorem guarantees this minimises $\|A - B\|_F$ over all rank-$k$ matrices $B$.

Example · Image compression

A $512 \times 512$ grayscale image has 262,144 entries. Its SVD has 512 singular values. Keeping only the top 50 gives a rank-50 approximation that often looks nearly identical to the original, using only $512 \times 50 + 50 + 512 \times 50 = 51,250$ numbers — an 80% reduction.

Applications in ML

Principal Component Analysis (PCA)

PCA on a centred data matrix $X$ is the SVD of $X/\sqrt{n-1}$. The right singular vectors are the principal components; the singular values give the standard deviations along each component.

LoRA (Low-Rank Adaptation)

LoRA fine-tunes large language models by decomposing weight updates as low-rank matrices:

$$W_{\text{new}} = W_{\text{frozen}} + BA$$

where $B \in \mathbb{R}^{d \times r}$ and $A \in \mathbb{R}^{r \times k}$ with $r \ll \min(d,k)$. This is an implicit SVD-like decomposition of the update $\Delta W = BA$.

Condition number

The condition number of $A$ is $\kappa(A) = \sigma_{\max}/\sigma_{\min}$. Large $\kappa$ means the matrix is ill-conditioned — small input changes produce large output changes. This affects numerical stability of linear solvers and gradient flow.

Computing SVD

import numpy as np

A = np.array([[1, 2], [3, 4], [5, 6]])
U, s, Vt = np.linalg.svd(A, full_matrices=False)

print("Singular values:", s)      # [9.525, 0.514]
print("Rank-1 approx:", s[0] * np.outer(U[:,0], Vt[0,:]))

# Truncated to top-k
k = 1
A_k = U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :]
Full vs. reduced SVD

full_matrices=False gives the reduced SVD: $U$ is $m \times \min(m,n)$ and $V$ is $n \times \min(m,n)$. The full version extends the orthonormal bases; it does not pad those bases with zero columns. Use the reduced form when the extra basis vectors are unnecessary.