Quiz 2

Dimensionality Reduction: PCA & t-SNE

1900 words
10 min read
Python Week 1: the first filter for runtime behavior
Visual companion
Python
Type and operator map

Python Week 1: the first filter for runtime behavior

View
Revision summary

What this note is really saying

Short form

# Dimensionality Reduction: PCA & t-SNE ## 🎯 Learning Objectives - Explain why dimensionality reduction is necessary and when to use it - Understand PCA: eigendecomposition, explained variance, and projection - Implement PCA for visualization and noise reduction - Use t-SNE for high-dimensional data visualization -...

Dimensionality Reduction: PCA & t-SNE

🎯 Learning Objectives

  • Explain why dimensionality reduction is necessary and when to use it
  • Understand PCA: eigendecomposition, explained variance, and projection
  • Implement PCA for visualization and noise reduction
  • Use t-SNE for high-dimensional data visualization
  • Compare linear (PCA) vs non-linear (t-SNE) dimensionality reduction

📋 Prerequisites

  • Linear algebra — eigenvalues, eigenvectors, covariance matrix
  • Statistics — variance, covariance, standardization
  • Visualization — scatter plots

📖 Core Content

10.1 Intuition: Seeing in 4D (and Beyond)

Imagine trying to visualize a dataset with 50 features. You can't plot 50-dimensional data, but you suspect there's structure hidden in those 50 dimensions. Maybe many features are correlated, or the "signal" lies in just a few dimensions. Dimensionality reduction compresses data to fewer dimensions while preserving as much information as possible. It's like creating a 2D shadow of a 3D object — you lose some detail but gain the ability to see (and work with) the object. (Diagram)

10.2 PCA: Principal Component Analysis

PCA finds the directions (principal components) of maximum variance in the data and projects the data onto these directions. Intuition: The first principal component is the line that best captures the spread of the data. The second component is perpendicular to the first and captures the next most variance, and so on. Step-by-step algorithm:
  1. Standardize the data (mean=0, std=1 for each feature)
  2. Compute covariance matrix
  3. Compute eigenvectors and eigenvalues of covariance matrix
  4. Sort eigenvectors by decreasing eigenvalue
  5. Select top k eigenvectors as principal components
  6. Project data: Xreduced=XWkX_{reduced} = X \cdot W_k
python
# runnable
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
iris = load_iris()
X, y = iris.data, iris.target
# Standardize
X_scaled = StandardScaler().fit_transform(X)
# PCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
print(f"Explained variance ratio: {pca.explained_variance_ratio_}")
print(f"Cumulative: {pca.explained_variance_ratio_.cumsum()}")
print(f"Components:\n{pca.components_}")
# Plot
for target, color, label in zip([0, 1, 2], ['r', 'g', 'b'], iris.target_names):
    plt.scatter(X_pca[y==target, 0], X_pca[y==target, 1],
                c=color, label=label, alpha=0.7)
plt.xlabel(f'PC1 ({pca.explained_variance_ratio_[0]:.2%})')
plt.ylabel(f'PC2 ({pca.explained_variance_ratio_[1]:.2%})')
plt.title('PCA of Iris Dataset')
plt.legend()
plt.grid(True)
plt.show()

10.2.1 Worked Example 1: 2D → 1D PCA by Hand

Points: A(1,1), B(2,1), C(3,3), D(4,2). Step 1: Standardize. Mean = (2.5, 1.75). Centered data:
  • A: (-1.5, -0.75)
  • B: (-0.5, -0.75)
  • C: (0.5, 1.25)
  • D: (1.5, 0.25) Step 2: Covariance matrix.
Σ=13[(1.5)2+(0.5)2+(0.5)2+(1.5)2(1.5)(0.75)+(0.5)(0.75)+(0.5)(1.25)+(1.5)(0.25)(1.5)(0.75)+(0.5)(0.75)+(0.5)(1.25)+(1.5)(0.25)(0.75)2+(0.75)2+(1.25)2+(0.25)2]\Sigma = \frac{1}{3} \begin{bmatrix} (-1.5)^2+(-0.5)^2+(0.5)^2+(1.5)^2 & (-1.5)(-0.75)+(-0.5)(-0.75)+(0.5)(1.25)+(1.5)(0.25) \\ (-1.5)(-0.75)+(-0.5)(-0.75)+(0.5)(1.25)+(1.5)(0.25) & (-0.75)^2+(-0.75)^2+(1.25)^2+(0.25)^2 \end{bmatrix} Σ=13[5.02.752.752.75]=[1.6670.9170.9170.917]\Sigma = \frac{1}{3} \begin{bmatrix} 5.0 & 2.75 \\ 2.75 & 2.75 \end{bmatrix} = \begin{bmatrix} 1.667 & 0.917 \\ 0.917 & 0.917 \end{bmatrix}
Step 3: Eigenvalues. Solve det(ΣλI)=0\det(\Sigma - \lambda I) = 0:
(1.667λ)(0.917λ)(0.917)2=0(1.667-\lambda)(0.917-\lambda) - (0.917)^2 = 0 λ22.584λ+1.5280.841=0\lambda^2 - 2.584\lambda + 1.528 - 0.841 = 0 λ22.584λ+0.687=0\lambda^2 - 2.584\lambda + 0.687 = 0 λ1=2.291,λ2=0.293\lambda_1 = 2.291, \lambda_2 = 0.293
Step 4: First eigenvector (for λ₁ = 2.291):
(1.6672.291)v1+0.917v2=0    0.624v1+0.917v2=0    v=[0.8270.562](1.667-2.291)v_1 + 0.917v_2 = 0 \implies -0.624v_1 + 0.917v_2 = 0 \implies v = \begin{bmatrix} 0.827 \\ 0.562 \end{bmatrix}
Step 5: Explained variance: λ₁/(λ₁+λ₂) = 2.291/(2.291+0.293) = 0.887 = 88.7%. Step 6: Project data onto PC1:
  • A: (-1.5, -0.75) · (0.827, 0.562) = -1.24 - 0.42 = -1.66
  • B: (-0.5, -0.75) · (0.827, 0.562) = -0.41 - 0.42 = -0.83
  • C: (0.5, 1.25) · (0.827, 0.562) = 0.41 + 0.70 = 1.11
  • D: (1.5, 0.25) · (0.827, 0.562) = 1.24 + 0.14 = 1.38 The 4 points are now 1D values: [-1.66, -0.83, 1.11, 1.38].

10.3 Choosing the Number of Components

Scree plot — plot explained variance vs number of components. Choose where the curve flattens (the "elbow").
python
# runnable
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
digits = load_digits()
X = digits.data  # 64 features (8×8 pixel images)
pca = PCA()
pca.fit(X)
plt.figure(figsize=(10, 4))
plt.subplot(1, 2, 1)
plt.plot(range(1, len(pca.explained_variance_ratio_)+1),
         pca.explained_variance_ratio_.cumsum(), 'bo-')
plt.xlabel('Number of components')
plt.ylabel('Cumulative explained variance')
plt.axhline(y=0.95, color='r', linestyle='--', label='95% variance')
plt.title('Scree Plot')
plt.grid(True)
plt.legend()
plt.subplot(1, 2, 2)
plt.bar(range(1, len(pca.explained_variance_ratio_)+1), pca.explained_variance_ratio_)
plt.xlabel('Component')
plt.ylabel('Variance explained')
plt.title('Individual Component Variance')
plt.tight_layout()
plt.show()
# How many components for 95% variance?
cumsum = np.cumsum(pca.explained_variance_ratio_)
k = np.argmax(cumsum >= 0.95) + 1
print(f"Components needed for 95% variance: {k}")

10.4 PCA for Noise Reduction

By projecting data onto top components and then back to original space, PCA smooths out noise:
python
# runnable
from sklearn.datasets import load_digits
import numpy as np
digits = load_digits()
X = digits.data
np.random.seed(42)
X_noisy = X + np.random.randn(*X.shape) * 15  # Add noise
# PCA denoise
pca = PCA(n_components=32)
X_pca = pca.fit_transform(X_noisy)
X_denoised = pca.inverse_transform(X_pca)
print(f"Original noise variance: {np.var(X_noisy - X):.2f}")
print(f"Denoised residual variance: {np.var(X_denoised - X):.2f}")

10.5 t-SNE: Non-Linear Visualization

t-SNE (t-distributed Stochastic Neighbor Embedding) is designed specifically for visualization (2D or 3D). It preserves local structure — nearby points in high-D stay nearby in low-D. How it works:
  1. Compute pairwise similarities in high-D space (Gaussian distribution)
  2. Compute pairwise similarities in low-D space (Student-t distribution)
  3. Minimize KL divergence between the two similarity distributions
python
# runnable
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
digits = load_digits()
X, y = digits.data, digits.target
tsne = TSNE(n_components=2, random_state=42, perplexity=30)
X_tsne = tsne.fit_transform(X)
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=y, cmap='tab10', alpha=0.7)
plt.colorbar(scatter)
plt.title('t-SNE Visualization of Digits Dataset')
plt.grid(True)
plt.show()
Key difference from PCA: t-SNE captures non-linear structure. PCA would show the digit classes as overlapping blobs; t-SNE creates well-separated clusters.

10.6 PCA vs t-SNE

AspectPCAt-SNE
TypeLinearNon-linear
GoalMaximize variancePreserve local neighborhoods
OutputDeterministicStochastic (different each run)
SpeedFast (O(mn²) or SVD O(m²n))Slow (O(m²))
InterpretabilityComponents are interpretableAxes have no meaning
Best forCompression, preprocessingVisualization (2D/3D only)

10.7 When to Use / Not Use

When to UseWhen NOT to Use
Need to visualize high-D dataWant to keep all original features
Multicollinearity problemsNeed interpretable features (use feature selection)
Noise reductionData is already low-dimensional
Pre-processing for other MLNeed to keep relationships non-linear
Compressing dataPCA assumes linearity — try t-SNE/UMAP for non-linear

📐 Key Formulas / Concepts

ConceptFormulaNotes
Covariance matrixΣ=1m1(Xμ)T(Xμ)\Sigma = \frac{1}{m-1}(X - \mu)^T(X - \mu)Measures feature correlations
Eigen-decompositionΣv=λv\Sigma v = \lambda vPrincipal components = eigenvectors
Explained varianceλiλj\frac{\lambda_i}{\sum \lambda_j}Proportion of variance captured
ProjectionXreduced=XWkX_{reduced} = X \cdot W_kDot product with top k eigenvectors
ReconstructionX^=XreducedWkT\hat{X} = X_{reduced} \cdot W_k^TInverse transform

⚠️ Common Pitfalls

Pitfall 1: PCA Without Standardization

The mistake: Applying PCA to raw data with different scales. Why: PCA maximizes variance — features with larger ranges have higher variance and dominate the first components. Fix: Standardize all features to mean=0, std=1 before PCA.

Pitfall 2: Misinterpreting t-SNE Distances

The mistake: Thinking that cluster distances in t-SNE have quantitative meaning. Why: t-SNE preserves local neighborhoods, not global distances. Cluster sizes and distances between clusters in the t-SNE plot are arbitrary. Fix: Use t-SNE for cluster discovery, not for measuring cluster separation.

Pitfall 3: Using PCA on Non-Linear Data

The mistake: Applying PCA to data with non-linear structure (e.g., Swiss roll, concentric circles). Why: PCA can only find linear projections. Non-linear structure is folded over and lost. Fix: Use kernel PCA or t-SNE for non-linear data.

📝 Practice Questions

Q1: What does PCA maximize?
PCA maximizes the variance of projected data. The first principal component is the line that maximizes the variance of the projected points. Equivalently, it minimizes the reconstruction error (sum of squared distances from points to their projections). Q2: If 3 components explain 90% of variance, how many components should you keep?
Either keep 3 (enough for 90%) or keep however many reach your threshold (95% is common). For visualization, keep 2. For downstream ML, retain enough to preserve signal — often 90-99%. Q3: Why are PCA components orthogonal?
Because the covariance matrix is symmetric. Eigenvectors of a symmetric matrix are orthogonal. This ensures each component captures unique variance not explained by previous components. Q4: What is the perplexity parameter in t-SNE?
Perplexity controls the balance between local and global aspects. It's roughly the number of nearest neighbors considered. Common range: 5-50. Lower perplexity focuses on very local structure; higher perplexity considers more global structure. The method is robust to perplexity choice between 5-50. Q5: You apply PCA and get explained variance [0.4, 0.3, 0.2, 0.1]. How many components for 95%?
Cumulative: 0.4 + 0.3 + 0.2 = 0.9 (90%). Adding the 4th: 0.9 + 0.1 = 1.0 (100%). So 4 components reach 95%. Wait — 0.9 < 0.95, so we need 4 components to exceed 95%. Q6: Can PCA be used for anomaly detection?
Yes! Project data onto top k components, then reconstruct. If reconstruction error is high for a point, it's likely an anomaly — the normal structure (captured by PCA) doesn't explain it well. This is useful for detecting unusual patterns in manufacturing, network traffic, etc. Q7: Compare PCA and LDA (Linear Discriminant Analysis).
AspectPCALDA
SupervisionUnsupervisedSupervised (uses labels)
GoalMaximize varianceMaximize class separation
ComponentsUp to n featuresUp to C-1 (C = classes)
Best forCompressionClassification preprocessing
LDA finds projections that best separate known classes. Q8: Why can't t-SNE be used for out-of-sample extension?
t-SNE is a non-parametric method — it creates a new representation for the given data points but doesn't learn a function to map new points. To add new points, you'd need to re-run t-SNE on the full dataset including new points. Some variants (parametric t-SNE) address this. Q9: What happens if you use PCA with n_components = n_features?
You'd get all components that explain 100% of the variance. The transformed data would have the same dimensionality as the input but rotated to align with the principal components. No compression happens. This is useful for decorrelating features. Q10: Your t-SNE plot shows well-separated clusters but they don't correspond to any known labels. What might be happening?
t-SNE may be finding structure you haven't thought of — perhaps there's a natural (but unknown) grouping in the data. It could also be:
  1. Over-interpreting noise: t-SNE can create false clusters from random noise (especially with small perplexity)
  2. Batch effects: Data collected from different batches/sensors
  3. A continuous gradient: t-SNE can break a continuum into apparent clusters
Check by running t-SNE with different perplexities and random seeds. Q11: How does the reconstruction error relate to explained variance?
Reconstruction error = total variance - explained variance. If you keep k components, the reconstruction error equals the sum of the variances of the discarded (n-k) components. Lower reconstruction error = better data preservation. Q12: Is it valid to fit PCA on training data and transform test data?
Yes — and this is the correct approach:
  1. Fit PCA on training data only
  2. Use the same PCA transformation to transform test data
  3. Never fit PCA on the full dataset before splitting — this leaks information from test to training
python
pca = PCA(n_components=10)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)  # Use same transform

🔗 Cross-References

Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.