Module 1b: Statistical Linear Algebra and Numerical Methods
Advanced Mathematical Foundations for Computational Astrophysics | ASTR 596
Quick Navigation Guide¶
📚 Choose Your Learning Path¶
Starting Project 4? Read sections marked 🔴
Preparing for Projects 4-5? Read 🔴 and 🟡
Everything in Fast Track, plus:
Want mastery? Read all sections including 🟢
Complete module with:
Advanced decompositions
Numerical implementations
ML connections
🎯 Navigation by Project Needs¶
Quick Jump to What You Need by Project
For Project 4 (MCMC):
Section 1.3: Covariance Matrices - Proposal distributions
Section 1.4: Multivariate Gaussian - Sampling
Section 3: Numerical Reality - Stability
For Project 5 (Gaussian Processes):
Section 5: Positive Definite Matrices - Kernel matrices
Section 5.5: Cholesky Decomposition - GP implementation
Section 6.2: Schur Complement - Efficient updates
For Final Project (Neural Networks):
Section 6: Advanced Topics - Matrix norms, Jacobians
Section 8: Bridge to ML - Connecting everything
Section 8.5: Matrix Calculus - Backpropagation
Learning Objectives¶
📅 When to Read This Module
Before Project 4: Read sections marked 🔴 (3-4 hours)
During Projects 4-5: Deep dive into 🟡 sections
For Final Project: Review Section 8 connections
Reference: Return when debugging numerical issues
Prerequisites: Complete Module 0a or be comfortable with vectors, matrices, and eigenvalues.
By the end of this module, you will be able to:
Determine whether a matrix is positive definite using multiple methods 🔴
Construct and interpret covariance matrices from data 🔴
Apply Cholesky decomposition for sampling and solving 🟡
Debug numerical failures in statistical computations 🔴
Connect linear algebra to MCMC, Gaussian Processes, and neural networks 🟡
Implement robust algorithms that handle finite precision 🟢
Prerequisites from Module 0a¶
📚 Required Knowledge from Module 0a
Priority: 🔴 Essential - Review if needed
Before starting this module, ensure you understand:
Matrix multiplication and transposition
Eigenvalues and eigenvectors
Symmetric matrices and their properties
Matrix determinants and rank
Basic floating-point arithmetic concepts
If unfamiliar, review Module 0a first. This module builds on numerical foundations from Module 0a, focusing on advanced topics specific to statistical methods and machine learning.
Module Overview¶
Building on Module 0a’s foundations, this module explores how linear algebra enables statistical computation and machine learning. We cover positive definite matrices that ensure physical validity (Project 4), covariance structures that encode correlations (Project 5), and advanced numerical methods that keep statistical computations stable despite finite precision (all projects). The module culminates by showing how these concepts unite classical physics with modern machine learning (Final Project).
Part 1: Positive Definite Matrices and Statistical Foundations¶
Priority: 🟡 Important - Essential for Projects 4-5
1.1 Quadratic Forms and Energy {#part-5-positive-definite}¶
A quadratic form is:
These appear as energy expressions throughout physics:
| Type | Formula | Physical Meaning |
|---|---|---|
| Kinetic Energy | M is mass matrix | |
| Potential Energy | K is stiffness matrix | |
| Statistical Distance | Mahalanobis distance |
Physical Example: The kinetic energy of a rotating rigid body
where is angular velocity and is the moment of inertia tensor. This quadratic form is always positive (energy can’t be negative), making positive definite. The eigenvectors of are the principal axes - spin around these and the object doesn’t wobble!
1.2 Positive Definiteness: Ensuring Physical Reality {#positive-definiteness}¶
A symmetric matrix is positive definite if its quadratic form is always positive. This property ensures physical validity—energies are positive, distances are non-negative, and covariance matrices represent valid uncertainties.
Four Equivalent Tests for Positive Definiteness:
✅ All eigenvalues > 0
✅ All leading principal minors > 0
✅ Has Cholesky decomposition (requires strict positive definiteness)
✅ Can write as for some invertible matrix
Quick check: Positive definite matrices always have positive diagonal elements. Proof: For standard basis vector , we have .
Important Distinction:
Positive definite (all eigenvalues > 0): Standard Cholesky works
Positive semi-definite (eigenvalues ≥ 0): May have rank deficiency (rank < dimension), requiring modified Cholesky or eigendecomposition
Why it matters: Zero eigenvalues mean the matrix maps some directions to zero—information is lost
1.3 Covariance Matrices: The Bridge to Statistics {#covariance-matrices}¶
Priority: 🟡 Important - Foundation for Projects 4-5
Before diving into matrices, let’s understand what covariance actually tells us:
Intuitive Understanding:
Positive covariance: Variables tend to increase together (mass and luminosity in stars)
Negative covariance: One increases as the other decreases (stellar temperature and radius for giants)
Zero covariance: No linear relationship (doesn’t mean independent!)
Mathematical Definition:
This measures the average product of deviations from the mean. When both variables are above (or below) their means together, the products are positive, giving positive covariance.
Relationship to Correlation:
Correlation is just normalized covariance! It ranges from -1 to +1, making it easier to interpret than raw covariance.
The Covariance Matrix:
For multiple variables , we organize all pairwise covariances into a matrix:
Structure and Properties:
Diagonal elements: (variances are “self-covariance”)
Off-diagonal elements: (covariances between different variables)
Always symmetric: (order doesn’t matter)
Always positive semi-definite: All eigenvalues ≥ 0 (why? see below)
Why Positive Semi-Definite?
For any linear combination of variables :
Variance can’t be negative! This forces to be positive semi-definite. If it has negative eigenvalues, you could construct a linear combination with negative variance—physically impossible!
1.4 The Multivariate Gaussian Distribution {#multivariate-gaussian}¶
Priority: 🟡 Important - Core of Projects 4-5
The multivariate Gaussian extends the familiar bell curve to multiple dimensions. In 1D, you know the Gaussian as the bell-shaped curve. In higher dimensions, it becomes an ellipsoidal cloud of probability.
The Formula Decoded:
Let’s understand each piece intuitively:
The Exponent:
This is the Mahalanobis distance squared
In 1D with variance : reduces to
Measures “how many standard deviations away” but accounts for correlations
If variables are correlated, being far in one direction might be “cheaper” than another
The Normalization:
Ensures total probability integrates to 1
is the determinant—the “volume” of the uncertainty ellipsoid
Larger determinant = more spread out = lower peak height (volume conserved)
Geometric Picture:
Mean : Center of the probability cloud
Covariance : Shape and orientation of the ellipsoid
Eigenvalues: Lengths of ellipsoid axes
Eigenvectors: Directions of axes
Contours of constant probability: Ellipsoids defined by
1.5 Cholesky Decomposition: The Matrix Square Root¶
Priority: 🟡 Important - Essential for Project 5
Every positive definite matrix can be factored as:
where is lower triangular with positive diagonal entries.
Uniqueness Property: The Cholesky decomposition is unique — for any positive definite matrix , there exists exactly one lower triangular matrix with positive diagonal entries such that .
This uniqueness is crucial for numerical methods: no matter which algorithm you use (whether the classical Cholesky-Banachiewicz or the Cholesky-Crout variant), you’ll always get the same matrix (up to numerical precision). This deterministic property makes Cholesky decomposition ideal for reproducible scientific computing.
Why uniqueness matters: When you use Cholesky in your MCMC proposals (Project 4) or GP implementations (Project 5), you’re guaranteed consistent results across different machines and libraries. This isn’t true for eigendecomposition, where eigenvectors can differ by sign or be arbitrarily chosen when eigenvalues are repeated.
Intuitive Understanding: Think of Cholesky as finding the “square root” of a matrix
Just as , we have
transforms uncorrelated unit variance variables into correlated variables with covariance
Why Lower Triangular? The triangular structure means each variable depends only on previous ones:
Variable 1: Independent
Variable 2: Depends on variable 1
Variable 3: Depends on variables 1 and 2
And so on...
This sequential dependency structure makes computation efficient!
Two Key Applications:
1. Solving Linear Systems (faster than computing inverse):
# Problem: Solve Ax = b where A is positive definite
# Slow way: x = inv(A) @ b (NEVER DO THIS!)
# - Computing inverse: O(n³) operations
# - Numerically unstable
# - Loses sparsity structure
# Fast way using Cholesky:
L = np.linalg.cholesky(A) # A = LL^T
# Now Ax = b becomes LL^T x = b
# Step 1: Solve Ly = b (forward substitution)
y = np.linalg.solve(L, b)
# Step 2: Solve L^T x = y (back substitution)
x = np.linalg.solve(L.T, y)
# Why faster? Triangular systems solve in O(n²) not O(n³)!2. Generating Correlated Random Variables (Projects 4-5):
# Generate samples from N(mu, Sigma)
# The magic: If z ~ N(0, I), then Lz ~ N(0, LL^T) = N(0, Sigma)
L = np.linalg.cholesky(Sigma)
z = np.random.randn(n) # Standard normal (uncorrelated)
x = mu + L @ z # Has mean mu, covariance Sigma
# Why does this work?
# - z has covariance I (independent unit variance)
# - Lz has covariance L·I·L^T = LL^T = Sigma
# - Adding mu shifts the mean without changing covarianceProgressive Problems: Positive Definiteness¶
Part 2: Advanced Topics for Your Projects¶
Priority: 🟢 Enrichment - Read as needed for specific projects
📅 When You’ll Use This
These advanced topics appear in later projects or when optimizing code. Read as needed rather than all at once. Revisit these sections after completing related projects — they’ll make more sense with practical experience.
2.1 Singular Value Decomposition - The Swiss Army Knife {#svd-swiss-army}¶
Every matrix has a singular value decomposition:
where:
: Left singular vectors (orthonormal output directions)
: Diagonal matrix of singular values (stretching factors)
: Right singular vectors (orthonormal input directions)
SVD for Non-Square Matrices: For an matrix :
is (square, orthogonal)
is (rectangular!)
is (square, orthogonal)
Only singular values exist; the rest of is padded with zeros. This is crucial for understanding rank and dimensionality reduction.
Geometric Intuition: Any matrix transformation can be broken into three steps:
Rotate (by ): Align input to principal axes
Stretch (by ): Scale along each axis by σᵢ
Rotate (by ): Align to output space
This means ANY linear transformation—no matter how complex—is just rotate-stretch-rotate! This decomposition is unique (up to sign ambiguities) and always exists.
Understanding Rank Through SVD: The rank of a matrix equals the number of non-zero singular values. This tells you the true dimensionality:
Full rank: All , no information lost
Rank deficient: Some , transformation loses dimensions
Numerical rank: Count tolerance (e.g., 10⁻¹⁰) for finite precision
The Pseudoinverse and Least Squares:
The pseudoinverse where inverts non-zero singular values:
For overdetermined systems (more equations than unknowns): Gives least-squares solution
For underdetermined systems (more unknowns than equations): Gives minimum-norm solution
Robust via truncation: Ignore singular values < threshold
# Computing pseudoinverse via SVD
U, s, Vt = np.linalg.svd(A, full_matrices=False)
# Threshold small singular values (regularization)
threshold = 1e-10 * s.max()
s_inv = np.where(s > threshold, 1/s, 0)
# Construct pseudoinverse
A_pseudo = Vt.T @ np.diag(s_inv) @ U.T
# Now x = A_pseudo @ b gives:
# - Least-squares solution if overdetermined
# - Minimum-norm solution if underdeterminedWhy SVD Beats Eigendecomposition:
| Property | Eigendecomposition | SVD |
|---|---|---|
| Works for | Square matrices only | ANY matrix shape |
| Requires | Diagonalizable | Always works |
| Vectors | May be complex | Always real for real matrices |
| Values | Can be negative/complex | Always non-negative real |
| Numerical stability | Can be unstable | Very stable algorithms |
The Deep Connection: For any matrix :
has eigenvalues and eigenvectors = columns of
has eigenvalues and eigenvectors = columns of
This is why SVD always exists—symmetric matrices always have eigendecompositions!
2.2 Block Matrices and the Schur Complement¶
Large systems often have natural block structure:
Physical Motivation: Different parts of your system interact differently.
Concrete Example: Triple Star System Consider a close binary with a distant third star: $$\begin{pmatrix} F_{11} & F_{12} & F_{13} \ F_{21} & F_{22} & F_{23} \ F_{31} & F_{32} & F_{33} \end{pmatrix} =
The 2×2 upper-left block represents strong binary interactions, while off-diagonal blocks show weak coupling to the distant star.
The Schur Complement in Action:
Let’s solve
Instead of solving the full system, we can eliminate :
From bottom equation:
Substitute into top:
Rearrange:
The matrix is the Schur complement—it’s the “effective ” after accounting for ’s influence through .
Physical Intuition: Think of the Schur complement as “marginalizing out” variables. It’s like projecting 3D motion onto 2D while accounting for the 3rd dimension’s influence. When you eliminate variables, their effect doesn’t disappear—it gets encoded in the effective interactions between remaining variables.
Simple 2×2 Example:
Schur complement of :
This 2.5 is the “effective resistance” in the first variable after the second adjusts optimally.
Why It Matters for Project 5 (GPs): When you add a new observation to a Gaussian Process:
Old observations = block
Covariance with new point = blocks
New point variance = block
Prediction uses the Schur complement to efficiently update without re-inverting everything!
2.3 The Jacobian Matrix: Local Linear Approximation {#jacobian-matrix}¶
For vector function :
Intuitive Understanding: Near any point, nonlinear functions look linear. The Jacobian is that linear approximation:
Concrete 2D Example: For the transformation (polar to Cartesian):
The determinant tells you area scaling—this is why polar area elements are !
In Project 2 (N-body Stability): Near an equilibrium configuration , perturbations evolve as:
The eigenvalues of determine the fate:
All Re(λ) < 0: Stable (perturbations decay)
Any Re(λ) > 0: Unstable (perturbations grow)
Re(λ) = 0, Im(λ) ≠ 0: Neutral oscillations
Example: For a star orbiting at Lagrange point L4:
Eigenvalues have small negative real parts → weakly stable
Large imaginary parts → oscillates if perturbed
This is why Trojan asteroids librate around L4/L5!
2.4 Matrix Exponentials: Solving Linear Evolution {#matrix-exponentials}¶
The matrix exponential solves any linear ODE system:
Three Ways to Understand :
1. Series Definition (like scalar exponential):
2. Through Eigenvalues (if is diagonalizable): If where is diagonal with eigenvalues:
3. Physical Interpretation: is the propagator—it evolves the system from time 0 to time .
Practical Computation:
# Never use the series directly—it's inefficient and can be inaccurate
# Instead, use specialized algorithms:
import scipy.linalg as la
A = np.array([[0, 1], [-1, -0.1]]) # Damped oscillator
t = 5.0
# Method 1: Direct computation (best for dense matrices)
expAt = la.expm(A * t)
# Method 2: Via eigendecomposition (good for understanding)
eigvals, eigvecs = la.eig(A)
D = np.diag(np.exp(eigvals * t))
expAt_eig = eigvecs @ D @ la.inv(eigvecs)
# Method 3: For solving ODEs, use ODE solvers instead!
# They're more efficient than computing e^{At} explicitlyExample: Damped Harmonic Oscillator: For , rewrite as first-order system:
The eigenvalues determine behavior:
Underdamped (): Complex λ → oscillatory decay
Critically damped (): Repeated real λ → fastest decay
Overdamped (): Two real λ → slow decay
2.5 Matrix Norms: How Big is a Matrix?¶
Priority: 🟢 Enrichment - Crucial for understanding stability and convergence
Matrix norms measure “size” but different norms capture different aspects:
Frobenius Norm (total “energy”):
Like treating matrix as a long vector
All elements contribute equally
Easy to compute but ignores structure
Spectral Norm (worst-case amplification):
Maximum stretch factor for any unit vector
Equals largest singular value
Determines stability and convergence
Why Spectral Norm Matters:
Stability: System is stable iff
Error amplification: Input error → output error ≤
Condition number:
Convergence rate: Iterations converge like
Example: Why Deep Networks Are Hard to Train: Consider a 10-layer network where each layer multiplies by matrix :
If : Gradients grow as
If : Gradients shrink as
Need for stable training!
This is why techniques like batch normalization and careful initialization are crucial.
2.6: Numerical Implementation Examples¶
🌟 The More You Know: How Cholesky Decomposition Powers GPS
Priority: 🟢 Enrichment
Every GPS satellite continuously solves navigation equations using Kalman filters, which require Cholesky decomposition thousands of times per day. The Kalman filter updates position estimates by combining predictions with measurements, requiring the factorization of covariance matrices at each step.
André-Louis Cholesky (1875-1918) developed his decomposition method while working on geodesy and map surveying for the French military. Tragically, he died in World War I just months before the war ended, never seeing his method’s full impact. His work, published posthumously in 1924, remained relatively obscure until the computer age.
The connection to GPS is profound: the Extended Kalman Filter (EKF) used in GPS receivers must update the covariance matrix P at each timestep:
where the Kalman gain requires solving systems involving the innovation covariance . Cholesky decomposition makes this numerically stable—without it, rounding errors would accumulate and your GPS would drift by kilometers within hours!
Today, your smartphone performs Cholesky decomposition hundreds of times per second to fuse GPS, accelerometer, and gyroscope data, giving you meter-level positioning accuracy. Cholesky’s century-old algorithm guides you home every day.
Sources: Benoit, C. (1924). “Note sur une méthode de résolution des équations normales provenant de l’application de la méthode des moindres carrés à un système d’équations linéaires en nombre inférieur à celui des inconnues.” Bulletin Géodésique, 2, 67-77; Grewal, M. S., & Andrews, A. P. (2014). “Kalman Filtering: Theory and Practice Using MATLAB” (4th ed.). Wiley.
🌟 The More You Know: How SVD Revolutionized Netflix
Priority: 🟢 Enrichment
The Netflix Prize (2006-2009) offered $1 million to anyone who could improve their recommendation system by 10%. The winning solution? Sophisticated use of SVD to compress millions of user-movie ratings into meaningful patterns.
The problem: Netflix had a sparse matrix of 100 million ratings from 480,000 users rating 17,770 movies—a matrix that would require 8.5 billion entries if complete, but was 98.8% empty! Direct storage and computation were impossible.
SVD to the rescue: By decomposing the ratings matrix and keeping only the top k singular values (typically 20-40), teams could:
Compress 8.5 billion potential entries into ~20 million parameters
Identify latent factors (genres, moods, themes) automatically
Predict missing ratings as
The “FunkSVD” algorithm by Simon Funk used gradient descent to compute SVD on sparse data without filling in missing values—a breakthrough that influenced all subsequent solutions. The final winning team “BellKor’s Pragmatic Chaos” used an ensemble including multiple SVD variants.
This same SVD approach now powers recommendations at YouTube (1 billion users × millions of videos), Spotify (500 million users × 100 million songs), and every major content platform. When Netflix suggests your next binge-watch, it’s using the same linear algebra you’re learning now!
Sources: Bennett, J., & Lanning, S. (2007). “The Netflix Prize.” Proceedings of KDD Cup and Workshop; Koren, Y., Bell, R., & Volinsky, C. (2009). “Matrix Factorization Techniques for Recommender Systems.” Computer, 42(8), 30-37.
These advanced topics aren’t just mathematical curiosities—they’re the computational workhorses of modern astrophysics:
SVD reveals hidden structure and enables massive data compression (galaxy spectra, CMB analysis)
Block matrices exploit natural hierarchies to solve huge systems efficiently
Jacobians determine stability of everything from orbits to numerical methods
Matrix exponentials solve linear evolution exactly—the foundation for understanding nonlinear dynamics
Matrix norms quantify stability, convergence, and error propagation
Power method underlies iterative algorithms from PageRank to finding vibrational modes
The beauty is that these tools interconnect: SVD uses eigenvalues, matrix exponentials need eigendecomposition, stability analysis uses Jacobians and norms together. Master these connections and you’ll see how a small set of linear algebra concepts powers all of computational astrophysics.
As you progress through projects, return to these sections—concepts that seem abstract now will crystallize when you need them to debug unstable orbits or understand why your neural network won’t converge.
Part 3: Numerical Reality - When Mathematics Meets Silicon¶
Priority: 🔴 Essential - Critical for debugging all projects
Needed from: Day 1 of coding Most critical for: Debugging numerical errors Returns in: Every project when things go wrong
Read this section early and refer back when debugging.
Pure mathematics assumes infinite precision, but computers work with finite bits. This section reveals the harsh realities of floating-point arithmetic and teaches you to recognize and fix numerical disasters before they ruin your simulations. These aren’t edge cases—you WILL encounter these issues in your projects.
7.1 Condition Numbers Revisited: Statistical Context {#condition-numbers}¶
Building on Module 0a’s introduction to condition numbers, let’s explore their specific implications for statistical computations:
Condition Numbers in Statistical Methods:
For covariance matrices, the condition number has special meaning:
This ratio tells you:
Near 1: Variables have similar scales and low correlation
Large: Either variables have vastly different scales OR near-perfect correlation
Infinite: Perfect correlation (singular covariance)
MCMC Implications (Project 4):
# Poorly conditioned proposal covariance slows convergence
Sigma_bad = np.array([[1, 0.999], [0.999, 1]]) # κ ≈ 2000
# MCMC needs ~κ steps to explore the distribution
# Well-conditioned after reparameterization
L = np.linalg.cholesky(Sigma_bad)
# Sample in transformed space where κ = 1, then transform backGP Implications (Project 5):
# Kernel matrices become ill-conditioned when:
# 1. Data points are very close (duplicate measurements)
# 2. Length scale is too small (overfitting)
# 3. Noise term is too small (numerical instability)
# Check your GP's condition number:
kappa = np.linalg.cond(K)
if kappa > 1e12:
print("Warning: GP may give nonsense predictions!")
# Solutions:
# - Increase noise term σ²
# - Remove duplicate points
# - Adjust length scale7.2 When Statistical Computations Fail¶
Understanding failure modes specific to statistical methods helps you recognize and fix problems:
Covariance Matrix Not Positive Semi-Definite:
# Computing sample covariance with insufficient data
n_samples = 3
n_features = 5 # More features than samples!
X = np.random.randn(n_samples, n_features)
Sigma = np.cov(X.T) # Shape: (5, 5)
# This is rank-deficient: rank ≤ min(n_samples-1, n_features) = 2
print(f"Rank: {np.linalg.matrix_rank(Sigma)}") # 2, not 5!
# Cholesky will fail:
try:
L = np.linalg.cholesky(Sigma)
except np.linalg.LinAlgError:
print("Covariance is singular!")
# Fix: Regularization (add prior belief about variance)
Sigma_reg = Sigma + 0.01 * np.eye(n_features)
L = np.linalg.cholesky(Sigma_reg) # Now worksNumerical Underflow in Likelihoods:
# Computing likelihood of many data points
log_likelihoods = []
for x in data:
# BAD: Probability underflows to zero
p = multivariate_normal.pdf(x, mu, Sigma)
# GOOD: Work in log space
log_p = multivariate_normal.logpdf(x, mu, Sigma)
log_likelihoods.append(log_p)
# Sum log-likelihoods instead of multiplying probabilities
total_log_likelihood = np.sum(log_likelihoods)Cholesky Decomposition Failures:
def safe_cholesky(A, max_tries=5):
"""
Robust Cholesky with automatic regularization.
"""
jitter = 1e-6
for i in range(max_tries):
try:
L = np.linalg.cholesky(A + jitter * np.eye(len(A)))
return L
except np.linalg.LinAlgError:
if i == max_tries - 1:
# Last resort: eigenvalue thresholding
eigvals, eigvecs = np.linalg.eigh(A)
eigvals = np.maximum(eigvals, jitter)
A_fixed = eigvecs @ np.diag(eigvals) @ eigvecs.T
return np.linalg.cholesky(A_fixed)
else:
jitter *= 10 # Increase regularization
return None7.3 Statistical-Specific Numerical Guidelines¶
Follow this systematic workflow when encountering Cholesky decomposition failures:
def debug_cholesky_failure(A):
"""Systematic debugging when np.linalg.cholesky(A) fails."""
print("=== Cholesky Debugging Workflow ===")
# Step 1: Check symmetry
asymmetry = np.max(np.abs(A - A.T))
print(f"1. Symmetry check: max|A - A^T| = {asymmetry:.2e}")
if asymmetry > 1e-10:
print(" FIX: A = (A + A.T) / 2")
A = (A + A.T) / 2
# Step 2: Check diagonal elements
min_diag = np.min(np.diag(A))
print(f"2. Diagonal check: min(diag(A)) = {min_diag:.2e}")
if min_diag <= 0:
print(" ERROR: Non-positive diagonal elements!")
return None
# Step 3: Check eigenvalues
eigvals = np.linalg.eigvalsh(A)
print(f"3. Eigenvalue range: [{eigvals.min():.2e}, {eigvals.max():.2e}]")
# Step 4: Check condition number
cond = eigvals.max() / max(eigvals.min(), 1e-15)
print(f"4. Condition number: {cond:.2e}")
# Step 5: Apply fixes based on diagnosis
if eigvals.min() < -1e-10:
print(" FIX: Matrix is not PSD. Using eigenvalue thresholding...")
eigvecs = np.linalg.eigh(A)[1]
eigvals = np.maximum(eigvals, 1e-10)
A = eigvecs @ np.diag(eigvals) @ eigvecs.T
elif eigvals.min() < 1e-10:
print(" FIX: Near-singular. Adding regularization...")
A = A + 1e-6 * np.eye(len(A))
# Step 6: Retry Cholesky
try:
L = np.linalg.cholesky(A)
print("✓ Cholesky successful after fixes!")
return L
except np.linalg.LinAlgError:
print("✗ Still failing. Consider stronger regularization or SVD approach.")
return NoneQuick Decision Tree:
Symmetry error? → Force symmetry
Negative diagonal? → Data/math error, check upstream
Negative eigenvalues? → Eigenvalue thresholding
Tiny eigenvalues? → Add regularization
Large condition number? → Standardize data or reformulate
Always Work in Log Space for Probabilities:
# BAD: Product of probabilities
prob = 1.0
for p in probabilities:
prob *= p # Underflows to 0
# GOOD: Sum of log probabilities
log_prob = 0.0
for p in probabilities:
log_prob += np.log(p)Use Stable Parameterizations:
# BAD: Parameterize by standard deviation
sigma = optimizer.optimize(sigma_init)
# GOOD: Parameterize by log(sigma)
log_sigma = optimizer.optimize(np.log(sigma_init))
sigma = np.exp(log_sigma) # Always positive!Standardize Your Data:
# BAD: Raw features with different scales
X = data # columns might range from 0.001 to 1000000
# GOOD: Standardized features
X = (data - data.mean(axis=0)) / data.std(axis=0)
# Now all features have mean=0, std=1
# Covariance matrix will be well-conditionedMonitor Numerical Health:
def check_matrix_health(A, name="Matrix"):
"""
Diagnostic function for matrix numerical health.
"""
print(f"\n{name} Health Check:")
print(f" Shape: {A.shape}")
print(f" Rank: {np.linalg.matrix_rank(A)}")
print(f" Condition number: {np.linalg.cond(A):.2e}")
eigvals = np.linalg.eigvalsh(A)
print(f" Eigenvalue range: [{eigvals.min():.2e}, {eigvals.max():.2e}]")
if eigvals.min() < 0:
print(f" ⚠️ WARNING: Negative eigenvalues detected!")
if np.linalg.cond(A) > 1e10:
print(f" ⚠️ WARNING: Poorly conditioned!")Library Choice Guidance:
| Library | When to Use | Why |
|---|---|---|
numpy.linalg | Quick prototyping, small matrices | Convenient, always available |
scipy.linalg | Production code, edge cases | More robust algorithms, better error handling |
scipy.sparse | Sparse matrices (>90% zeros) | Memory efficient, specialized algorithms |
sklearn | Machine learning pipelines | Integrated preprocessing, cross-validation |
JAX | Differentiable operations | Autodiff, JIT compilation, GPU acceleration |
Performance Profiling Notes:
Cholesky decomposition has O(n³/3) complexity but with excellent cache performance. Here’s why it beats other factorizations:
| Operation | Complexity | Cache Performance | When to Use |
|---|---|---|---|
| Cholesky | O(n³/3) | Excellent | Positive definite systems |
| LU | O(2n³/3) | Good | General square systems |
| QR | O(2n³) | Fair | Least squares, rank-deficient |
| Eigendecomposition | O(10n³) | Poor | Need all eigenvalues/vectors |
| SVD | O(11n³) | Poor | Rank analysis, pseudoinverse |
The factor of 3 difference between Cholesky and LU matters: for n=1000, Cholesky needs ~167 million operations vs 667 million for LU!
The concepts in this module directly extend to cutting-edge research:
Gaussian Processes → Neural Tangent Kernels: Recent work shows that infinitely wide neural networks behave exactly like Gaussian Processes with specific kernels. Your GP understanding directly transfers to understanding deep learning theory!
Covariance Matrices → Attention Mechanisms: The attention matrices in transformers (like GPT) are essentially learned covariance structures that capture which tokens should “pay attention” to each other.
SVD → Model Compression: Modern large language models use SVD-based techniques to compress billion-parameter models to run on phones while maintaining performance.
Matrix Exponentials → Neural ODEs: Instead of discrete layers, Neural ODEs use continuous transformations via matrix exponentials, enabling memory-efficient deep networks.
These aren’t distant connections—they’re active research areas where your linear algebra foundation enables breakthrough science!
On June 4, 1996, the European Space Agency’s Ariane 5 rocket exploded 39 seconds after launch, destroying $370 million of satellites. The cause? A floating-point overflow in the navigation software.
The horizontal velocity value (a 64-bit float) was converted to a 16-bit signed integer. When the velocity exceeded 32,767 (the maximum for 16-bit signed integers), the conversion caused an overflow, leading to a hardware exception. The backup system had the same bug, so both failed simultaneously.
Lessons for your projects:
Check value ranges: Before type conversions, verify values fit in the target type
Test edge cases: The Ariane 4 software worked fine—Ariane 5’s faster acceleration triggered the bug
Don’t assume backup = different: Redundant systems with identical code have identical bugs
Understand your precision limits: Know when float32 vs float64 matters
In your projects:
Project 2: Check for position overflows in long integrations
Project 4: Monitor log-probability underflows in MCMC
Project 5: Watch for precision loss in badly-scaled kernels
Source: Lions, J. L. (1996). “Ariane 5 Flight 501 Failure: Report by the Inquiry Board.” European Space Agency.
Part 4: Bridge to Machine Learning¶
Priority: 🟡 Important - Helps see the big picture
Read this section when transitioning between course phases to understand connections. Return to it after Projects 1-3 to see how classical methods connect to modern ML.
8.1 From Classical to Statistical to Learning¶
Linear algebra provides the mathematical continuity across your entire journey. Watch how the same mathematical objects evolve in meaning as you progress through different computational paradigms:
The Evolution of Mathematical Objects:
| Mathematical Object | Classical Physics (Projects 1-3) | Statistical Methods (Projects 4-5) | Machine Learning (Final Project) |
|---|---|---|---|
| Vectors | Positions, velocities, forces | Parameter samples, data points | Feature vectors, gradients |
| Matrices | Transformations, rotations | Covariance, kernels | Weight matrices, Jacobians |
| Eigenvalues | Stability, oscillation modes | Convergence rates, principal components | Learning rates, network dynamics |
| Dot products | Work, projections | Correlations, similarities | Attention scores, kernels |
| Norms | Distances, magnitudes | Errors, uncertainties | Loss functions, regularization |
| Decompositions | Solving dynamics | Statistical inference | Network compression, analysis |
This isn’t coincidence—it’s the deep unity of mathematics. The same linear algebra that predicts planetary orbits also powers Google’s search algorithm and ChatGPT’s language understanding.
8.2 Matrix Calculus for Neural Networks {#matrix-calculus-nn}¶
Priority: 🟡 Important for Final Project
Your final project requires understanding how gradients flow through matrix operations. Here’s the essential matrix calculus:
Basic Matrix Derivatives:
For scalar function of matrix :
Key Results You’ll Need:
Linear layer:
Quadratic form:
Frobenius norm:
Chain Rule for Matrices:
For composition :
This is what happens during backpropagation—gradients flow backward through the network via chain rule!
Example: Simple Two-Layer Network:
# Forward pass:
# Layer 1: z₁ = W₁x + b₁
# Activation: a₁ = relu(z₁)
# Layer 2: z₂ = W₂a₁ + b₂
# Loss: L = ||z₂ - y||²
# Backward pass (what JAX computes automatically):
# ∂L/∂z₂ = 2(z₂ - y)
# ∂L/∂W₂ = (∂L/∂z₂) @ a₁ᵀ
# ∂L/∂a₁ = W₂ᵀ @ (∂L/∂z₂)
# ∂L/∂z₁ = (∂L/∂a₁) ⊙ relu'(z₁) # Element-wise product
# ∂L/∂W₁ = (∂L/∂z₁) @ xᵀ
# The pattern: gradients with respect to weights = (upstream gradient) @ (input)ᵀ8.3 Connecting Everything: The Big Picture¶
The techniques in this module power every major simulation and discovery in modern astrophysics:
Your Learning Journey:
Classical (Projects 1-3): Deterministic systems, exact solutions
Statistical (Projects 4-5): Uncertainty quantification, probabilistic inference
Learning (Final Project): Pattern discovery, function approximation
The Mathematical Thread:
Same linear algebra throughout
Increasing complexity of applications
Growing appreciation for numerical stability
Deepening understanding of connections
Why This Matters: Every breakthrough in computational astrophysics builds on these foundations:
Gaia: 1 billion stars → massive covariance matrices
LIGO: Gravitational waves → matched filtering in high dimensions
JWST: Spectroscopy → dimensionality reduction via SVD
Vera Rubin: 20 TB/night → statistical methods at scale
Numerical Recipes Quick Reference¶
When Matrices Misbehave - Immediate Fixes:
# Force symmetry (when you know A should be symmetric)
A_sym = (A + A.T) / 2
# Add jitter for positive definiteness
A_stable = A + 1e-6 * np.eye(len(A))
# Robust Cholesky with automatic jitter
def safe_cholesky(A, initial_jitter=1e-6):
jitter = initial_jitter
max_tries = 5
for i in range(max_tries):
try:
L = np.linalg.cholesky(A + jitter * np.eye(len(A)))
return L
except np.linalg.LinAlgError:
jitter *= 10
# Last resort: eigenvalue thresholding
eigvals, eigvecs = np.linalg.eigh(A)
eigvals = np.maximum(eigvals, initial_jitter)
A_fixed = eigvecs @ np.diag(eigvals) @ eigvecs.T
return np.linalg.cholesky(A_fixed)
# Work in log space for probabilities
log_prob = multivariate_normal.logpdf(x, mu, Sigma) # Not .pdf()!
# Stable parameterization for optimization
log_sigma = optimizer.param # Optimize log
sigma = np.exp(log_sigma) # Always positive!
# Standardize data before any statistical analysis
X_std = (X - X.mean(axis=0)) / X.std(axis=0)
# Robust matrix inversion via SVD
def robust_inverse(A, threshold=1e-10):
U, s, Vt = np.linalg.svd(A)
s_inv = np.where(s > threshold * s.max(), 1/s, 0)
return Vt.T @ np.diag(s_inv) @ U.T
# Check before trusting
def is_positive_definite(A):
try:
np.linalg.cholesky(A)
return True
except np.linalg.LinAlgError:
return FalseEmergency Diagnostics:
def matrix_health_report(A):
"""Quick health check - run this when things break."""
print(f"Shape: {A.shape}")
print(f"Symmetric: {np.allclose(A, A.T)}")
print(f"Condition: {np.linalg.cond(A):.2e}")
if A.shape[0] == A.shape[1]: # Square matrix
eigvals = np.linalg.eigvalsh(A) if np.allclose(A, A.T) else np.linalg.eigvals(A)
print(f"Eigenvalues: [{np.min(eigvals):.2e}, {np.max(eigvals):.2e}]")
print(f"Positive definite: {np.all(eigvals > 0)}")Glossary of Terms¶
All terms introduced in this module, arranged alphabetically:
back substitution: Solving upper triangular systems from bottom to top, used in the second phase of solving systems via Cholesky decomposition
block matrix: Matrix partitioned into submatrices, often reflecting natural system structure (e.g., strong/weak interactions in multi-body systems)
Cholesky decomposition: Factorization of a positive definite matrix where is lower triangular with positive diagonal entries; geometrically finds the “square root” of a positive definite matrix
condition number: For statistical context: , ratio of largest to smallest singular value; measures how much errors amplify in statistical computations
covariance: Measure of how two variables change together; positive means they increase together, negative means one increases as the other decreases, zero means no linear relationship
covariance matrix: Matrix containing all pairwise covariances between random variables; ; encodes all linear relationships in your data
forward substitution: Solving lower triangular systems from top to bottom, used in the first phase of solving systems via Cholesky decomposition
Frobenius norm: Matrix norm defined as ; treats matrix like a vector and sums all squared elements
Jacobian: Matrix of all first-order partial derivatives ; represents the best linear approximation of a vector function at a point
Mahalanobis distance: Scale-invariant distance that accounts for correlations: ; measures “how many standard deviations away” in correlated space
matrix exponential: The operator that propagates linear systems forward in time; solution to is
multivariate Gaussian: Multi-dimensional generalization of the bell curve, defined by mean vector and covariance matrix ; probability density involves
positive definite: Property of a symmetric matrix where for all ; ensures energies are positive and covariances are valid
positive semi-definite: Property of a symmetric matrix where for all ; allows for zero eigenvalues (rank deficiency)
precision matrix: Inverse of the covariance matrix: ; encodes conditional independence structure (zero entries indicate conditional independence)
pseudoinverse: Generalized inverse obtained via SVD; gives least-squares solution for overdetermined systems and minimum-norm solution for underdetermined systems
quadratic form: Expression where is symmetric; represents energies, distances, and other positive quantities in physics
regularization: Adding small positive values (often to diagonal elements) to improve numerical stability or prevent singularities; balances stability with bias
Schur complement: The “effective” matrix after eliminating some variables: ; represents how eliminated variables influence remaining ones
singular values: Non-negative values from SVD; measure importance/variance explained by each component
spectral norm: Matrix norm defined as ; equals maximum amplification factor for any unit vector
SVD (Singular Value Decomposition): Universal matrix factorization that reveals the fundamental action of any matrix as rotate-stretch-rotate
Main Takeaways¶
This module bridged classical linear algebra with statistical methods and machine learning:
Positive definite matrices guarantee physical validity - they ensure energies are positive, distances are non-negative, and probability distributions are valid
Covariance matrices encode all linear relationships between random variables, with diagonal elements as variances and off-diagonal as covariances
Cholesky decomposition is the bridge between uncorrelated randomness and structured correlations - essential for sampling and solving
Numerical precision is finite - always check condition numbers, work in log space for probabilities, and add regularization when needed
Advanced decompositions reveal hidden structure - SVD for dimensionality reduction, Schur complement for efficient updates, Jacobian for stability analysis
Matrix calculus underlies neural networks - gradients flow through matrix operations via the chain rule during backpropagation
Statistical computations require special care - work in log space, use stable parameterizations, standardize data, monitor numerical health
The same mathematics spans all domains - eigenvalues determine both orbital stability and MCMC convergence rates
Master these concepts and you’re ready for the statistical challenges of Projects 4-6!
Essential NumPy/SciPy Reference for Module 0b¶
Priority: 🔴 Essential - Keep this open while coding Projects 4-6
Statistical Linear Algebra Functions
Task | Function | When to Use | Project |
|---|---|---|---|
Cholesky decomposition |
| Positive definite systems | P4-5 |
Check positive definite |
| Before Cholesky | P4-5 |
Sample covariance |
| Compute from data | P4 |
Multivariate normal |
| Sampling, likelihood | P4-5 |
Log probability |
| Avoid underflow | P4-5 |
Pseudoinverse |
| Rank-deficient systems | P5 |
SVD |
| Decomposition, PCA | All |
Matrix exponential |
| Time evolution | P2,5 |
Force symmetry |
| Fix rounding errors | P4-5 |
Add regularization |
| Improve conditioning | P4-5 |
Numerical Stability Patterns
Problem | Solution | Code Pattern |
|---|---|---|
Cholesky fails | Add jitter |
|
Negative eigenvalues | Threshold to zero |
|
Probability underflow | Work in log space | Use |
Ill-conditioned | Regularize | Add to diagonal |
Not symmetric | Force symmetry |
|
Different scales | Standardize |
|
Quick Reference Card¶
Positive Definiteness¶
Test: All eigenvalues > 0
Fix: Add jitter
A + 1e-6 * ICheck:
np.linalg.eigvalsh(A).min() > 0
Covariance Matrices¶
Diagonal: Variances
Off-diagonal: Covariances
Always symmetric and PSD
Correlation:
ρ = Σᵢⱼ/√(ΣᵢᵢΣⱼⱼ)
Multivariate Gaussian¶
PDF:
N(μ, Σ)Sample:
x = μ + L @ randn()whereL = cholesky(Σ)Log-likelihood: Use
logpdfto avoid underflow
Numerical Guidelines¶
Always check condition numbers
Work in log space for probabilities
Standardize data before analysis
Monitor eigenvalue ranges
Key Functions¶
np.linalg.cholesky() # Cholesky decomposition
np.linalg.eigvalsh() # Eigenvalues (symmetric)
np.linalg.cond() # Condition number
np.linalg.lstsq() # Least squares
scipy.linalg.expm() # Matrix exponentialWith these foundations, you’re equipped to tackle the statistical and machine learning challenges ahead!