Principal component analysis and the SVD

How Many Numbers Does a Day of Levant Weather Need?

15 July 2024, daily mean temperature (ERA5)

Twenty-two cities from Athens to Aleppo give twenty-two temperatures every day. Write down one number per day instead of twenty-two. How close can you get to all of them, and which number should it be?

By the end you can

  • find the direction along which data varies most, and say why it is an eigenvector
  • compress a dataset to \(k\) numbers per example and measure what is lost
  • compute PCA with the SVD, and read the shape of every matrix in it
  • read what the patterns mean, in digits or in weather, and where they stop

Five questionsParts 1 to 3 for everyone, then one part for each course

  1. 1A day of weatherWhat is one day, as numbers?
  2. 2The direction of most variationWhich single line through the data keeps the most?
  3. 3An eigenvalue problemHow do we find that line, and how many numbers does a day need?
  4. 4Eigen-digits (Intro to ML)What does PCA find in pictures of handwriting?
  5. 5Weather modes (ML for Science)What do the patterns mean, and what can they not do?

ApplicationsWhere principal component analysis is used

  • Image compression. Represent images, or patches of them, in a lower-dimensional basis that keeps the dominant principal components.
  • Visualization. Project gene expression data, text embeddings or customer features into two or three dimensions for a person to look at.
  • Population genetics. Identify population structure, genetic ancestry and subpopulation clusters.
  • Finance. Reduce many stock returns, risk factors, interest rates or yield curves to a few.
  • Process monitoring. Watch multivariate sensor data over time: temperature, pressure, vibration.
  • Healthcare. Reduce gene expression, medical features or patient records to fewer dimensions.
  • Marketing. From many features (demographics, purchases), find a few latent preference axes.
  • Video. Separate a video into temporal and spatial modes, for example to model the background.
  • Physical modelling. Find the main spatial and temporal modes of a fluid or a material; in weather and climate these are called empirical orthogonal functions.

Why fewer numbers at all: with many dimensions, data is sparse (most of the space is empty), distances between points become alike, and a model needs far more examples to cover the space. This is the curse of dimensionality.

A day is 22 numbersERA5 daily mean temperature at 22 cities, 1 January 2010 to 31 December 2025: 5,844 days. Slide through the days; click a city.

Stack the days as rows and the cities as columns: a matrix of 5,844 rows and 22 columns. ERA5 is a reanalysis: a weather model kept close to observations, read at the grid cell nearest each city (Hersbach and colleagues, 2020). The data (CSV)

How many numbers does a day need?Guess before any method: enough to be off by less than a degree, on average over the cities and the days

Beirut and Damascus are 85 km apart and both are warm in August. Gaziantep and Alexandria are not alike, but they too are warm in August. The 22 numbers of a day are far from independent.

Representing data with fewer numbers than it has columns, while keeping most of what is in it, is dimensionality reduction. To make the question precise we need two cities first.

Part 2 of 5

The direction of most variation

Which single line through the data keeps the most?

Principal Component AnalysisTwo columns of the matrix: Beirut and Damascus, one point per day (every sixth day drawn). Point at a day.

Dataset
x₁x₂
14.88.5
17.910.6
16.210.7
15.411.4
......

Each day \(i\) is a point \(x^{(i)} = (x_1^{(i)}, x_2^{(i)})\): Beirut's temperature and Damascus's, in °C. The first rows are the first four days of 2010.

The points lie along a diagonal (correlation 0.963): a warm day in Beirut is a warm day in Damascus. Damascus swings more: 8.3 °C standard deviation against 5.9 °C.

 

Principal Component AnalysisThe purpose: find the major axis of variation, then the next one at a right angle

Principal component 1, \(v_1\), is the direction along which the days spread the most. Here it points 55° up from the Beirut axis: \(v_1 = \) (0.57, 0.82).

Principal component 2, \(v_2\), is the direction of most spread among those at a right angle to \(v_1\).

Principal components are orthogonal unit vectors, so together they are a new set of axes: a change of coordinates. Principal component analysis (PCA) finds them.

Principal Component AnalysisBefore finding the directions, centre the data; normalise it only when the columns are in different units

Mean, then centre the data

\[\mu_j = \frac{1}{n}\sum_{i=1}^n x_j^{(i)}, \qquad x_j^{(i)} \leftarrow x_j^{(i)} - \mu_j\]

Variance, then normalise the data

\[\sigma_j^2 = \frac{1}{n}\sum_{i=1}^n \left(x_j^{(i)} - \mu_j\right)^2, \qquad x_j^{(i)} \leftarrow x_j^{(i)}/\sigma_j\]

All cities are in °C, so this deck centres and does not normalise: Gaziantep (9.4 °C) should count more than Alexandria (5.0 °C). Normalise when the columns have different units.

Principal Component AnalysisThe centred days in the new coordinates, then projected onto the axis of highest variation, \(v_1\)

Keeping one number per day, \(z_1^{(i)}\), is a projection onto \(v_1\). The error of that projection is each day's distance in the direction of \(v_2\): the reconstruction error. How do we find \(v_1\) and \(v_2\)?

What's the major axis of variation?Drag in the plot or use the slider to turn the line. Every day drops onto it (green), along the red dashes.

variance of the projections mean squared distance to the line their sum, at every angle
\[\|x^{(i)}\|^2 = (\text{length along the line})^2 + (\text{distance to the line})^2\]

Pythagoras, for every day (the formula for the length along the line comes with the exercise in part 3). Summed over the days, the left side is fixed, 103.8 °C², so the line with the most variance along it is the line with the least squared distance to it. At \(v_1\) the error is 1.7 °C², a typical distance of 1.3 °C.

Part 3 of 5

An eigenvalue problem

How do we find that line, and how many numbers does a day need?

Notation, used for the rest of the deckOne letter per object, and the shape of each

\(n\)number of examples: days (5,844), or digits (20,000)
\(d\)numbers per example: cities (22), or pixels (256)
\(x^{(i)} \in \mathbb{R}^d\)example \(i\), centred: a day minus the mean day \(\mu\)
\(X \in \mathbb{R}^{n \times d}\)the centred data, one example per row
\(\Sigma = \tfrac{1}{n} X^\top X \in \mathbb{R}^{d \times d}\)the covariance matrix
\(v_j \in \mathbb{R}^d,\ \lambda_j\)principal directions (unit length, orthogonal) and their variances, \(\lambda_1 \ge \lambda_2 \ge \dots\)
\(z^{(i)} \in \mathbb{R}^k\)the \(k\) numbers kept for example \(i\): \(z_j^{(i)} = v_j^\top x^{(i)}\)
\(X = U\,\Xi\,V^\top\)the singular value decomposition, singular values \(\sigma_j\) on the diagonal of \(\Xi\)

The F25 slides called the directions \(u\) and switched to \(v\) at the SVD; here they are \(v\) from the start, because they are the columns of \(V\), not of \(U\).

Exercise: the projection of \(x\) on \(v\)Given a day \(x^{(i)}\) and a unit vector \(v\): which point on the line is closest to \(x^{(i)}\), and how far along the line is it?

✏ with your neighbour

You know \(x^{(i)}\) (yellow) and the unit vector \(v\) (pink). Which point on the line is closest to \(x^{(i)}\), and how far from the origin is it? One dot product.

Drop the perpendicular (red dashes): the closest point on the line is its foot. What is lost is the red length.

\[z^{(i)} = x^{(i)\top} v = \sum_{j=1}^d x_j^{(i)} v_j, \qquad \|v\|_2 = 1\]

\(z^{(i)}\) is one number, the signed distance along \(v\). The closest point is \(z^{(i)}\, v\) (green): \(z^{(i)}\) copies of the unit vector.

Over all days, the variance of the projections is the mean of \(\big(z^{(i)}\big)^2\) (centred data: the \(z^{(i)}\) average to zero). The next slide maximises it.

Maximize the variance of the projectionsOne step at a time: the variance along \(v\) is a quadratic form in the covariance matrix

1The variance of the \(z^{(i)} = x^{(i)\top} v\), to be maximised over unit vectors \(v\): \(\displaystyle \max_{\|v\|_2 = 1}\ \frac{1}{n}\sum_{i=1}^n \left(x^{(i)\top} v\right)^2\) 2A number equals its transpose, so \(\big(x^{(i)\top} v\big)^2 = \big(v^\top x^{(i)}\big)\big(x^{(i)\top} v\big) = v^\top x^{(i)} x^{(i)\top} v\): \(\displaystyle \frac{1}{n}\sum_{i=1}^n v^\top x^{(i)} x^{(i)\top} v = v^\top \Big(\frac{1}{n}\sum_{i=1}^n x^{(i)} x^{(i)\top}\Big) v\) 3The matrix in the middle is the covariance matrix, \(\Sigma = \frac{1}{n} X^\top X\), \(d \times d\). The problem is \(\displaystyle \max_{\|v\|_2 = 1}\ v^\top \Sigma\, v\)

Lagrange multipliersThe constraint \(v^\top v = 1\) enters with a multiplier \(\lambda\)

1Add the constraint to the objective: \(\mathcal L(v, \lambda) = v^\top \Sigma\, v - \lambda\,(v^\top v - 1)\) 2Set the gradient in \(v\) to zero (\(\Sigma\) is symmetric): \(\dfrac{\partial \mathcal L}{\partial v} = 2\Sigma v - 2\lambda v = 0\) 3The best direction is an eigenvector of the covariance matrix: \(\Sigma\, v = \lambda\, v\) 4And its eigenvalue is the variance it keeps: multiply by \(v^\top\), \(v^\top \Sigma v = \lambda\, v^\top v = \lambda\)

So the largest eigenvalue gives the first principal component. The next one, maximised among directions orthogonal to \(v_1\), is the eigenvector with the second largest eigenvalue, and so on.

The eigenvalue problem, spelled out\(\Sigma\) is \(d \times d\) and has \(d\) eigenvectors. Stack them as the columns of one matrix.

1One direction at a time: a unit vector that \(\Sigma\) only stretches, by \(\lambda\). A covariance has \(d\) of them, orthogonal, with \(\lambda_j \ge 0\): \(\Sigma\, v_j = \lambda_j\, v_j, \qquad j = 1, \dots, d, \qquad \lambda_1 \ge \lambda_2 \ge \dots \ge \lambda_d \ge 0\) 2Stack the \(d\) equations side by side, \(\Sigma V = V \Lambda\): the \(d \times d\) matrix \(V\) holds the eigenvectors as columns, \(\Lambda\) the eigenvalues on its diagonal: \(\Sigma \begin{bmatrix} | & & | \\ v_1 & \cdots & v_d \\ | & & | \end{bmatrix} = \begin{bmatrix} | & & | \\ v_1 & \cdots & v_d \\ | & & | \end{bmatrix} \begin{bmatrix} \lambda_1 & & \\ & \ddots & \\ & & \lambda_d \end{bmatrix}\) 3\(V\) is orthogonal, \(V^\top V = V V^\top = I\), so \(\Sigma\) itself is a sum of stretches, one per direction: \(\displaystyle \Sigma = V \Lambda V^\top = \sum_{j=1}^d \lambda_j\, v_j v_j^\top\)

Beirut and Damascus: \(\Sigma = \begin{bmatrix} 34.9 & 47.2 \\ 47.2 & 69.0 \end{bmatrix}\) °C², \(v_1 = \) (0.57, 0.82), \(\lambda_1 = \) 102.1, \(\lambda_2 = \) 1.7; the trace 103.8 is \(\lambda_1 + \lambda_2\), the total variance.

What an eigenvector isA matrix turns most vectors. Turn \(u\) with the slider and watch \(\Sigma u\): the directions it does not turn are the eigenvectors, and the stretch is \(\lambda\).

\(\Sigma u\) is turned from \(u\) byand has length\(u^\top \Sigma u\), the variance along \(u\)

The circle of unit vectors becomes an ellipse whose axes are the eigenvectors and whose half-lengths are the eigenvalues: a symmetric matrix never shears, it only stretches along \(v_1\) and \(v_2\) (3Blue1Brown, Essence of linear algebra, chapter 14). The weather's \(\Sigma\) is so lopsided (98.4% along \(v_1\)) that it turns almost every \(u\) onto \(v_1\).

From the eigenvectors back to the data\(x\) is not written in \(\Sigma v = \lambda v\), but every day is inside \(\Sigma\); once \(V\) is known, each day is measured against it

1Where the data went: \(\Sigma\) averages the outer products of the days, so \(V\) depends on all of them at once: \(\displaystyle \Sigma = \frac{1}{n} \sum_{i=1}^n x^{(i)} x^{(i)\top} = \frac{1}{n} X^\top X\) 2Project: \(k\) dot products with the first \(k\) eigenvectors, the columns of \(V_k \in \mathbb{R}^{d \times k}\); each \(z_j\) is the exercise's projection, onto \(v_j\): \(z^{(i)} = V_k^\top x^{(i)} = \big(v_1^\top x^{(i)},\ \dots,\ v_k^\top x^{(i)}\big)^\top \in \mathbb{R}^k, \qquad Z = X V_k \in \mathbb{R}^{n \times k}\) 3Reconstruct: put the \(k\) numbers back on their directions, and add the mean day: \(\displaystyle \hat x^{(i)} = \mu + V_k z^{(i)} = \mu + \sum_{j=1}^k z_j^{(i)}\, v_j\)

With \(k = d\) nothing is lost, since \(V V^\top = I\). For Beirut and Damascus, \(k = 1\) keeps 98.4% of the variance: one number per day, its position along \(v_1\). If the data were standardised as well (each feature divided by its spread \(s_c\), the centring slide), PCA runs on \(x_c / s_c\): the directions change, and the reconstruction scales back, \(\hat x = \mu + s \odot V_k z\).

The eigenvalue route in codeCode: runs on the weather. Three corrections to the F25 slide: divide by \(n\), use eigh for a symmetric matrix, and sort

import numpy as np, pandas as pd
df = pd.read_csv('levant_era5_daily_mean_temp_2010_2025.csv')
X = df.drop(columns='date').to_numpy()           # n = 5844 days by d = 22 cities, deg C
X_centered = X - X.mean(axis=0)                  # n by d
Sigma = X_centered.T @ X_centered / len(X)       # d by d covariance
lam, V = np.linalg.eigh(Sigma)                   # eigh: symmetric, real, ascending order
lam, V = lam[::-1], V[:, ::-1]                   # largest first; column j of V is v_j
k = 3
Z = X_centered @ V[:, :k]                        # n by k: the k numbers per day
print(np.round(lam[:3] / lam.sum(), 3))          # shares 95.5%, 1.5%, 0.9%
print(Z.shape, np.round(Z[0], 1))                # (5844, 3) and the first day's three numbers
print(np.allclose(V.T @ V, np.eye(22)))          # the directions are orthonormal

np.linalg.eig returns eigenvalues in no particular order and, through rounding, sometimes with tiny imaginary parts. eigh is for symmetric matrices: real results, sorted from smallest to largest, so reverse them. Without the \(1/n\) the eigenvectors are the same and every eigenvalue is \(n\) times too large.

What are the dimensions of \(x\), \(\Sigma\) and \(v\) here?A cloud of points near a plane in three dimensions. Drag to turn it; the slider moves the points off the plane.

\(\lambda_1, \lambda_2, \lambda_3\)kept by the plane of \(v_1, v_2\)
✏ exercise · do it now

Write the shape of each, for this cloud and for the weather (22 cities over 5,844 days), then turn the slide:

  • one example \(x^{(i)}\), and the data matrix \(X\)
  • the covariance matrix \(\Sigma\)
  • one principal direction \(v_j\), and how many there are
  • the \(k\) numbers \(z^{(i)}\) kept for an example, and all of them stacked

How many eigenvalues are large, and why? What happens to \(\lambda_3\), and to \(v_3\), as the cloud thickens?

The dimensionsThe answer to the exercise; below, the weather

The cloud. Each point is \(x^{(i)} \in \mathbb{R}^3\), so \(\Sigma\) is \(3 \times 3\) and there are three directions \(v_1, v_2, v_3 \in \mathbb{R}^3\). The points lie close to a plane: two eigenvalues are large, the third is small, and \(v_3\) is the normal to the plane. Thicken the cloud and \(\lambda_3\) grows; at some thickness there is no plane to find.

  • A day and the data. 22 numbers per day, one row per day. \( x^{(i)} \in \mathbb{R}^{22}, \qquad X \in \mathbb{R}^{5844 \times 22} \)
  • The covariance. One row and one column per city, whatever the number of days. \( \Sigma = \tfrac{1}{n} X^\top X \in \mathbb{R}^{22 \times 22} \)
  • The directions. 22 of them, each a weight per city. \( v_1, \dots, v_{22} \in \mathbb{R}^{22} \)
  • What is kept. \(k\) numbers per day; stacked, \(XV_k\) with \(V_k\) the first \(k\) columns. \( z^{(i)} \in \mathbb{R}^{k}, \qquad Z = X V_k \in \mathbb{R}^{5844 \times k} \)

Truncate: the percentage of variance preservedThe 22 eigenvalues of the weather's covariance, largest first. Move \(k\).

\[\frac{\sum_{j=1}^k \lambda_j}{\sum_{j=1}^d \lambda_j} \times 100\]
variance preservedrms error per city per day

The total, \(\sum_j \lambda_j\), is the trace of \(\Sigma\): the sum of the 22 cities' variances, 1003 °C². The first eigenvalue is 957.8 of it, 95.5%. Rules of thumb for \(k\): the elbow of this plot, a share such as 95%, or, when the numbers feed a model, the \(k\) that predicts best on held-out data.

A day rebuilt from \(k\) numbersThe 22 cities, west to east: dots are the day, bars \(\hat x^{(i)}\), the mean day plus \(k\) patterns. Move \(k\), pick a day.

\[z^{(i)} = V_k^\top x^{(i)} \in \mathbb{R}^k, \qquad \hat x^{(i)} = \mu + V_k\, z^{(i)} = \mu + \sum_{j=1}^k z^{(i)}_j\, v_j, \qquad V_k = \big[\, v_1 \cdots v_k \,\big] \in \mathbb{R}^{22 \times k}, \quad x^{(i)} \text{ centred}\]

This day is off by (rms over the cities); over all days, .

One number, mostly: the seasonWhat the first direction weighs, city by city, and the first number itself, \(z_1^{(i)} = v_1^\top x^{(i)}\), day by day. Click a city.

The answer

One number per day keeps 95.5% of the variance and leaves 1.43 °C of error per city, against 6.75 °C for the mean day alone. Three numbers bring it under a degree (0.97 °C).

Yellow: \(z_1\) for every day of 2024, the 22 centred temperatures weighted by \(v_1\) and summed. Blue: its monthly means over all 16 years. Every weight is positive: \(z_1\) is how warm the whole region is, low in January (-42) and high in August (41). The weights follow each city's yearly swing (correlation 0.995): largest at Gaziantep (0.30), smallest at Alexandria (0.16).

The singular value decomposition of \(X\)The same \(V\), computed from \(X\) itself, with no \(\Sigma\) to form. Pick a form and move \(k\): what a truncation keeps stays lit.

\[X = U\,\Xi\,V^\top = \sum_{j=1}^{d} \sigma_j\, u_j v_j^\top\]

\(U^\top U = I\) and \(V^\top V = I\): orthonormal columns

Columns of \(V\): the principal directions (\(v_1\) is Vt[0]). \(\sigma_j\): the singular values, largest first. The numbers kept: \(Z = XV = U\Xi\). Why this \(V\) is the eigenvalue problem's: next slide.

Why the SVD gives the principal componentsPut the SVD into the covariance matrix, one step at a time

1Use \(X = U\Xi V^\top\) and \(U^\top U = I\): \(\displaystyle \Sigma = \tfrac{1}{n} X^\top X = \tfrac{1}{n} V\,\Xi^\top U^\top U\,\Xi\, V^\top = V \Big(\tfrac{1}{n}\Xi^\top \Xi\Big) V^\top\) 2\(\Xi^\top\Xi\) is diagonal with entries \(\sigma_j^2\): this is \(\Sigma = V \Lambda V^\top\) again, so each column of \(V\) is an eigenvector of \(\Sigma\): \(\displaystyle \Sigma\, v_j = \frac{\sigma_j^2}{n}\, v_j, \qquad \lambda_j = \frac{\sigma_j^2}{n}\) 3And the numbers kept are the columns of \(U\), scaled: \(\displaystyle Z = X V = U\,\Xi\,V^\top V = U\,\Xi, \qquad z_j^{(i)} = \sigma_j\, u_{ij}\)

For the weather, \(\sigma_1 = \) 2366 and \(n = \) 5,844, so \(\lambda_1 = \sigma_1^2/n = \) 957.8 °C², the first bar of the scree plot. Computing \(X^\top X\) squares the condition number and loses digits of accuracy; the SVD works on \(X\) itself, which is why it is the standard route (Brunton and Kutz, 2022).

Truncation in code, and why it is the best rank-\(k\) approximationCode: the error of the rank-\(k\) reconstruction is the sum of the squared singular values it dropped

import numpy as np, pandas as pd
df = pd.read_csv('levant_era5_daily_mean_temp_2010_2025.csv')
Xc = df.drop(columns='date').to_numpy(); Xc = Xc - Xc.mean(axis=0)   # 5844 by 22, centred
U, s, Vt = np.linalg.svd(Xc, full_matrices=False)   # economy: U is 5844 by 22, s has 22 values, Vt is 22 by 22
for k in [1, 2, 3, 22]:
    Xk = (U[:, :k] * s[:k]) @ Vt[:k]                # k columns of U, k singular values, k rows of Vt
    print(k, round(((Xc - Xk)**2).sum()), round((s[k:]**2).sum()))   # the two numbers agree

Eckart and Young (1936): among all matrices of rank \(k\), \(X_k = U_k \Xi_k V_k^\top\) is the closest to \(X\) in squared error, and the error left is \(\|X - X_k\|_F^2 = \sum_{j > k} \sigma_j^2\). The PCA reconstruction with \(k\) components is exactly \(X_k\); dividing by \(n\) turns the dropped \(\sigma_j^2\) into the dropped eigenvalues of the scree plot. The three forms, in the shape of \(U\): full \(n \times n\), economy \(n \times d\) (full_matrices=False), truncated \(n \times k\).

PCA of the weather in codeCode: prints the numbers these slides quote

import numpy as np, pandas as pd
df = pd.read_csv('levant_era5_daily_mean_temp_2010_2025.csv')
X = df.drop(columns='date').to_numpy()                # 5844 days by 22 cities, deg C
Xc = X - X.mean(axis=0)                               # centre each city
U, s, Vt = np.linalg.svd(Xc, full_matrices=False)     # rows of Vt are v_1, v_2, ...
lam = s**2 / len(X)                                   # eigenvalues of the covariance
print(np.round(lam[:3] / lam.sum(), 3))               # 95.5%, 1.5%, 0.9%
for k in [0, 1, 2, 3]:
    Xk = (U[:, :k] * s[:k]) @ Vt[:k]                  # rank-k reconstruction
    print(k, round(np.sqrt(((Xc - Xk)**2).mean()), 2))  # rms error, deg C
v1 = Vt[0] * np.sign(Vt[0].sum())                     # a direction has no sign: make v_1 positive
print(df.columns[1:][v1.argmax()], df.columns[1:][v1.argmin()])   # largest and smallest weight

Expected: shares 95.5%, 1.5%, 0.9%; errors 6.75 °C, 1.43 °C, 1.17 °C, 0.97 °C; then Gaziantep and Alexandria. A direction is defined only up to its sign, so libraries can return \(-v_j\); fix a convention before you read the weights.

Check yourself: variance preservedSix eigenvalues of a covariance matrix, largest first. Work it out on paper, type, check. New numbers each time.

A dataset has \(d = 6\) features. The eigenvalues of its covariance matrix are on the left.

(a) Share of the variance kept by the first two components:%
(b) The smallest \(k\) that keeps at least 90%:
(c) The variance thrown away with \(k = 2\) (data units squared):

Check yourself: stacking a new datasetDecide what one example is, then give the rows and columns of every object. New dataset each time.

One example, one row of \(X\), is:

Then the shapes (rows × columns). \(n\) and \(d\) are in the text; count, do not guess.

Check yourself: one projection by handA centred point \(x\) and a unit vector \(v\). Three numbers, then check. New numbers each time.

(a) \(z = x^\top v\), the position of \(x\) along \(v\):
(b) The closest point to \(x\) on the line, \(z\,v\):(,)
(c) The squared distance from \(x\) to the line, what one number loses:

Over a dataset, the variance kept by \(v\) is the mean of \(z^2\) and the variance lost is the mean of (c): the two bars of the best-axis slide.

Two ways onEach course takes one part from here

Part 4 of 5

Eigen-digits

What does PCA find in pictures of handwriting?

Introduction to Machine Learning

Singular Value DecompositionA dataset of digits: each row of \(X\) is one 16 by 16 picture, read as 256 numbers

\(n\times d\)\(X\)\(x_1\)
\(x_2\)
\(\vdots\)
= \(n\times n\)\(U\)\(u_1\,u_2\cdots\) \(n\times d\)\(\Xi\)\(\sigma_j\) \(d\times d\)\(V^\top\)\(v_j^\top\)
eigen-digits

Here \(n = \) 20,000 digits and \(d = \) 256 pixels, values from 0 (black) to 1 (white). Each \(v_j\) has 256 entries, one per pixel, so it can be drawn as a picture: an eigen-digit. The F25 slide did this with faces (eigenfaces, Turk and Pentland, 1991); these are MNIST digits (LeCun and colleagues, 1998), shrunk to 16 by 16.

Eigen-digitsThe mean digit and the first 15 directions, red where a direction adds ink and blue where it removes it. Click one.

Pixels are all in the same unit, so the digits are centred and not normalised; 14 border pixels are black on every digit, have no spread, and could not be divided by it anyway. The first direction keeps 11.3% of the variance, far less than the weather's 95.5%: a digit has more independent parts than a day.

How many components is a digit?With your neighbour: guess the smallest \(k\) at which the rebuilt digit is readable. Then check, on several digits.

the digit, 256 numbers

variance kept, all digitsread correctly by a 3-nearest-neighbour readerthis digit's rms pixel error

Here each \(v_j\) is an eigen-digit, a picture of 256 numbers, and \(z_j = v_j^\top (x - \mu)\) is one number: how much of eigen-digit \(j\) this digit contains.

\(\hat x = \mu + \sum_{j=1}^k z_j v_j\): the mean digit plus \(k\) eigen-digits, each weighted by this digit's own score, the reconstruction of part 3 with \(d = 256\). These 20 digits were held out from the reader that judges the rebuilt digits; the eigen-digits themselves were found from all 20,000.

Readable long before the variance is keptThe share of the variance kept (blue), and how often held-out digits rebuilt from \(k\) components are read correctly (yellow)

Two criteria for \(k\). Blue is the usual one, the share of the variance kept: 51 components for 90%, 125 for 99%. Yellow is the task: a reader is shown digits rebuilt from \(k\) components and we count how often it names them right. At \(k = 30\) only 81% of the variance is kept, yet 95% of the rebuilt digits are read correctly, against 96.6% for the originals.

How the numbers were made. Computed for this deck (scripts/verify_pca_svd.py in the course repository) on the MNIST digits of LeCun, Bottou, Bengio and Haffner (1998), shrunk to 16 by 16: PCA on 20,000 digits; a 3-nearest-neighbour reader fitted on 16,000 full digits; the other 4,000 rebuilt from \(k\) components and shown to it. Nothing here is quoted from a paper.

The variance thrown away is mostly the small wobbles of each person's pen, not the shape that makes a 4 a 4. Variance kept measures pixels, not meaning: for a task, choose \(k\) by how well the task goes.

Two numbers per digit, as a map1,500 held-out digits placed by \(z_1\) and \(z_2\), coloured by what they are. PCA never saw the labels. Pick a digit.

Zeros gather at one end of \(z_1\) (their mean is +2.0) and ones at the other (−2.0); the other eight digits overlap in the middle, every mean within 0.4 of zero. Two numbers are enough to see some structure and too few to separate ten digits.

PCA keeps the directions of largest spread, which is not the same as the directions that separate classes. Methods that bend the map, such as t-SNE and UMAP, come with autoencoders.

End of the Introduction to ML pathPart 5 is for ML for Science; you are welcome to read it

PCA is one linear map from pictures to a few numbers and one linear map back. An autoencoder replaces both maps with networks: the autoencoder in the architectures deck is the place to see it next.

What to take away

Part 5 of 5

Weather modes

What do the patterns mean, and what can they not do?

ML for Science

Read the weather modesEach pattern \(v_j\) as weights on the map: red positive, blue negative. Teams: say what patterns 2 and 3 mean before reading the right column.

This pattern keeps .

  • \(v_2\) (1.5%) is not the coast against inland. It is west against east: Athens +0.51, Amman −0.31 (correlation with longitude -0.83). Its monthly mean is -2.5 in April and +2.7 in July: inland warms first in spring, the Aegean holds its heat in summer.
  • \(v_3\) (0.9%) is the south-eastern coast against the north: Haifa +0.35, Gaziantep −0.39. The sea against the continent comes third.

Take out the average yearFor each city, a mean plus three yearly harmonics, fitted over 16 years; what is left is the weather

The average year explains 87.9% of the variance, less than PCA's first number (95.5%), which also follows whole months that run warm or cool everywhere. On the anomalies (previous slide, second button) pattern 1 has one sign everywhere and keeps 71.9%: a warm or cold spell over the region, strongest inland (Zahle) and weakest at Alexandria. Pattern 2 is the same west against east seesaw (8.6%); pattern 3 is Cairo +0.40 against Gaziantep −0.42 (5.2%). 5 patterns keep 90% of the anomalies.

The weather moves, and a pattern cannotHow well one city's anomaly today matches another's \(L\) days later. Pick a pair.

Athens's anomaly matches Damascus's two days later better (0.50) than on the same day (0.34): weather systems cross the region from west to east. In PCA's terms, \(z_2\) today predicts \(z_1\) two days later (correlation 0.37), although on the same day the two are uncorrelated by construction.

Each PCA term is a fixed map times a number that changes in time, \(z_j(t)\, v_j\). A travelling pattern needs several such terms, and PCA ranks them by variance, not by how they move. Dynamic mode decomposition looks for patterns that each move in time in one simple way.

The same SVD in the notation of dynamic mode decompositionStack the days as columns instead of rows: a snapshot matrix

\[X^\top = V\,\Xi^\top U^\top \quad\text{is written}\quad X_{\mathrm{snap}} = \begin{bmatrix} | & | & & | \\ \mathbf{x}_1 & \mathbf{x}_2 & \cdots & \mathbf{x}_m \\ | & | & & | \end{bmatrix} \approx U_r\,\Sigma_r\,V_r^\top\]
this deckdynamic mode decompositionfor the weather
\(d\), numbers per example\(n\), the state size22 cities
\(n\), examples\(m\), snapshots in time5,844 days
\(v_j\), columns of \(V\)\(\mathbf{u}_j\), columns of \(U\): spatial modesthe maps of the last slides
\(\Xi\), singular values \(\sigma_j\)\(\Sigma\), the same \(\sigma_j\)\(\sigma_1\) is the season
\(\sigma_j u_j\), the scores \(z_j\)\(\sigma_j \mathbf{v}_j^\top\), rows of \(\Sigma V^\top\): temporal modes\(z_1\) through the year

There \(\Sigma\) holds the singular values; it is not a covariance. Climate scientists call the spatial modes empirical orthogonal functions, fluid dynamicists POD modes: both are this SVD.

Now your project's matrixIn the iteration log: an SVD of your own data, and what its first two patterns mean

✏ exercise · do it now
  1. Write your data as a matrix: what is a row, what is a column, what are \(n\) and \(d\)?
  2. Decide what to subtract before the SVD (the mean, an average cycle) and whether the columns need normalising (are they in one unit?).
  3. Run np.linalg.svd(X, full_matrices=False) and plot \(\sigma_j^2 / \sum \sigma^2\). How many patterns keep 90%?
  4. Draw \(v_1\) and \(v_2\) in the shape of one example (a map, a spectrum, a picture) and say in one sentence each what they mean. Then check that sentence against the data.

Next: patterns that moveThe SVD finds the directions; it says nothing about time

Shuffle the 5,844 days and PCA returns the same patterns: it never used their order. Dynamic mode decomposition uses the order, by fitting the linear map that takes each day to the next, \(\mathbf{x}_{t+1} \approx A\,\mathbf{x}_t\), and starts from this SVD to do it.

That is the next deck, linear dynamical systems and DMD, on the wake behind a cylinder, where the SVD's spatial modes \(\mathbf{u}_j\) and temporal modes \(\sigma_j \mathbf{v}_j^\top\) appear in the notation of the last slide.

What to take away

  1. Centre, then find the direction of most spread. It is also the line closest to the data: the variance kept and the squared error lost add up to a fixed total.
  2. That direction is an eigenvector of the covariance, \(\Sigma v = \lambda v\), and its eigenvalue is the variance it keeps.
  3. Compute it with the SVD of the centred data, \(X = U\Xi V^\top\): the directions are the columns of \(V\), and \(\lambda_j = \sigma_j^2/n\).
  4. A day of Levant weather needs one number for 95.5% of its variance, how warm the region is, and three to be off by less than a degree on average. Digits need far more.
  5. Variance is not meaning, and a fixed pattern cannot travel: read the patterns against the data, and use the order in time when it matters.