翻译自英文原版 maths-cs-ai-compendium,共 20 章全部完成。 第01章 向量 | 第02章 矩阵 | 第03章 微积分 第04章 统计学 | 第05章 概率论 | 第06章 机器学习 第07章 计算语言学 | 第08章 计算机视觉 | 第09章 音频与语音 第10章 多模态学习 | 第11章 自主系统 | 第12章 图神经网络 第13章 计算与操作系统 | 第14章 数据结构与算法 第15章 生产级软件工程 | 第16章 SIMD与GPU编程 第17章 AI推理 | 第18章 ML系统设计 第19章 应用人工智能 | 第20章 前沿人工智能 翻译说明: - 所有数学公式 $...$ / $$...$$、代码块、图片引用完整保留 - mkdocs.yml 配置中文导航 + language: zh - README.md 已翻译为中文(兼 docs/index.md) - docs/ 目录包含指向各章文件的 symlink - 约 29,000 行中文内容,排除 .cache/ 构建缓存
12 KiB
矩阵分解
矩阵分解将复杂矩阵拆分为更简单的因子,用于求解方程组、计算逆矩阵和数据压缩。本文涵盖高斯消元、LU、QR、Cholesky、特征分解和SVD——这些算法是PCA、推荐系统和机器学习数值稳定性的基石。
-
矩阵分解(或因子分解)将一个矩阵拆分成更容易处理的更简单的部分。可以把它类比为因数分解:
12 = 3 \times 4比单独的12更容易理解。 -
我们分解矩阵是为了更快地求解方程组、稳定地计算逆矩阵、寻找特征值、压缩数据以及理解变换的几何结构。
-
最基本的技术是高斯消元(行化简)。思路很简单:给定方程组 $A\mathbf{x} = \mathbf{b}$,使用三种允许的操作简化 $A$,直到答案显而易见。
-
这些操作是:交换两行、将一行乘以非零标量、或将一行的倍数加到另一行上。
-
例如,要消除主元下方的第一列,从下面的行中减去第1行的倍数:
\begin{bmatrix} 2 & 1 & 5 \\ 4 & 3 & 7 \\ 6 & 5 & 9 \end{bmatrix} \xrightarrow{R_2 - 2R_1} \begin{bmatrix} 2 & 1 & 5 \\ 0 & 1 & -3 \\ 6 & 5 & 9 \end{bmatrix} \xrightarrow{R_3 - 3R_1} \begin{bmatrix} 2 & 1 & 5 \\ 0 & 1 & -3 \\ 0 & 2 & -6 \end{bmatrix}
- 目标是行阶梯形(REF):每个主元(每行第一个非零条目)下方全为零,且每个主元在其上方主元的右侧。矩阵呈现阶梯形状。
-
进一步得到简化行阶梯形(RREF),使每个主元为1且是该列中唯一的非零条目。每个矩阵有唯一的RREF。
-
一旦转换为三角形形式,我们通过回代求解:最下面一行直接给出最后一个变量,然后向上求解。
-
这是所有其他分解方法所建立的基础,分解的目标就是将矩阵简化为三角形形式,从而可以通过回代求解变量。
-
LU分解将高斯消元形式化,将方阵分解为 $A = LU$(或通过行交换得到 $A = PLU$),其中
L是下三角矩阵,U是上三角矩阵。
-
求解 $A\mathbf{x} = \mathbf{b}$:先通过前向代入(从上到下)求解 $L\mathbf{y} = \mathbf{b}$,然后通过回代(从下到上)求解 $U\mathbf{x} = \mathbf{y}$。两次简单的三角求解代替了一次困难的一般求解。
-
相比原始高斯消元的优势在于可复用。一旦得到
L和 $U$,就可以对许多不同的\mathbf{b}向量求解,而无需重新进行分解。 -
如果你需要用1000个不同的右端项求解同一个方程组(这在模拟中很常见),只需分解一次然后重复使用。
-
当矩阵是对称正定矩阵时(如协方差矩阵),我们可以做得更好。
-
Cholesky分解将其分解为 $A = LL^T$,其中
L是下三角矩阵。例如:
\begin{bmatrix} 4 & 2 \\ 2 & 5 \end{bmatrix} = \begin{bmatrix} 2 & 0 \\ 1 & 2 \end{bmatrix} \begin{bmatrix} 2 & 1 \\ 0 & 2 \end{bmatrix}
-
这大约比LU快两倍,并且保证数值稳定。可以将其视为矩阵的"平方根"。
-
如果分解失败(平方根下出现负值),则该矩阵不是正定的。因此Cholesky分解也可以作为正定性的检验方法。
-
方阵
A的特征向量是特殊方向,该变换在这些方向上只进行拉伸或压缩,而不旋转。特征值是缩放因子:
A\mathbf{x} = \lambda\mathbf{x}
-
大多数向量在乘以矩阵时方向会改变。但特征向量是特殊的:输出方向与输入方向相同,仅被
\lambda缩放。如果 $\lambda = 2$,特征向量长度加倍。如果 $\lambda = -1$,它翻转方向。如果 $\lambda = 0$,它被压缩为零。 -
例如,对于:
A = \begin{bmatrix} 3 & 1 \\ 0 & 2 \end{bmatrix}
向量 [1, 0]^T 是特征向量,$\lambda = 3$,因为 $A[1, 0]^T = [3, 0]^T = 3[1, 0]^T$。
-
求特征值需要解特征多项式 $\det(A - \lambda I) = 0$。根即为特征值。然后将每个
\lambda代回(A - \lambda I)\mathbf{x} = \mathbf{0}中,求出对应的特征向量。 -
关键性质:
A的迹等于其特征值之和。A的行列式等于其特征值之积。- 对称矩阵的特征向量互相垂直,特征值为实数。
- 正定矩阵的所有特征值为正。
- 协方差矩阵(我们将在统计学中遇到)总是半正定的。
-
通过特征多项式计算特征值对于大型矩阵来说是不切实际的。相反,使用迭代方法:
-
幂迭代:反复乘以
A并归一化。收敛到主特征向量(最大特征值)。简单但只能找到一个特征对。 -
QR算法:最常用的方法。使用QR分解反复分解和重组矩阵,直到矩阵收敛到三角形形式,对角线上的元素即为所有特征值。
-
反迭代:寻找最接近给定目标值的特征向量。当你大致知道想要哪个特征值时很有用。
-
对于大型稀疏矩阵,Arnoldi和Lanczos迭代利用稀疏性提高效率。
-
-
如果方阵有一组完整的线性无关的特征向量,它可以被对角化:$A = PDP^{-1}$,其中
D是以特征值为对角元的对角矩阵,P的列是特征向量。 -
这有什么用?对角矩阵非常容易处理。需要计算 $A^{100}$?不用将
A自乘100次,计算PD^{100}P^{-1}即可——而对角矩阵的幂只需独立地对每个对角元求幂。这将一个昂贵的运算变成了廉价运算。 -
特征基是完全由特征向量构成的基。在这个基下,矩阵变成对角矩阵,变换仅仅是沿每个特征向量方向的独立缩放。这就像是找到了变换的自然坐标系。
-
QR分解将任意矩阵
A分解为 $A = QR$,其中Q是正交矩阵(其列是标准正交的),R是上三角矩阵。可以理解为将"方向"信息($Q$)与"缩放和混合"信息($R$)分开。 -
Gram-Schmidt过程逐列构建 $Q$。取
A的第一列并归一化。取第二列,减去其在第一列上的投影(使其垂直),再归一化。对每一列重复此过程。结果是一组标准正交向量。 -
QR分解是QR算法求特征值背后的引擎。它也直接用于求解最小二乘问题:当
A\mathbf{x} = \mathbf{b}没有精确解(方程多于未知数)时,QR找到最佳近似解。 -
SVD(奇异值分解)是最通用、也可以说是最重要的分解。每个矩阵(任意形状、任意秩)都有SVD:
A = U\Sigma V^T- $V^T$($n \times n$,正交):旋转输入
- $\Sigma$($m \times n$,对角):沿正交坐标轴缩放(奇异值,非负,递减排列)
- $U$($m \times m$,正交):旋转输出
-
几何上,SVD表明每个线性变换,无论多么复杂,都只是一个旋转、一个沿坐标轴的拉伸、再一个旋转的组合。一个圆变成了一个椭圆。
-
奇异值($\sigma_1 \geq \sigma_2 \geq \ldots$)揭示了每个方向的"重要性"。大的奇异值对应最重要的方向。
A的秩等于非零奇异值的个数。 -
低秩近似:只保留最大的
k个奇异值,将其他置零,就得到了A的最佳秩-k近似。这就是图像压缩的原理:一张1000 \times 1000的图像可能只需要k = 50个奇异值就能看起来几乎一模一样,压缩了20倍。 -
SVD也提供了伪逆:$A^+ = V\Sigma^+U^T$,其中
\Sigma^+是对非零奇异值取倒数。 -
特征分解只对方阵有效,而SVD对任意矩阵都有效。这是它的关键优势。
-
PCA(主成分分析)使用特征分解(或SVD)进行降维。
-
想象一个数据集,每个样本有100个特征(堆叠成矩阵的100维向量)。其中许多特征是相关的、冗余的。
-
PCA找到数据实际变化的那些方向,让你只保留重要的部分。
-
第一主成分(PC1)是方差最大的方向。
-
第二主成分(PC2)捕获剩余部分的最大方差,且与第一主成分垂直。
-
如果大部分方差只集中在少数几个方向上,你可以将数据投影到这些维度上,丢弃其余部分,损失极小。
-
步骤:
- 标准化数据(减去均值,除以标准差),使所有特征贡献平等
- 计算协方差矩阵
- 求其特征值和特征向量
- 选择
k个最大特征值对应的特征向量(即主成分) - 将数据投影到这些主成分上
-
标准化至关重要:如果不做标准化,用公里测量的特征会主导用厘米测量的特征,而不论其实际重要性如何。
-
在实践中,PCA用于可视化(将高维数据投影到2D或3D)、降噪(丢弃主要是噪声的低方差方向),以及通过减少输入特征数量来加速机器学习模型。
-
核PCA将PCA扩展到非线性关系。它通过核函数将数据映射到更高维空间,在那里结构变得线性,然后应用标准PCA并投影回来。
-
Schur分解将方阵分解为 $A = QTQ^\ast$,其中
Q是酉矩阵,T是上三角矩阵。每个方阵都有Schur分解,即使它不能被对角化。 -
非负矩阵分解(NMF) 将一个矩阵分解为两个非负矩阵:$A \approx WH$,其中
W和H的所有条目都 $\geq 0$。与可能产生负条目的SVD不同,NMF只做加法,从不做减法。这使得各部分可解释:在主题建模中,W给出每个文档的主题权重,H给出每个主题的词权重,全部非负,这与我们对文档"包含多少某个主题"的思考方式相符。 -
谱定理指出,对称(或Hermitian)矩阵总可以用正交(或酉)矩阵对角化。它们的特征值总是实数,特征向量总是正交的。这是PCA的理论基础。
编程练习(使用CoLab或Jupyter Notebook)
- 计算对称矩阵的特征值和特征向量。验证特征向量互相垂直,并从特征分解重建矩阵。
import jax.numpy as jnp
A = jnp.array([[4.0, 2.0],
[2.0, 3.0]])
eigenvalues, eigenvectors = jnp.linalg.eigh(A)
print(f"Eigenvalues: {eigenvalues}")
print(f"Eigenvectors orthogonal: {jnp.dot(eigenvectors[:,0], eigenvectors[:,1]):.6f}")
# Reconstruct: A = P D P^T
D = jnp.diag(eigenvalues)
A_reconstructed = eigenvectors @ D @ eigenvectors.T
print(f"Reconstruction matches: {jnp.allclose(A, A_reconstructed)}")
- 实现幂迭代求最大特征值,以及反迭代求最小特征值。与
jnp.linalg.eigh比较。然后尝试自己实现QR算法。
import jax.numpy as jnp
A = jnp.array([[4.0, 2.0],
[2.0, 3.0]])
# Power iteration: finds the LARGEST eigenvalue
v = jnp.array([1.0, 0.0])
for _ in range(20):
v = A @ v
v = v / jnp.linalg.norm(v)
print(f"Largest eigenvalue: {v @ A @ v:.4f}")
# Inverse iteration: multiply by A^{-1} instead of A, finds the SMALLEST eigenvalue
v = jnp.array([1.0, 0.0])
for _ in range(20):
v = jnp.linalg.solve(A, v)
v = v / jnp.linalg.norm(v)
print(f"Smallest eigenvalue: {1.0 / (v @ jnp.linalg.solve(A, v)):.4f}")
print(f"jnp.linalg.eigh: {jnp.linalg.eigh(A)[0]}")
- 计算矩阵的SVD,然后仅使用前k个奇异值重建矩阵,观察近似质量随k的变化。
import jax.numpy as jnp
A = jnp.array([[1.0, 2.0, 3.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]])
U, S, Vt = jnp.linalg.svd(A)
for k in [1, 2, 3]:
approx = U[:, :k] @ jnp.diag(S[:k]) @ Vt[:k, :]
error = jnp.linalg.norm(A - approx)
print(f"k={k}, reconstruction error: {error:.4f}")