如何高效计算高维行列式与逆矩阵
- 1如何高效计算高维行列式与逆矩阵本文
本篇主要回答下面这个问题:
当维度 很大时,如何高效计算 和 ?如何高效计算矩阵-向量乘法?
这个问题其实是两部分,而且第二句(矩阵-向量乘法)才是关键——它在暗示我们:我们根本不需要真的算出 .
答案:用矩阵分解代替求逆。
对对称正定的 做 Cholesky 分解 ,于是
- ,计算成本极小;
- 通过两次三角求解(前代 + 回代)得到,每次 ,不用显式求逆。
总代价:一次分解 ,之后每次查询 。
1. 如何高效计算 和
1.1 “直接求逆” 的坏处
朴素做法有三宗罪:
| 做法 | 代价 | 问题 |
|---|---|---|
| 显式算 (如 Gauss–Jordan) | 数值不稳定;多花 内存 | |
| 直接展开算 | 比 还糟 | 大 下上溢/下溢 |
| 然后矩阵-向量乘 | 每次 | 但其实分解后能更省 |
1.1.1 为什么显式求逆是 ?
我们可以数”扫过矩阵的次数”:消到第 个主元时,要把主元下方约 行的该列清零,每次行变换要更新整行(约 个数),故单个主元 ;共 个主元:
更精确地,待消的块逐次缩小,,加上回代共约 ——这正是 Gauss 消元 / LU 是 的来源。
关于避免直接求逆,最核心的原因在于:在实际问题里,我们几乎从不需要 本身,我们需要的只是它能作用于一个向量:
也就是说,所有用到 的公式,都会以上面两种形式出现。我们以多元高斯对数密度为例:
拆开看第二项:先算 ,再算 (一个内积)。整个过程只用了”作用一次”的结果,从来没有需要逆矩阵本身。
于是就可以跳过求逆,改用分解(Cholesky):
下面我们将详细介绍 Cholesky 分解。
1.2 Cholesky 分解
设 对称正定(symmetric positive definite, SPD),即
则存在唯一的下三角矩阵 ,其对角元全为正(),使得
称为 的 Cholesky 因子(Cholesky factor)。
更详细的介绍参见 Cholesky Decomposition.
协方差矩阵 对称正定,正好命中 Cholesky 的适用条件:
下面我们用一个例子来展示:
我们的目标是求解方程
其中
我们有
设 ,于是要解 ,等价于解:
第一步前代: 展开成
我们可以轻松解出来
第二步回代: 展开()
然后算出 .
简单验算一下:
可以看到,我们从头到尾没有算过 ,但拿到了 .
对于 的计算也是一样的。我们知道,三角矩阵的行列式 = 对角元之积(这是三角矩阵的好性质之一)。再由 :
已经在第 1 步算好了,所以取行列式只是把 个数乘一乘:。
这个数会爆炸或消失。举个例子:、每个 ,那么
而计算机的双精度浮点数最大只能表示到约 ——直接溢出了,变成 inf(反过来, 小于 1 时会一路下溢成 0,信息全丢)。但取对数:
所以,在实际代码里(比如算高斯密度时)永远取 再往下算,这也是 “机器学习的 log-likelihood 为什么到处是 log” 的一个技术原因。
1.3 回到高斯密度:整套流程
把上面拼起来,多元正态密度的计算变成:
- 一次 Cholesky ,之后可重复使用;
- 每个样本: 是 ,马氏距离 。
上面给出了两种不同的时间复杂度,对应计算过程中的两个阶段:
| 阶段 | 依赖什么 | 要做几次 | 成本 |
|---|---|---|---|
| ① 准备:对 做 Cholesky,得到 | 只依赖分布() | 一次 | |
| ② 查询:给一个数据点 ,算 | 每个样本各不相同 | 次( 个样本) | 每次 |
单个样本的公式是
-
第一项 :纯常数,。
-
第二项 :把 个对角元取对数再加起来,. 注意它根本不含 ——对所有样本都一样,所以严格说算一次就够了(之后缓存成一个数,每次查表 )。
-
第三项(马氏距离) 才是真正”每个样本都要重算”的部分:
怎么算?不碰 ,而是解两次三角方程:
合计 。每来一个新样本,就重复一次这个 的流程。
1.4 当 极大、连 都受不了时
这是真正的”大维度”对策,和我们后面将要介绍的 SVD / 低秩 相关:
(a) 低秩 + 对角结构(Woodbury 恒等式)
若
则用 Woodbury 矩阵恒等式:
所有昂贵的运算都只作用在小矩阵 ()上,代价降到 。
(b) 稀疏 / 带状 / 层次结构
若 (精度矩阵)稀疏(如高斯随机场、稀疏高斯过程),就用稀疏 Cholesky / 稀疏 LU,代价 甚至 。
(c) 随机化方法
用随机化 SVD 求低秩近似——这正是 Lec2 结尾预告的”randomized SVD”。
(d) 不要 本身,只要它的对数 —— 之前已说明。
2. 如何高效计算矩阵-向量乘法
2.1 稠密一般矩阵: 是下界
对一般稠密 , 需要
你必须碰到矩阵的每一个元素,所以 是渐近最优的,无法再降。
FLOPs = Floating-point Operations(浮点运算次数),即做了多少次的浮点数加减乘除。
在上面的例子中,计算某个 需要 次乘法 + 次加法,一共有 个 ,所以总运算量约为 ,用大 记就是 .
那”高效”从哪来?硬件层面:
- 矩阵-向量乘法算术强度低(每读一个矩阵元素只做一次乘法+一次加法),是内存带宽瓶颈;
- 优化手段:cache 分块(blocking)、向量化、利用对称性( 对称 → 只存一半);
- 批量做多个向量:把 拼成矩阵,变成 Level 3 矩阵-矩阵乘法,算术强度大幅提升,性能天差地别。
2.2 利用结构:真正能把指数降下来的地方
| 矩阵结构 | 朴素 | 结构化后 | 手段 |
|---|---|---|---|
| 一般稠密 | BLAS、分块、向量化 | ||
| 对称 | 只存/算一半 | ||
| 低秩 | 先算 ,再乘 | ||
| 带状(带宽 ) | 只遍历带宽 | ||
| 稀疏( 非零) | 稀疏存储 + SpMV | ||
| Toeplitz/循环 | 用 FFT 卷积 | ||
| 层次/H-矩阵 | 或 | 低秩分块 |
回到高斯: 之所以能”高效”,本质就是把 看成”三角分解的作用”而不是一个显式矩阵——用两次 的三角求解,取代一次 求逆 + 一次 乘法。
2.3 近似计算
若允许近似:
- 随机化投影 / Johnson–Lindenstrauss:把 维投影到低维再做;
- 随机化 SVD(后续内容):用少量矩阵-向量乘逼近低秩结构;
- 采样/草图(sketching): 或 。
文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!





