FAU Erlangen-Nürnberg
Institute of Micro- and Nanostructure Research
notebooks/week03_pca_nmf_eels.ipynb. Build a 3-phase spectrum image, then compare PCA and NMF against the ground truth.By the end of this week you can:


X.shape before any analysis — a transposed matrix gives meaningless PCA.
U, s, Vt = np.linalg.svd(X, full_matrices=False) — then zero out s[k:].import numpy as np
# ✅ CORRECT full pipeline — copy this version
mean_spectrum = X.mean(axis=0) # (D,) mean of original data
X_centered = X - mean_spectrum # center before SVD
U, s, Vt = np.linalg.svd(X_centered, full_matrices=False) # core computation
K = 3 # chosen from scree plot
# Scores (chemical maps): how strongly each PC is expressed per pixel
scores = X_centered @ Vt[:K].T # shape (N, K)
# Eigenspectra (spectral shapes): rows of Vt[:K], shape (K, D)
eigenspectra = Vt[:K] # already unit-norm and orthogonal
# Reconstruct (denoise): restore mean to get back to original scale
X_denoised = scores @ eigenspectra + mean_spectrum # shape (N, D)


Synthetic Ti-L\(_{2,3}\) + O-K core-loss spectrum. (1) Power law fitted in a pre-edge window (log-log linear regression). (2) After subtraction the edges emerge. (3) A stack whose energy axis drifts by ±0.8 eV: its first principal component is simply the derivative \(dI/dE\) of the edge (img/make_figures.py).

img/make_figures.py).

sklearn.decomposition.NMF(beta_loss="kullback-leibler", solver="mu"); you write the updates yourself in notebook Part D.Top: ground-truth endmembers (TiO\(_2\)-like, FeO-like, Ni) and abundance maps. Middle: PCA with \(K=3\). The components are signed difference spectra, the maps have positive and negative lobes, and PC3 is pure noise (sum-to-one removes one dimension after centering). Bottom: NMF with \(K=3\) recovers phase-like spectra and non-negative maps, with small artefacts at the edge onsets (img/make_figures.py, same data as the notebook).


img/make_figures.py).A rare phase occupying 13 pixels (0.3 %) is invisible in the scree plot (elbow at \(k=2\)). The Poisson-normalised residual at \(K=2\) shows it as a spatially coherent hot spot, and only at \(K\approx8\) is it absorbed, together with six noise components (img/make_figures.py).
| Question | Method | Constraint | Unique? | Watch out for |
|---|---|---|---|---|
| How many things vary? Denoise | PCA / SVD (weighted) | orthogonal, variance-ordered | yes (± sign) | truncation bias, rare phases, needs weighting |
| Which phases, known references | NNLS / FCLS | \(\mathbf{a}\ge0\), \(\sum a=1\) | yes | missing endmember → biased fractions |
| Which phases, unknown spectra | NMF (Frobenius / KL) | \(\mathbf{W},\mathbf{H}\ge0\) | no | rotational ambiguity, init, choose \(K\) from PCA |
| + physical prior knowledge | MCR-ALS / physics-guided NMF | + closure, unimodality, known spectra | ≈ with enough constraints | constraints must be true |
| Discrete phases, no mixing | K-means / GMM (Week 9) | hard / soft labels | no (init) | mixed pixels at boundaries |
| Curved manifolds, shifting peaks | Autoencoders (Week 9) | learned non-linear | no | interpretability, validation |

notebooks/week03_pca_nmf_eels.ipynb, “PCA vs NMF on a synthetic spectrum image”.
Material for questions and self-study; not part of the 90-minute lecture path.



np.linalg.cond(X) — if \(> 10^6\), you have a serious problem.
©Philipp Pelz - FAU Erlangen-Nürnberg - Data Science for Electron Microscopy