P02: Image Compression Using SVD
P02: Image Compression Using SVD
Build a tool that compresses images by decomposing them with Singular Value Decomposition, letting you visually see how much information each โrankโ captures.
Overview
| Attribute | Value |
|---|---|
| Difficulty | Intermediate |
| Time Estimate | 1-2 weeks |
| Language | Python (recommended) or C |
| Prerequisites | Basic matrix operations, understanding of P01 |
| Primary Book | โMath for Programmersโ by Paul Orland |
Learning Objectives
By completing this project, you will:
- See matrices as data - Understand that any grid of numbers (images, spreadsheets) is a matrix
- Master matrix decomposition - Break matrices into simpler, meaningful components
- Understand eigenvalues intuitively - The โimportance weightsโ of a matrixโs structure
- Grasp low-rank approximation - How a few numbers can capture most information
- Connect SVD to applications - Compression, recommendation systems, dimensionality reduction
- Build numerical intuition - Understand floating-point precision and numerical stability
Theoretical Foundation
Part 1: Images as Matrices
The Digital Image
A grayscale image is nothing more than a matrix of numbers:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GRAYSCALE IMAGE AS MATRIX โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Image (visual) Matrix (numerical) โ
โ โ
โ โโโโโโโโโโโโโโ [0 0 0 0 128 128 128 ... โ
โ โโโโโโโโโโโโโโ 0 0 128 128 255 255 255 ... โ
โ โโโโโโโโโโโโโโ 0 0 128 128 255 255 255 ... โ
โ โโโโโโโโโโโโโโ 0 0 128 0 0 0 128 ... โ
โ โโโโโโโโโโโโโโ 0 0 0 0 0 0 0 ... โ
โ ... โ
โ โ
โ Each pixel = one matrix entry โ
โ Value 0-255 represents darkness to brightness โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

For an mรn image, we have an mรn matrix A where:
- A[i][j] = brightness of pixel at row i, column j
- Typically 0 = black, 255 = white (for 8-bit images)
For color images, we have three matrices: one each for Red, Green, Blue channels.
Matrix Properties
A 512ร512 grayscale image:
- 512 ร 512 = 262,144 pixels
- Each pixel = 1 byte (8 bits, values 0-255)
- Total: 262,144 bytes โ 256 KB
Can we store this with fewer numbers?
Part 2: The Rank of a Matrix
What is Rank?
The rank of a matrix is the number of โtruly independentโ pieces of information it contains.
Full rank matrix (rank 3): Low rank matrix (rank 1):
[1 0 0] [1 2 3]
[0 1 0] rank = 3 [2 4 6] rank = 1
[0 0 1] [3 6 9]
Every row/column adds new All rows are multiples of [1,2,3]
information Only ONE piece of information!
Key insight: A rank-1 matrix can be written as the outer product of two vectors:
[1 2 3] [1]
[2 4 6] = [2] ร [1 2 3] = u ร vแต
[3 6 9] [3]
Instead of storing 9 numbers, store 6 numbers (two vectors)!
Rank and Information
- A rank-k matrix can be written as the sum of k rank-1 matrices
- Real images rarely have exact low rank, but are โapproximatelyโ low rank
- The important patterns are captured by the first few rank-1 pieces
- The remaining pieces are often noise or fine detail
Full Image โ Major patterns + Minor patterns + Finer details + Noise
(rank 1) (rank 2-10) (rank 11-50) (rest)
Part 3: Eigenvalues and Eigenvectors
The Core Concept
An eigenvector of matrix A is a special direction that only gets stretched (not rotated) by A:
A ร v = ฮป ร v
Where:
- v is the eigenvector (a direction in space)
- ฮป (lambda) is the eigenvalue (the stretch factor)
Visually:
A transforms...
Regular vector: โ gets rotated AND stretched
Eigenvector: โ gets ONLY stretched (by factor ฮป)
If ฮป = 2: eigenvector doubles in length
If ฮป = 0.5: eigenvector halves
If ฮป = -1: eigenvector flips direction
If ฮป = 0: eigenvector collapses to zero
Why Eigenvectors Matter
Eigenvectors reveal the natural axes of a transformation:
Consider stretching an image 2ร horizontally, 0.5ร vertically:
[2 0]
Stretch = [0 0.5]
Eigenvectors: [1, 0] with ฮป=2 (horizontal direction)
[0, 1] with ฮป=0.5 (vertical direction)
These are the "natural" directions of the transformation!
For symmetric matrices (like AแตA), eigenvectors are orthogonalโthey form a new coordinate system aligned with the matrixโs โpreferredโ directions.
Eigenvalue Magnitude
The magnitude of an eigenvalue indicates importance:
-
Large ฮป : This direction is strongly affected by the transformation -
Small ฮป : This direction is weakly affected - ฮป = 0: This direction is completely nullified (in the null space)
Part 4: Singular Value Decomposition (SVD)
The Grand Decomposition
SVD says: Every matrix can be written as a sequence of three simple operations.
A = U ร ฮฃ ร Vแต
Where:
- U: mรm orthogonal matrix (rotation in output space)
- ฮฃ: mรn diagonal matrix (scaling)
- Vแต: nรn orthogonal matrix (rotation in input space)
For an mรn matrix A.
Geometrically:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SVD GEOMETRIC INTERPRETATION โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ Any matrix transformation can be decomposed into: โ
โ โ
โ Vแต ฮฃ U โ
โ โโโโโโโ โ โโโโโโโโโ โ โโโโโโโ โ
โ Rotate Scale along Rotate again โ
โ input new axes in output space โ
โ โ
โ โ โฌญ โฌญ โ
โ โฑโโฒ โ โฑ โฒ โ โฑ โฒ โ
โ โ โ โฒ โ
โ โ โ โ โ
โ โ
โ Original Stretched/ Final โ
โ circle squished ellipse โ
โ along axes โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

The Components
ฮฃ (Sigma) - The Singular Values:
[ฯโ 0 0 ...]
ฮฃ = [0 ฯโ 0 ...]
[0 0 ฯโ ...]
[... ... ... ]
- ฯโ โฅ ฯโ โฅ ฯโ โฅ ... โฅ 0 (ordered by magnitude)
- These are the square roots of eigenvalues of AแตA
- They measure the "importance" of each component
U - Left Singular Vectors:
- Columns of U are orthonormal vectors in the output space
- They form the new coordinate axes after transformation
- uโ is the most โstretchedโ direction
V - Right Singular Vectors:
- Columns of V are orthonormal vectors in the input space
- They are the input directions that become the U directions
- Avโ points in the uโ direction (scaled by ฯโ)
SVD as Sum of Rank-1 Matrices
The magical property:
A = ฯโ(uโ ร vโแต) + ฯโ(uโ ร vโแต) + ฯโ(uโ ร vโแต) + ...
Each term (uแตข ร vแตขแต) is a rank-1 matrix!
Each ฯแตข is the "weight" or importance of that term.
For images:
Image = ฯโ(patternโ) + ฯโ(patternโ) + ฯโ(patternโ) + ...
Where ฯโ > ฯโ > ฯโ > ...
The first few patterns capture most of the image!
Part 5: Low-Rank Approximation
The Eckart-Young-Mirsky Theorem
This is the key result that makes SVD useful for compression:
The best rank-k approximation to A is obtained by keeping only the top k singular values.
A_k = ฯโ(uโ ร vโแต) + ฯโ(uโ ร vโแต) + ... + ฯโ(uโ ร vโแต)
This is the closest rank-k matrix to A (in terms of Frobenius norm).
No other rank-k matrix is closer!
Compression Achieved
For an mรn image with rank-k approximation:
Original storage: m ร n values
SVD storage (rank k):
- k columns of U: m ร k values
- k singular values: k values
- k columns of V: n ร k values
Total: k ร (m + n + 1) values
Compression ratio: (m ร n) / (k ร (m + n + 1))
Example with 512ร512 image:
Original: 262,144 values
Rank 10: 10 ร (512 + 512 + 1) = 10,250 values
Compression: 25.6ร smaller!
Rank 50: 50 ร 1,025 = 51,250 values
Compression: 5.1ร smaller!
Choosing k
How many singular values to keep?
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SINGULAR VALUE DECAY โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ฯ โ
โ โ โ
โ โโ โ
โ โโ โ
โ โโโ โ
โ โโโโ โ
โ โโโโโ โ
โ โโโโโโโ โ
โ โโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ k โ
โ โ โ โ โ
โ keep these cutoff discard these โ
โ (signal) here (noise/detail) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

Common criteria:
- Keep k values that capture X% of total โenergyโ:
(ฯโยฒ + ฯโยฒ + ... + ฯโยฒ) / (ฯโยฒ + ฯโยฒ + ... + ฯโยฒ) โฅ X% - Keep values above a threshold
- Fixed k based on desired file size
Part 6: Computing SVD
Method 1: Via Eigendecomposition
For matrix A, compute:
- AแตA (symmetric positive semi-definite)
- Find eigenvalues ฮปแตข and eigenvectors vแตข of AแตA
- Singular values: ฯแตข = โฮปแตข
- V = [vโ, vโ, โฆ, vโ]
- U columns: uแตข = Avแตข / ฯแตข
This works but has numerical issues for large matrices.
Method 2: Power Iteration (for largest singular value)
def largest_singular_value(A, iterations=100):
v = random_unit_vector(n)
for _ in range(iterations):
u = A @ v # Apply A
u = u / norm(u) # Normalize
v = A.T @ u # Apply Aแต
v = v / norm(v) # Normalize
sigma = norm(A @ v)
return sigma, u, v
This finds ฯโ, uโ, vโ. For subsequent singular values, deflate: Aโ = A - ฯโuโvโแต
Method 3: Use a Library
In practice, use optimized implementations:
import numpy as np
U, S, Vt = np.linalg.svd(A, full_matrices=False)
Part 7: Image-Specific Considerations
Color Images
For RGB images, apply SVD to each channel separately:
Original: R, G, B channels (each mรn)
For each channel:
U_c, ฮฃ_c, V_c = SVD(channel)
compressed_c = U_c[:, :k] @ ฮฃ_c[:k, :k] @ V_c[:k, :]
Reconstruct: Combine compressed R, G, B
Or convert to YCbCr and compress more aggressively on chrominance channels (human eyes are less sensitive to color detail).
Block-Based Compression
Like JPEG, process image in blocks:
For each 8ร8 or 16ร16 block:
Apply SVD
Keep top k singular values
Store U, ฮฃ, V for block
This allows local adaptation and parallelization.
Comparison with Other Methods
| Method | Approach | SVD Similarity |
|---|---|---|
| JPEG | DCT + quantization | Both find basis; DCT uses fixed basis |
| PCA | Find principal components | PCA of rows = SVD (related) |
| Wavelets | Multi-resolution decomposition | Different basis functions |
Project Specification
What Youโre Building
A command-line tool that:
- Loads a grayscale or color image
- Computes SVD of the image matrix
- Reconstructs the image using top k singular values
- Displays/saves the compressed image
- Reports compression ratio and quality metrics
Minimum Requirements
- Load image as matrix (grayscale first)
- Compute SVD (use library or implement)
- Reconstruct image with top k singular values
- Display original vs compressed side-by-side
- Calculate and display compression ratio
- Allow user to specify k
- Show singular value decay plot
Stretch Goals
- Support color images (per-channel SVD)
- Implement SVD from scratch (power iteration)
- Interactive slider to adjust k in real-time
- Calculate PSNR/SSIM quality metrics
- Compare with JPEG at similar file sizes
- Save compressed representation to file
Solution Architecture
Data Structures
class SVDCompressor:
"""Handles SVD-based image compression."""
def __init__(self, image: np.ndarray):
self.original = image
self.U = None
self.S = None # Singular values
self.Vt = None
def compress(self, k: int) -> np.ndarray:
"""Return rank-k approximation."""
pass
def compression_ratio(self, k: int) -> float:
"""Calculate storage ratio."""
pass
def energy_captured(self, k: int) -> float:
"""Percentage of total variance captured."""
pass
Module Structure
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ main.py โ
โ - CLI argument parsing โ
โ - Load image โ
โ - Display results โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโ
โผ โผ โผ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ image.py โ โ svd.py โ โ metrics.py โ
โ โ โ โ โ โ
โ load_image โ โ compute_svd โ โ psnr โ
โ save_image โ โ reconstruct โ โ ssim โ
โ display โ โ truncate โ โ compression_ratio โ
โ to_grayscale โ โ โ โ energy_ratio โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโ
โ visualize.pyโ
โ โ
โ plot_singular_values โ
โ side_by_side โ
โ difference_image โ
โโโโโโโโโโโโโโโโ
Processing Pipeline
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ SVD COMPRESSION PIPELINE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ Input Image โ 512ร512 grayscale โ
โ โ (m ร n) โ 262,144 values โ
โ โโโโโโโโฌโโโโโโโ โ
โ โ โ
โ โผ Compute SVD โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ A = U ร ฮฃ ร Vแต โ โ
โ โ โ โ
โ โ U: 512ร512 ฮฃ: 512ร512 diagonal Vแต: 512ร512โ โ
โ โโโโโโโโฌโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโ โ
โ โ โ โ โ
โ โผ โผ โผ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ Keep top โ โ Keep top โ โ Keep top โ โ
โ โ k columnsโ โ k values โ โ k rows โ โ
โ โ of U โ โ of ฮฃ โ โ of Vแต โ โ
โ โโโโโโโโโโโโ โโโโโโโโโโโโโโ โโโโโโโโโโโโ โ
โ โ โ โ โ
โ โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Reconstruct โ โ
โ โ A_k = U_k ฮฃ_k V_k^T โ โ
โ โโโโโโโโโโฌโโโโโโโโโ โ
โ โ โ
โ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ Compressed Imageโ k = 50: 51,250 values โ
โ โ (rank k approx) โ 5ร compression โ
โ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

Phased Implementation Guide
Phase 1: Image Loading and Display (Days 1-2)
Goal: Load and display images as matrices
Tasks:
- Set up Python environment with numpy, PIL/OpenCV, matplotlib
- Load grayscale image as numpy array
- Display image using matplotlib
- Print matrix dimensions and value range
- Visualize raw matrix values (maybe a small crop)
Verification:
# Image should load as 2D array
assert len(image.shape) == 2 # grayscale
assert image.min() >= 0 and image.max() <= 255
# Display should show correct image
plt.imshow(image, cmap='gray')
Phase 2: SVD Computation (Days 3-4)
Goal: Compute and understand SVD components
Tasks:
- Compute SVD using
np.linalg.svd() - Verify: reconstruct original from U, S, Vt
- Plot singular values (should decay)
- Calculate energy captured by top k values
Verification:
U, S, Vt = np.linalg.svd(image, full_matrices=False)
# Reconstruct should equal original
reconstructed = U @ np.diag(S) @ Vt
assert np.allclose(image, reconstructed)
# Singular values should be non-negative and ordered
assert all(s >= 0 for s in S)
assert all(S[i] >= S[i+1] for i in range(len(S)-1))
Phase 3: Low-Rank Approximation (Days 5-6)
Goal: Reconstruct images with reduced rank
Tasks:
- Implement truncation to rank k
- Reconstruct and display for various k values
- Create side-by-side comparisons
- Calculate compression ratios
Implementation:
def compress(U, S, Vt, k):
"""Reconstruct using only top k singular values."""
U_k = U[:, :k]
S_k = S[:k]
Vt_k = Vt[:k, :]
return U_k @ np.diag(S_k) @ Vt_k
Verification:
- k=1: Very blurry, single dominant pattern
- k=10: Major features visible
- k=50: Good quality for most images
- k=full: Equals original
Phase 4: Visualization (Days 7-8)
Goal: Create informative visualizations
Tasks:
- Plot singular value decay (log scale useful)
- Show cumulative energy curve
- Display rank-1, rank-10, rank-50, original side by side
- Create difference image (original - compressed)
- Implement interactive slider for k
Visualizations:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VISUALIZATION DASHBOARD โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Singular Value Decay โ โ Cumulative Energy โ โ
โ โ โ โ โ โ
โ โ ฯ โ โ % 100% โ โ
โ โ โ\ โ โ โ ____โโ โ โ
โ โ โ \ โ โ โ ___/ โ โ
โ โ โ \_____ โ โ โ ___/ โ โ
โ โ โโโโโโโโโโโโโ k โ โ โโโโ/โโโโโโโโโโโโ k โ โ
โ โ โ โ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โ
โ โ k = 1 โ โ k = 10 โ โ k = 50 โ โ Original โ โ
โ โ โ โ โ โ โ โ โ โ
โ โ โโโโ โ โ โโโโ โ โ โโโโ โ โ โโโโ โ โ
โ โ โโโโ โ โ โโโโ โ โ โโโโ โ โ โโโโ โ โ
โ โ โ โ โ โ โ โ โ โ
โ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

Phase 5: Metrics and Analysis (Days 9-10)
Goal: Quantify compression quality
Tasks:
- Implement PSNR (Peak Signal-to-Noise Ratio)
- Implement MSE (Mean Squared Error)
- Calculate compression ratios for various k
- Create quality vs. compression tradeoff plot
- Compare with JPEG at similar sizes
Metrics:
def mse(original, compressed):
return np.mean((original - compressed) ** 2)
def psnr(original, compressed, max_val=255):
return 10 * np.log10(max_val**2 / mse(original, compressed))
# PSNR > 30 dB: Good quality
# PSNR > 40 dB: Excellent quality
Phase 6: Color Images (Days 11-12)
Goal: Extend to RGB images
Tasks:
- Load color image and split into R, G, B channels
- Apply SVD to each channel
- Reconstruct each channel
- Combine channels and display
- Compare different k for each channel
Implementation:
def compress_color(image, k):
channels = [image[:,:,i] for i in range(3)]
compressed = []
for channel in channels:
U, S, Vt = np.linalg.svd(channel, full_matrices=False)
compressed.append(compress(U, S, Vt, k))
return np.stack(compressed, axis=2)
Phase 7: Optional - Implement SVD from Scratch (Days 13-14)
Goal: Understand the algorithm deeply
Tasks:
- Implement power iteration for largest singular value
- Implement matrix deflation
- Compute multiple singular values iteratively
- Compare results with numpy
Implementation:
def power_iteration(A, num_iters=100):
"""Find largest singular value and vectors."""
m, n = A.shape
v = np.random.randn(n)
v = v / np.linalg.norm(v)
for _ in range(num_iters):
u = A @ v
u = u / np.linalg.norm(u)
v = A.T @ u
v = v / np.linalg.norm(v)
sigma = np.linalg.norm(A @ v)
return sigma, u, v
def svd_manual(A, k):
"""Compute top k singular values via power iteration."""
singular_values = []
U_cols, V_cols = [], []
A_remaining = A.copy()
for _ in range(k):
sigma, u, v = power_iteration(A_remaining)
singular_values.append(sigma)
U_cols.append(u)
V_cols.append(v)
A_remaining = A_remaining - sigma * np.outer(u, v)
return np.array(U_cols).T, np.array(singular_values), np.array(V_cols)
Testing Strategy
Unit Tests
- SVD reconstruction:
- Full reconstruction should equal original (within floating point tolerance)
- Singular value properties:
- All singular values โฅ 0
- Sorted in descending order
- Count โค min(m, n)
- Orthogonality:
- U columns should be orthonormal: UแตU = I
- V columns should be orthonormal: VแตV = I
- Rank-k approximation:
- rank(A_k) โค k
- A_k converges to A as k increases
Visual Tests
- Quality progression: k=1 โ k=full should show smooth improvement
- No artifacts: Compressed image shouldnโt have obvious visual errors
- Difference image: Should show high-frequency detail removed
Numerical Tests
- Compression ratio: Should match theoretical formula
- Energy capture: Sum of top k ฯยฒ / total ฯยฒ should increase with k
- PSNR: Should increase with k
Common Pitfalls and Debugging
Numerical Precision
Symptom: Small differences between original and full reconstruction
Cause: Floating-point arithmetic has limited precision
Fix: Use np.allclose() with appropriate tolerance, not exact equality
Image Data Type
Symptom: Image looks wrong or values are clipped
Cause: Image loaded as uint8 (0-255) but SVD produces floats
Fix: Convert to float before SVD, clip to [0, 255] after reconstruction
Memory for Large Images
Symptom: Out of memory for large images
Cause: Full SVD computes all singular values
Fix: Use svd(A, full_matrices=False) for economy SVD, or use randomized SVD
Color Channel Issues
Symptom: Color images have wrong colors after reconstruction
Cause: Channels mixed up or not properly recombined
Fix: Carefully track channel order, ensure floatโuint8 conversion is correct
Visualization Scale
Symptom: Compressed image looks too dark or too bright
Cause: Value range not normalized for display
Fix: Clip to valid range, or normalize: (image - min) / (max - min)
Extensions and Challenges
Beginner Extensions
- Save/load compressed representation
- Process multiple images in batch
- Add command-line interface with argparse
Intermediate Extensions
- Implement randomized SVD for large images
- Adaptive k selection based on quality threshold
- Block-based SVD (like JPEG blocks)
- Video compression (SVD on frame differences)
Advanced Extensions
- Implement truncated SVD with Lanczos algorithm
- Compare with DCT-based compression
- Explore tensor decomposition for color images
- GPU acceleration with CuPy or PyTorch
Real-World Connections
Data Compression
SVD is the mathematical foundation for:
- Netflixโs video encoding (partial)
- Image thumbnails and progressive loading
- Scientific data compression
Recommendation Systems
Netflix Prize (2006-2009) used matrix factorization:
Ratings Matrix โ U ร ฮฃ ร Vแต
U rows: user latent factors (taste preferences)
V rows: item latent factors (movie characteristics)
ฮฃ: importance weights
Your image compression is training you for this!
Dimensionality Reduction
PCA (Principal Component Analysis) is closely related:
Centered data matrix X
PCA directions = right singular vectors of X
PCA scores = left singular vectors ร singular values
Natural Language Processing
Latent Semantic Analysis (LSA):
Term-Document Matrix โ SVD โ Topics
U: term-topic relationships
V: document-topic relationships
ฮฃ: topic importance
Noise Reduction
Small singular values often correspond to noise:
Signal โ large singular values
Noise โ small singular values
Removing small ฯแตข denoises the data!
Self-Assessment Checklist
Conceptual Understanding
- I can explain what a matrix rank means geometrically
- I understand why singular values are ordered
- I can explain the Eckart-Young theorem in simple terms
- I know why low-rank approximation works for compression
- I understand the relationship between SVD and eigendecomposition
Practical Skills
- I can compute SVD and reconstruct the original matrix
- I can choose an appropriate k for a given compression target
- I can measure and interpret compression quality metrics
- I can visualize singular value decay and energy capture
- I can apply SVD compression to color images
Teaching Test
Can you explain to someone else:
- Why can a rank-1 matrix be stored with fewer numbers?
- What do the columns of U and V represent?
- Why are the first singular values larger?
- How does SVD relate to JPEG compression?
Resources
Primary
- โMath for Programmersโ by Paul Orland - Practical approach
- 3Blue1Brown: Essence of Linear Algebra - Especially the SVD intuition
- Grokking Algorithms - Appendix on linear algebra
Reference
- โNumerical Linear Algebraโ by Trefethen & Bau - Rigorous treatment
- โMining of Massive Datasetsโ - SVD for recommendation
- โThe Elements of Statistical Learningโ - SVD/PCA connection
Online
- NumPy SVD documentation - Implementation details
- Interactive SVD visualizations - Various web apps
- JPEG compression tutorials - For comparison
When you complete this project, youโll understand that matrices contain hidden structureโand that structure can be extracted, prioritized, and reconstructed. This is the foundation for machine learning, signal processing, and data science.