"매 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).
매 응용
PCA — top-k SVD of centered X.
Pseudoinverse A⁺ = V Σ⁺ Uᵀ.
Low-rank approximation (Eckart-Young theorem).
Recommender systems (Netflix, Funk SVD).
LoRA / weight compression (2026 LLM fine-tuning).
Image compression.
💻 패턴
NumPy SVD
importnumpyasnpA=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
defpca_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 VtreturnX_centered@Vt[:k].T# project to k-dim
Pseudoinverse
defpinv_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)returnVt.T@np.diag(s_inv)@U.T# Solve least squares: x = A⁺ bx=pinv_svd(A)@b
Image compression
fromPILimportImageimportnumpyasnpimg=np.array(Image.open("photo.jpg").convert("L"))U,s,Vt=np.linalg.svd(img,full_matrices=False)# Keep top-k singular valuesk=50compressed=U[:,:k]@np.diag(s[:k])@Vt[:k,:]# Storage: m*k + k + k*n vs m*n
Randomized SVD (large matrices)
fromsklearn.utils.extmathimportrandomized_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)
importtorch# 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)classLoRALayer(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))defforward(self,x,W_frozen):returnx@W_frozen.T+x@self.A.T@self.B.T
Eckart-Young error bound
# Best rank-k approx error in Frobenius normU,s,Vt=np.linalg.svd(A,full_matrices=False)k=5A_k=U[:,:k]@np.diag(s[:k])@Vt[:k,:]error_frob=np.sqrt(np.sum(s[k:]**2))assertnp.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.