Mathematical Derivation: SVD Whitening Implementation
Published:
This document explains the SVD Whitening method in SVD.R. While mathematically equivalent to PCA whitening for Symmetric Positive Definite (SPD) matrices, this method is framed in SVD notation; in eegwhiten it shares the same eigensolver as PCA.R.
1. Core Concept
The Singular Value Decomposition (SVD) generalizes eigendecomposition. For a covariance matrix (which is symmetric), the Singular Values are identical to the Eigenvalues, and Left/Right Singular Vectors are identical to Eigenvectors.
2. Mathematical Formulation
Step 1: Decomposition
Mathematically, we want the SVD of the covariance matrix $\Sigma$:
\[\Sigma = U D V^\top\]Since $\Sigma$ is symmetric and positive definite:
- $U = V$ (Left and Right singular vectors are the same).
- $D$ contains positive singular values (identical to eigenvalues $\lambda$).
Because the two decompositions coincide, SVD.R does not call svd(). It obtains $U$ and $D$ from the package’s shared SPD eigensolver .eigen_spd(), the same one used by PCA.R:
- By default this is base R’s
eigen(Sigma, symmetric = TRUE). - When only the leading
n_compcomponents are requested (fewer thanncol(Sigma)) and the RSpectra package is available, it switches to the iterativeRSpectra::eigs_sym()(selectable viaeig_method). - The singular values are returned in decreasing order, and the decomposition is truncated to the first
n_compcomponents if requested.
Finally, the sign of each singular vector is fixed so that results are reproducible across runs: its largest-magnitude entry is made positive, or it is aligned with sign_ref when one is supplied.
R Code Correspondence:
dec <- .eigen_spd(Sigma, k = k, method = eig_method, fast = fast, precomp = precomp)
U <- dec$vectors # singular vectors (= eigenvectors), one column per component
D <- dec$values # singular values (= eigenvalues), decreasing
if (any(D <= 0)) stop("Sigma must be positive-definite.")
U <- .fix_component_sign(U, sign_ref = sign_ref)
Step 2: Constructing the Whitening Matrix
With $U$ and $D$ in hand, the whitening matrix takes the same form as in PCA whitening:
\[W_{\text{SVD}} = D^{-1/2} U^\top\]so that $Z = X W^\top$ satisfies $\text{Cov}(Z) = D^{-1/2} U^\top \Sigma \, U D^{-1/2} = D^{-1/2} D \, D^{-1/2} = I$.
R Code Correspondence:
# W = D^-1/2 * U^T
W <- sweep(t(U), 1L, 1 / sqrt(D), "*")
