Machine Learning · Insper

Dimensionality Reduction

A few new columns that keep what matters

The curse of dimensionality, PCA (principal component analysis) by hand, and the maps of t-SNE (t-distributed stochastic neighbor embedding) and UMAP (uniform manifold approximation and projection)

Why reduce? The reason picks the method

goalwhat the method must delivertypical method
see the dataa 2-D or 3-D picture; local fidelity is enought-SNE, UMAP
compress / speed upreconstruction, and a transform for new dataPCA
remove noise / collinearitydrop the low-variance directionsPCA
feed another modelan honest fit/transform, no leakagePCA (almost always)
Mixing up these reasons is behind most misuse of these methods.

The path of this lesson

  1. The cursedistances lose their contrast
  2. Linear: PCAby hand, scaling, choosing k, reconstruction
  3. Nonlinear: t-SNE, UMAPwhere PCA runs out, what a map does not tell
  4. Compare and chooseside by side, forbidden statements, the goal decides
Each stage answers one question: why do many columns hurt? → which few directions keep the most variance? → how do we map a curved structure, and what can the map say? → which method fits which goal?
Stage 1 · Why do many columns hurt?

The curse of dimensionality

Take random points in the unit cube and look at the distances between them.

Predict. In 1,000 dimensions, how much farther is a point's farthest neighbor than its nearest: 40 times, 10 times, or about 10%?

Simulator: distances in \(d\) dimensions

Push \(d\) up and watch the histogram of distances collapse into a spike.

Relative contrast, measured

\((d_{\max} - d_{\min})/d_{\min}\), median over 400 points:

\(d\)noise columns2-D sheet in \(d\) columns
242.9739.23
102.2741.51
1000.3945.88
10000.1144.24
Relative contrast against the number of columns: noise falls from 43.0 to 0.11; the rotated 2-D sheet stays between 39 and 46
Concentration is not caused by the number of columns: the rotated sheet has 1,000 columns and does not move. What hurts is columns that carry no information. The real question: how many directions actually vary?
Stage 2 · Which few directions keep the most variance?

PCA: the directions of maximum variance

Centered data \(X\); covariance \(C = \frac{1}{n-1} X^\top X\).

\[ w_1 = \arg\max_{\|w\|=1} w^\top C\, w \qquad \text{EVR}_k = \frac{\lambda_k}{\sum_j \lambda_j} \]
  • \(w_1\) is the eigenvector of \(C\) with the largest eigenvalue \(\lambda_1\); the next is orthogonal to it, and so on.
  • \(\lambda_k\) is the variance captured by component \(k\); EVR is the explained variance ratio.
By Pythagoras, the part of each point along the line plus the part perpendicular to it is fixed: maximum variance = minimum reconstruction error.

PCA by hand: center, then covariance

\(x\)\(y\)\(x-\bar x\)\(y-\bar y\)
24−3−1
42−1−3
5500
6813
8631

1. The mean is \((5, 5)\).

2. With \(n - 1 = 4\): variance of \(x\) = \((9+1+0+1+9)/4 = 5\), the same for \(y\); covariance = \((3+3+0+3+3)/4 = 3\).

\[ C = \begin{pmatrix} 5 & 3 \\ 3 & 5 \end{pmatrix} \]

PCA by hand: eigenvalues and directions

3. \(\det(C - \lambda I) = 0\):

\[ \lambda^2 - \underbrace{10}_{\text{trace}}\lambda + \underbrace{16}_{\det} = 0 \quad\Rightarrow\quad \lambda_1 = 8,\ \lambda_2 = 2 \]

Check: \(8 + 2 = 10 = 5 + 5\), the total variance. So \(\text{EVR}_1 = 8/10 = 80\%\).

4. \((C - 8I)w = 0\) gives \(w_1 = w_2\): PC1, the first principal component, = \((1,1)/\sqrt{2}\), the 45° diagonal. PC2 = \((-1,1)/\sqrt{2}\).

PCA by hand: project and reconstruct

The five points, the two principal directions with lambda 8 and 2, residuals to the diagonal; captured and thrown-away variance always add to 10

5. Scores on PC1: \(-2\sqrt2, -2\sqrt2, 0, 2\sqrt2, 2\sqrt2\). Their variance is 8: the eigenvalue.

6. Keep PC1 only: \((2,4)\) and \((4,2)\) become \((3,3)\); squared error \(4 \times 2 = 8\), and \(8/4 = 2 = \lambda_2\).

The eigenvalue is the variance along the component. The reconstruction error is exactly the variance you threw away.

The same in code, and two details

  • np.linalg.eigh returns the eigenvalues in ascending order: the best direction comes last. Forgetting to sort is a silent bug.
  • scikit-learn's PCA agrees: explained_variance_ratio_ = [0.8, 0.2].
  • Signs are arbitrary: \(w\) and \(-w\) are both eigenvectors; read relative signs inside a component, never the absolute sign.
  • New points need no refitting: \((9,7) - (5,5) = (4,2)\), and \((4+2)/\sqrt2 = 4.243\), exactly pca.transform.
This is what lets PCA sit inside a pipeline. t-SNE cannot do it.

Simulator: rotate the line

Predict. As you turn the line, at how many angles does the captured variance peak? Then press find PC1.

The scaling question

Wine: 13 chemical measurements of 178 wines. Proline has standard deviation 314.9; hue is around 1.

Predict. On the raw columns, what will PC1 be?
variance ratio of PC1, PC2, PC3largest weights in PC1
raw columns0.998, 0.002, 0.0proline 1.000
standardized0.362, 0.192, 0.111flavanoids, total phenols, OD280

99.8% is not a discovery about wine: it is a measurement of the unit of proline.

Does it matter downstream?

Wine on PC1 and PC2: raw, the cultivars overlap; standardized, they form three separate groups

A k-NN classifier (k-nearest neighbors) that sees only the two PCA coordinates, scored on 30% of the wines:

raw → PCA(2)

0.722

scaled → PCA(2)

0.926
Standardize when columns are in different units; not blindly when they share a unit and their variance means something (the pixels of an image). And keep PCA inside the pipeline.

Choosing \(k\): 64 pixels of digits

Scree bars of the 64 digit components and the cumulative explained variance; 2 components keep 28.5%, 90% needs 21, 95% needs 29
  • 2 components keep 28.5%: a 2-D PCA picture shows less than a third.
  • 90% needs 21, 95% needs 29, 99% needs 41.
  • PCA(n_components=0.95) searches for you.

Criteria, most trusted first: a cumulative-variance threshold; the elbow (subjective); downstream performance on validation data; Kaiser's rule (fragile).

Reconstruction: what \(k\) components keep

\(k\)kepterror / imagediscarded \(\lambda\)
114.9%1022.61022.6
228.5%858.9858.9
1073.8%314.5314.5
2995.5%54.354.3
64100.0%0.00.0
Four digits rebuilt from k = 1 to 64 components; recognizable at 10, close to the original at 29
The two last columns are the same number: the error is the sum of the discarded eigenvalues. Hence compression and denoising.

Simulator: rebuild an image from \(k\) components

Predict. How few components does your eye need before it stops objecting?

Five PCA pitfalls

  1. Not standardizing columns in different units: you measure the unit.
  2. Fitting before the split: the test rows shape the projection.
  3. Assuming high-variance components are the useful ones for prediction: PCA never looks at the target.
  4. Reading components as real-world factors: signs are arbitrary, and close eigenvalues allow any rotation.
  5. PCA on one-hot columns without thinking: a 0/1 column has variance \(p(1-p)\), so rare categories vanish.
Stage 3 · How do we map a curved structure, and what can the map say?

Where PCA runs out

PCA can only rotate and project: it moves the axes, never bends them.

The Swiss roll: a 2-D sheet rolled up in 3-D. Two points on opposite layers are close in straight line, far along the sheet.

Predict. Project the roll with PCA. What happens to the colors of the two layers?

Simulator: the Swiss roll

Tick mark a pair of points, then project with PCA. Euclidean distance goes through the empty space; geodesic distance walks along the sheet.

A score for a map: trustworthiness

Of the \(k\) nearest neighbors of each point on the map, how many were really neighbors? 1 = no intruders; a random map ≈ 0.5.

PCA on the roll

0.810
layers land on top of each other

Isomap

0.976
walks a 10-neighbor graph: unrolls the sheet
The bet of every nonlinear method: Euclidean distance is only trustworthy locally. Build a neighborhood graph where it holds; infer the global shape from it.

t-SNE in three steps

  1. Neighborhoods in the data: a Gaussian around each point, its width tuned per point to a perplexity ("effective number of neighbors"). Dense and sparse regions get different widths.
  2. Neighborhoods on the map: a Student-t, with heavy tails, to make room in 2-D. Side effect: distances between groups stop meaning anything.
  3. Minimize the Kullback–Leibler divergence \(\text{KL}(P\,\|\,Q)\): true neighbors drawn far apart are expensive; far points drawn close are almost free.
What is close in the data is usually close on the map. What is close on the map may not be close in the data.

Simulator: real t-SNE, in your browser

Try. Run it on uniform noise; change only the perplexity; compare groups of different sizes.

What a t-SNE map does not tell you, measured

datat-SNE
how many times wider the loose group is11.61.0
how many times farther the far group is10.01.3
Original data and t-SNE: groups 11.6 times different in width come out the same size; a group 10 times farther comes out 1.3 times farther; noise becomes clumps
Not bugs, the design: the per-point width equalizes dense and sparse groups, and the heavy tail makes "far" and "very far" cost the same.

Perplexity changes the picture

perplexitydistance ratio
23.3
51.1
301.3
1007.0
The three groups at perplexity 2, 5, 30 and 100: fragments at 2 and 5, equidistant at 30, the far group pushed away at 100

At 2 and 5 every group shatters into fragments that do not exist. There is no "right" perplexity: usually 5–50, smaller than the smallest group you want to see.

Run several and trust only what persists. Report the perplexity like a random seed.

t-SNE finds groups in noise

best silhouettetrustworthiness
10-column noise itself0.09
its t-SNE map, perplexity 300.380.86
4-column noise, t-SNE map0.430.97
  • The map looks four to five times more "clustered" than the data.
  • A good trustworthiness does not certify the structure: noise has local neighborhoods too.
The cure: a null comparison. Shuffle each column independently, run the same pipeline, compare. If the shuffled data look equally structured, you saw the algorithm.

Axes and runs

The loss depends only on distances on the map: rotating or mirroring it changes nothing. Digits, random initialization, seed 0 against seeds 1, 2, 3:

horizontal axes |correlation|

1.0, 0.0, 0.1

seed 2 came out rotated a quarter turn

neighbors in common

90%, 94%, 85%

on noise: only 47%

The neighborhoods are real; the orientation is not. init="pca" (the default) makes the map reproducible, which is not the same as stable.

UMAP: a graph of neighbors

  1. Each point is linked to its n_neighbors nearest points, with fuzzy weights; no point is left isolated.
  2. The weights are merged into one symmetric fuzzy graph.
  3. A 2-D layout by stochastic gradient descent: edges attract, sampled random points repel; an explicit penalty for putting distant points close.

n_neighbors (15)

the scale at which Euclidean distance is trusted: local detail against global structure

min_dist (0.1)

how tightly points are packed: cosmetic, not structural

UMAP has transform: fit on 80% of the digits, 96.4% of the new images land next to an image of the same digit.
Stage 4 · Which method fits which goal?

PCA vs t-SNE, side by side

Digits: PCA overlaps the classes (0.830), t-SNE separates them (0.992) but splits the 1s; Swiss roll: PCA smears (0.810), t-SNE cuts the sheet into pieces (0.976)

Trustworthiness on the digits, for neighborhoods of size \(k\):

k=5k=30k=100
PCA0.8300.8300.835
t-SNE0.9950.9850.963
UMAP0.9890.9830.961

t-SNE splits the 1s into islands and cuts the roll into pieces. No winner until you say which scale you care about.

The comparison table

PCAt-SNEUMAP
naturelinear, deterministicnonlinear, stochasticnonlinear, stochastic
local structureweakvery goodvery good
global structurebest (variance)weakmoderate
group distances / sizesyes / yesno / nopartly / no
transform new datayes, trivialnoyes
key hyperparameters\(k\), scalingperplexity, iterationsn_neighbors, min_dist
preprocessing for a modelrecommendednot advisedwith care, in the pipeline

Seven forbidden statements about a t-SNE/UMAP plot

  1. "This group is bigger, so it varies more." (11.6× in the data, 1.0× on the map)
  2. "These two groups are close, so they are similar." (10× in the data, 1.3× on the map)
  3. "There are 5 groups in the data." There are 5 blobs on the plot.
  4. "The horizontal axis represents X." Rotation and reflection are arbitrary.
  5. "I ran it once and saw this." Vary seed, perplexity, sample.
  6. "I used the 2 t-SNE components as features." No honest transform.
  7. "I ran t-SNE on the whole dataset and then split." Leakage.
A plot is a hypothesis, not a result. A claim needs a number: reconstruction error, trustworthiness at several scales, a null comparison, a downstream model.

Choosing a method

  • It will feed another model, or you need reversibility → PCA. Full stop.
  • You want to look at the data to form hypotheses, up to a few thousand points → t-SNE or UMAP, with PCA first if \(d\) is large.
  • \(n\) is large, or you must project new data onto the same map → UMAP.
  • You need reliable global structure in one picture → none is ideal: show PCA and t-SNE/UMAP.

Summary

  1. Distances concentrate when columns carry no information; ask how many directions vary.
  2. PCA = eigenvectors of the covariance; \(\lambda\) is the variance kept; the error is the variance thrown away.
  3. Standardize columns in different units; fit PCA inside the pipeline.
  4. t-SNE and UMAP keep local neighborhoods; sizes, distances and axes on their maps mean nothing.
  5. Only UMAP and PCA can place new points.
Lab · about a minute on a laptop

Mapping handwritten zip codes

  • USPS: 9,298 handwritten digits from envelopes, 16×16 = 256 columns.
  • Download the lab notebook and open it in Jupyter or Colab; in Colab, run !pip install umap-learn first.

1. load a sample
2. how many dimensions does USPS really have?
3. compression and reconstruction error
4. three maps of the same images

5. score the maps with trustworthiness
6. perplexity
7. UMAP: n_neighbors, min_dist, new images
8. test a forbidden statement