奇异值分解(SVD)-- 任意矩阵的拆解术
特征分解只适用于方阵,但 SVD 没有这个限制——任意矩阵都可以做 SVD。
它是推荐系统、图像压缩、LoRA 微调等技术背后的数学引擎。
SVD:把矩阵拆成三部分
(m×n)
(m×m)
旋转
(m×n)
缩放
(n×n)
旋转
几何直觉:任何线性变换 = 旋转 + 沿坐标轴缩放 + 再旋转。
Σ 的对角元称为 奇异值,从大到小排列,表示矩阵在各个正交方向上的「能量」。
截断 SVD:用前 k 个奇异值近似
\[ A \approx U_k \Sigma_k V_k^T \]k 越小 = 压缩率越高 = 近似越粗糙。这是降维和压缩的核心思想。
生活例子
压缩一张图片
一张 1000×1000 的表(100 万个数),SVD 拆开后只用前 10 个奇异值重建。
只需要存约 10×1000×2 = 20000 个数,就能得到一个不错的近似。
这就是 SVD 压缩的威力——丢掉不重要的「能量」,保留核心结构。
数学定义
\[ A = U \Sigma V^T \]U 的列是左奇异向量(正交),V 的行是右奇异向量(正交),Σ 对角元 σ₁ ≥ σ₂ ≥ ... ≥ σ_r > 0 是奇异值。
Python 动手实践
实例
A = np.array([[1,0,0,0,2],[0,0,3,0,0],[0,0,0,0,0],[0,4,0,0,0]])
U, S, VT = np.linalg.svd(A)
print("奇异值:", np.round(S, 2)) # [4. 3. 2.24 0.]
print("非零奇异值个数 = 秩 =", np.sum(S > 1e-10))
# 图像压缩演示:秩为1的图像
img = np.outer(np.array([1,2,3,2,1]), np.array([2,4,6,4,2]))
U_i, S_i, VT_i = np.linalg.svd(img)
print("\n图像矩阵的奇异值:", np.round(S_i, 2))
# 只用1个奇异值完美重建(因为秩=1)
k = 1
approx = U_i[:,:k] @ np.diag(S_i[:k]) @ VT_i[:k,:]
print("k=1重建误差:", np.linalg.norm(img - approx))
奇异值: [4. 3. 2.24 0.] 非零奇异值个数 = 秩 = 3 图像矩阵的奇异值: [78.26 0. 0. 0. 0.] k=1重建误差: 7.11e-14 (几乎完美)
AI 中的应用场景
LoRA 微调的数学基础
LoRA 假设 :\( \Delta W \) 是低秩的——这等价于假设 \(\Delta W \) 的 SVD 中只有前 r 个奇异值显著,其余可以忽略。r 取得越小,可训练参数越少,但近似精度越低。实践中 r=8 或 16 常是效果与效率的最佳平衡点,这源于对权重矩阵奇异值衰减速度的经验观察。
推荐系统:矩阵分解协同过滤
用户-物品评分矩阵 R(m×n)做截断 SVD:\( R \approx U_k \Sigma_k V_k^T \)。U_k 的每行是用户的 k 维隐向量,V_k 的每行是物品的 k 维隐向量。用户 u 对物品 i 的预测评分 = u 的隐向量与 i 的隐向量的点积。
模型压缩与蒸馏
全连接层的权重矩阵 W 做 SVD 后,用截断 SVD 近似:\( W \approx U_k \Sigma_k V_k^T \)。原矩阵 m×n 的参数量为 mn,分解后为 k(m+n+1)。当 k << min(m,n) 时,参数量大幅减少。这在移动端部署大模型时非常有用。
PCA 的 SVD 实现
sklearn 的 PCA 底层不用特征分解而是用 SVD——对中心化后的数据矩阵直接做 SVD,右奇异向量 V 的列就是主成分方向。SVD 数值更稳定且不需要显式计算协方差矩阵。
