---
id: wiki-2026-0508-singular-value-decomposition
title: Singular Value Decomposition (SVD)
category: 10_Wiki/Topics
status: verified
canonical_id: self
aliases: [SVD, Matrix Factorization]
duplicate_of: none
source_trust_level: A
confidence_score: 0.95
verification_status: applied
tags: [linear-algebra, matrix-factorization, dimensionality-reduction, machine-learning]
raw_sources: []
last_reinforced: 2026-05-10
github_commit: pending
tech_stack:
  language: Python
  framework: NumPy/SciPy
---

# Singular Value Decomposition (SVD)

## 매 한 줄
> **"매 matrix 의 universal factorization"**. Beltrami (1873) / Jordan (1874) 에서 origin — 매 modern ML/DL 의 foundational tool: PCA, recommendation, LLM weight compression (LoRA, 2026 vLLM/MLX 의 SVD-based pruning).

## 매 핵심

### 매 Decomposition
- `A = U Σ Vᵀ`
- `A` (m×n), `U` (m×m, orthogonal), `Σ` (m×n, diagonal, σ₁≥σ₂≥...≥0), `Vᵀ` (n×n, orthogonal).
- σᵢ = singular values (≥ 0). U columns = left singular vectors. V columns = right.

### 매 핵심 properties
- Always exists (any matrix, even non-square / singular).
- σᵢ² = eigenvalues of `AᵀA` (and `AAᵀ`).
- rank(A) = number of non-zero σᵢ.
- ||A||₂ = σ₁ (largest singular value).
- ||A||_F = √Σσᵢ² (Frobenius norm).

### 매 응용
1. PCA — top-k SVD of centered X.
2. Pseudoinverse `A⁺ = V Σ⁺ Uᵀ`.
3. Low-rank approximation (Eckart-Young theorem).
4. Recommender systems (Netflix, Funk SVD).
5. LoRA / weight compression (2026 LLM fine-tuning).
6. Image compression.

## 💻 패턴

### NumPy SVD
```python
import numpy as np

A = np.random.randn(100, 50)
U, s, Vt = np.linalg.svd(A, full_matrices=False)
# U: (100,50), s: (50,), Vt: (50,50)
# Reconstruct: A ≈ U @ np.diag(s) @ Vt
```

### Truncated SVD (low-rank approx)
```python
from sklearn.decomposition import TruncatedSVD

# Top-k components — Eckart-Young optimal rank-k approx
svd = TruncatedSVD(n_components=10)
X_reduced = svd.fit_transform(X)  # (n_samples, 10)
print(svd.explained_variance_ratio_.sum())
```

### PCA via SVD
```python
def pca_svd(X, k):
    X_centered = X - X.mean(axis=0)
    U, s, Vt = np.linalg.svd(X_centered, full_matrices=False)
    # Principal components = rows of Vt
    return X_centered @ Vt[:k].T  # project to k-dim
```

### Pseudoinverse
```python
def pinv_svd(A, rcond=1e-10):
    U, s, Vt = np.linalg.svd(A, full_matrices=False)
    s_inv = np.where(s > rcond * s.max(), 1/s, 0)
    return Vt.T @ np.diag(s_inv) @ U.T

# Solve least squares: x = A⁺ b
x = pinv_svd(A) @ b
```

### Image compression
```python
from PIL import Image
import numpy as np

img = np.array(Image.open("photo.jpg").convert("L"))
U, s, Vt = np.linalg.svd(img, full_matrices=False)
# Keep top-k singular values
k = 50
compressed = U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :]
# Storage: m*k + k + k*n vs m*n
```

### Randomized SVD (large matrices)
```python
from sklearn.utils.extmath import randomized_svd

# Halko et al. 2011 — O(mn log k) instead of O(mn²)
U, s, Vt = randomized_svd(X_huge, n_components=20, random_state=42)
```

### LoRA-style low-rank weight update (2026)
```python
import torch

# Original frozen weight W (d_out, d_in)
# Learn ΔW = B @ A where B (d_out, r), A (r, d_in), r << min(d_out, d_in)
class LoRALayer(torch.nn.Module):
    def __init__(self, d_in, d_out, rank=8):
        super().__init__()
        self.A = torch.nn.Parameter(torch.randn(rank, d_in) * 0.01)
        self.B = torch.nn.Parameter(torch.zeros(d_out, rank))

    def forward(self, x, W_frozen):
        return x @ W_frozen.T + x @ self.A.T @ self.B.T
```

### Eckart-Young error bound
```python
# Best rank-k approx error in Frobenius norm
U, s, Vt = np.linalg.svd(A, full_matrices=False)
k = 5
A_k = U[:, :k] @ np.diag(s[:k]) @ Vt[:k, :]
error_frob = np.sqrt(np.sum(s[k:]**2))
assert np.isclose(np.linalg.norm(A - A_k, 'fro'), error_frob)
```

## 매 결정 기준
| 상황 | Approach |
|---|---|
| Dense small matrix | `np.linalg.svd` |
| Top-k only, large | `randomized_svd` / `TruncatedSVD` |
| Sparse matrix | `scipy.sparse.linalg.svds` |
| LLM weight adapter | LoRA (low-rank ΔW) |
| Recommender (sparse ratings) | Funk SVD / ALS |

**기본값**: full SVD via NumPy for small dense; randomized for large; sparse SVD for sparse.

## 🔗 Graph
- 부모: [[Linear-Algebra-Foundations|Linear-Algebra]] · [[Matrix-Factorization]]
- 변형: [[Eigendecomposition]]
- 응용: [[Principal-Component-Analysis]] · [[LoRA]] · [[Recommender-Systems]]
- Adjacent: [[Ridge-Regression]]

## 🤖 LLM 활용
**언제**: Dimensionality reduction (PCA). Pseudoinverse 의 compute. Low-rank approximation (compression, denoising). LLM weight 의 LoRA / SVD pruning. Spectral analysis.
**언제 X**: Very large sparse matrix (use iterative methods like Lanczos). Streaming data (use online PCA / incremental SVD).

## ❌ 안티패턴
- **`full_matrices=True` for fat/thin**: 매 wasted memory — `full_matrices=False` 의 사용.
- **Eigendecomposition of `AᵀA`**: 매 numerically unstable (squares condition number) — direct SVD 의 use.
- **Forgetting to center for PCA**: SVD on uncentered X = X dominated by mean direction.
- **Naive SVD on huge sparse**: O(mn²) — 매 randomized / Lanczos 의 use.

## 🧪 검증 / 중복
- Verified (Trefethen & Bau "Numerical Linear Algebra", Strang "Linear Algebra and Learning from Data", LAPACK gesdd).
- 신뢰도 A+.

## 🕓 Changelog
| 날짜 | 변경 |
|---|---|
| 2026-05-08 | Phase 1 |
| 2026-05-10 | Manual cleanup — SVD with PCA, pseudoinverse, randomized, LoRA applications |
