课程/M07/SVD 的计算与性质
M07 · SVD核心约 40 分钟

7.2 SVD 的计算与性质

本节位置:模块 7 · SVD | 前置:7.1 | 预计:40 分钟

一句话:奇异值就是 特征值的平方根, 的特征向量就是右奇异向量——但真正算的时候别真的去乘 。

0. 场景引入

你是单细胞测序组的工程师。一批数据是 3000 个细胞 × 2000 个高变基因的表达矩阵,fp32 占 。组里约定:低于 的奇异值视为测序噪声,不算一个独立维度;这个阈值决定下游聚类保留几个主成分。

你按教科书流程先算 (),再对它做特征分解、开方,得到最小奇异值 ,于是判定数值秩 1999。同事用 LAPACK 的 svd 直接算同一个矩阵,得到 ,数值秩 2000。两个数差了约 350 倍,而阈值 恰好卡在中间:一个说「这一维是噪声,截掉」,一个说「它是真实维度,保留」。

决策的代价不对称:截错了,可能把分开两个稀有亚群的方向当噪声删掉,聚类少一类,后续验证实验的钱白花;不截,噪声方向会污染降维结果。按一次单细胞建库约 3 万元估算,重做一轮既费钱又费样本。

问题出在第一步: 把条件数(condition number)平方了。读完你能回答三个问题:

  1. 奇异值和 特征值的确切关系是什么?
  2. 为什么显式乘 会丢掉一半有效数字?
  3. 手算、证明和真正跑数值计算,应该分别用哪条路?

1. 直觉

是「从输入侧看 」:它记录每个输入方向被放大的平方。因为 ,若 是 的特征向量、特征值为 ,则 ,拉伸倍数是 ——这就是奇异值。所以 的特征向量 = 右奇异向量,特征值 = 。

对称地, 是「从输出侧看 」,它的特征向量是左奇异向量,非零特征值同样是 。两张「X 光片」看的是同一副骨架。

💡 一句话直觉:SVD = 对 做谱分解,再开方; 由 把 搬过去得到。

1.1 它在现实世界里对应什么

在单细胞数据里, 的每一行是一个细胞、每一列是一个基因。SVD 给出的第 个三元组可以读成:

数学对象单细胞数据里的对应物
第 个「协同表达程序」的强度
这个程序在 2000 个基因上的权重
这个程序在 3000 个细胞上的得分
从「基因-基因」侧拍的 X 光片
从「细胞-细胞」侧拍的 X 光片

两张片子看的是同一副骨架:非零特征值都是 ,只是一个按基因排、一个按细胞排。这也是为什么 那么诱人——它把 的问题压成 。

1.2 这个类比在哪里失效

  • SVD 给的是正交的线性程序;真实的基因调控有非线性、有层级, 不能直接当因果强度读。
  • 「X 光片」把对比度平方:。 从 到 时, 从 到 ,正好撞上双精度的颗粒()。图像还在,细节已经糊了。
  • 因此 适合手算和证明,不适合数值计算;这两件事在这一节要分开说。

1.3 量级直觉

双精度的相对分辨率是 。因为 ,要让它不被颗粒淹没,需要

这个式子说的是:显式构造 的路线,只能可靠分辨到约 的相对奇异值;再小就和 0 分不开。直接对 做 SVD 没有这个平方,门槛回到 量级。

代价还有算力: 时,形成 本身就要 FLOP,和一次直接 SVD 的 同量级;再对它做 的特征分解是额外开销。精度更差,算力却没省。

2. 定义

2.1 由 构造 SVD(存在性版本)

设 ,。则 对称半正定,由谱定理存在正交 使

流程:

  1. 对 做特征分解,得 与单位特征向量 ;
  2. 令 ,设前 个为正,则 ;
  3. 对 定义 ;
  4. 已标准正交(7.1 的 4.3),再补 个单位向量使 正交(它们张成左零空间);
  5. 取 ,对角元为 ,其余为 0。

得到 。注意 是 、 是 ,而 与 同形。

2.2 三个矩阵的关系

矩阵形状特征值特征向量
(含 个 0)右奇异向量
(含 个 0)左奇异向量
仅当 才有定义与奇异向量一般不同

与 的非零特征值完全相同,都等于 。差别只在零特征值的个数:分别是 和 。

2.3 实际算法:不要显式构造

LAPACK 的 gesdd/gesvd 走的是双对角化 + 隐式 QR(Golub–Kahan 1965 年给出的算法):先用 Householder 变换把 化成上双对角矩阵(),再迭代求奇异值。全程只对 做正交变换,从不形成 。NumPy 的 np.linalg.svd、PyTorch 的 torch.linalg.svd 都调用它。

3. 为什么这样定义

为什么 是半正定的? 对任意 有 ,二次型永不为负,所以特征值 ,开方总合法。这是奇异值非负的代数根源。

为什么用 而不是随便一个对称矩阵? 因为它恰好编码了「所有输入方向被拉伸的平方」,而谱定理保证它有完整的正交特征基。 本身可能没有实特征值(如旋转矩阵),但 一定有,而且是对称的——这就是 SVD 比特征分解普适的原因。

为什么还要补 的剩余列? 当 时, 只给出 个方向, 需要 个。缺的那些对应「任何输入都到不了的方向」,即左零空间,可以任意选一组标准正交基,它们不影响 (因为乘的 是 0)。

3.1 反事实:真的去乘 会坏在哪

取一个能手算的 例子,:

它的迹约等于 ,行列式恰好是 。于是

到这里数学没错。坏在浮点: 的元素量级是 ,一次舍入的绝对误差约 ;而你要分辨的 只有 ——比单个元素的一次舍入还小一个数量级。换句话说,

落在 的一个 ulp 以下,在算出来的矩阵里根本表示不出来:它可能被算成 ,也可能因舍入变成负数,开方直接得到 nan。

后果是数值秩判错:真值 , 路线可能报 ,于是你把一个真实维度截掉。更讽刺的是,,而 ,已经超过 ——连条件数本身都算不准了。

对照直接 SVD:,,,所以 ,和上面一致,但全程只对 做正交变换,不平方。手算和证明用 ,数值计算用 LAPACK 的 SVD——这不是风格问题,是有效数字问题。

4. 性质与推导

4.1 核心推导:

第二、三步用到「迹在正交相似下不变」。这个式子说的是:Frobenius 范数把所有奇异值平方加起来,因此低秩近似的误差可以用被丢掉的那部分奇异值精确计算(第 7.3 节)。

4.2 性质清单

性质式子说明
谱范数(spectral norm)最大拉伸倍数
最小奇异值可逆时
条件数误差放大上界;见 4.6
秩数值上用阈值判
Frobenius见 4.1
扰动稳定Weyl 不等式:奇异值对扰动不敏感

最后一条值得强调:奇异值稳定,奇异向量不一定。 与 很接近时,对应的两个方向可以剧烈旋转; 与 相距很远时, 才稳定。

4.3 与特征分解的区别

维度特征分解SVD
存在条件方阵且可对角化任意
基一组(,一般不正交)两组(,都正交)
取值可为负、可为复数一定非负实数
与转置 特征值相同奇异值相同,向量互换
关系正规矩阵:一般矩阵:
扰动特征值可能剧变(非正规矩阵)

正规矩阵(normal matrix)指 ,包含对称、反对称、正交矩阵。只有在这类矩阵上,SVD 与特征分解才「几乎同一件事」。

5. 例子

5.1 手算: 矩阵的完整 SVD

特征值:。

右奇异向量: 时 ,取 ; 时 ,取 。

奇异值:,。

左奇异向量:

只有 2 个,还需第 3 个。取 ,验证:, ✓。

核对:,而 ✓;; 不是方阵,根本不存在特征值——这正是 SVD 的用武之地。

5.2 手算:为什么别乘

考虑 ,。理论上

于是 量级,,。双精度只有约 16 位十进制有效数字:直接对 做特征分解, 会被舍入误差淹没(实测常直接算成 0),符号甚至可能变负——开方就得到 nan 或虚假的秩。

用 np.linalg.svd(A) 直接算则稳定得多,因为算法从不对 平方。结论:手算和证明用 ,数值计算用 LAPACK 的 SVD。

5.3 场景闭环:3000×2000 的单细胞矩阵

输入:3000×2000 fp32,24 MB。每列已按测序深度归一化并中心化,否则第一主成分会指向整体表达水平。

计算:直接 SVD 的主项是双对角化,约 FLOP 量级,单核按 10 GFLOP/s 估约 1.2 s。若先乘 :形成 Gram 矩阵要 FLOP,再对 2000×2000 做特征分解约 FLOP。两者的时间同量级,但后者多占 16 MB,还把 平方。

输出:数值秩 (取 )与保留的主成分数 (例如 30)。两条路线在 上给出 与 ,正好跨过阈值,于是 或 。

成本:完整 SVD 的 是 fp32=24 MB, 是 16 MB;只要前 30 个主成分时, 为 360 kB、 为 240 kB。 路线额外占 B=16 MB,却省不下时间。

失败条件:

  • 阈值附近的奇异值: 落在 附近时,两种算法给出不同的秩,下游聚类可能少一个稀有亚群。兜底:不要只报秩,把谱画出来,并对 做 倍敏感性分析;结论随 翻转就说明这一维不可靠。
  • 噪声不是白噪声:测序深度、批次效应会集中在少数方向,截断可能删掉批次而不是噪声。兜底:先做批次校正,或把已知协变量回归掉。
  • 精度天花板:bf16 下相对精度约 , 的方向不可信;低精度流程里不要用 判秩。

6. 常见误区

  1. 误区:奇异值是「 的特征值开平方」。 纠正:是 (或 )特征值的平方根。 可能没有实特征值, 的特征值是 ,奇异值却是 。
  2. 误区: 总是成立。 纠正:只对正规矩阵成立。 特征值双 1,奇异值是 与 (黄金比例)。
  3. 误区:算出一个很小的奇异值就说明矩阵秩亏。 纠正:先看阈值。NumPy 的 matrix_rank 用 ;低于阈值的才算 0(数值秩,第 7.4 节)。这个数值秩判据在 Golub 与 Van Loan 里有系统讨论。
  4. 误区:奇异值算得准,奇异向量也算得准。 纠正: 时,对应子空间内的任意正交组合都是合法的奇异向量,单个向量的数值结果没有意义,只有子空间稳定。

7. 概念网络

8. 通往大模型:算得对,才算得动

出现位置:分析权重谱、估计谱范数做谱归一化、诊断微调是否病态、以及在低精度下判断「哪些奇异值还可信」。

形状与代价:对 做完整 SVD 约需 次浮点运算,显存里还要放 的 和 : 字节(fp32) MB。实际分析常常只求前 个(svds,)。

为什么需要: 是谱归一化(spectral normalization)要约束的量——把 压到 1 附近,判别器的 Lipschitz 常数就有上界。训练中还可以用幂迭代估计 :迭代 再归一化,10–20 步就够,代价只有两次矩阵向量乘。

低精度陷阱:bf16 只有 8 位有效位(1 位隐含 + 7 位显式),相对精度约 。 低于 量级时,尾部奇异值在 bf16 下已不可分辨;fp32 相对精度约 ,门槛降到 量级。一个 的 权重在 bf16 下,最小的那些奇异值只是噪声,不能用来解释「模型学到了什么」。

可检验结论:对随机 (元素方差 ),奇异值谱落在 附近(Marchenko–Pastur 律),、 接近 0, 随 增大而不是 1;因此未训练的权重天然病态,微调时看到的大 未必是训练造成的。

s = np.linalg.svd(W, compute_uv=False)   # W: [4096, 4096]
print(s[0], s[-1], s[0] / s[-1])

算错时下游看到什么:若用 路线把 算成 、据此判秩 1999,下游就少一个维度。如果那个方向恰好分开两个稀有亚群,聚类结果会少一类,标记基因列表里也找不到它。用户看到的是「细胞类型数比预期少一个」,而不是一个报错。兜底是同时打印谱、阈值和两种算法的差,并对 附近的方向做敏感性分析。

9. 练习

  1. 概念:为什么 的特征值一定非负?用一行式子说明。
  2. 计算: 由 求全部奇异值并验证 ;再对 求 、、、, 是有限值吗?
  3. 场景:某权重矩阵的奇异值为 。它的前两个奇异向量在你的数值实验里两次运行结果不同,合理吗?
  4. 开放:既然奇异值稳定而奇异向量不稳定,做「权重可解释性分析」时应该报告哪一个?
参考答案
  1. ,二次型非负 特征值非负。
  2. ,,, ✓。对 :,,(奇异)。
  3. 合理。 与 很接近(相对差 5%),对应二维子空间内的方向可以任意旋转;稳定的是子空间(张成的平面),不是单个向量。
  4. 优先报告奇异值谱与低维子空间(如「前 10 维解释了 90% 能量」),少报单个奇异向量的坐标;若必须报向量,给出子空间距离与 作为置信度。

10. 一页速记

  • ; 是 的特征向量,。
  • 物理意义 / 现实对应: 是第 个方向的「透光率」; 的特征值是透光率的平方,所以它把动态范围平方,可分辨的 相对下限从 抬到 。
  • 与 非零特征值相同,都是 。
  • ,,,。
  • 特征分解只对方阵、可能有复数;SVD 对任意矩阵、一定非负;手算用 ,数值计算用 LAPACK,显式乘 会把 平方。

11. 参考文献与致谢

这一页的知识不是凭空来的。下面列出本页直接借用的原始工作与权威整理;正文中的人名、定理名已链接到对应条目。链接优先指向 DOI、arXiv 或可长期访问的原文存档。

  • Golub 与 Kahan(Gene H. Golub & William Kahan, 1965):Calculating the Singular Values and Pseudo-Inverse of a Matrix。把 SVD 计算化成「Householder 双对角化 + QR 迭代」,全程不形成 ,因此不会把条件数平方;这就是本页第 2.3 节里 LAPACK gesvd/gesdd 的算法祖先。SIAM J. Numer. Anal. 2(2)
  • Golub 与 Van Loan(Gene H. Golub & Charles F. Van Loan, 2013):Matrix Computations(4th ed.)。对 SVD 的存在性、数值秩、条件数与最小二乘给出标准处理,本页第 4.2 节的性质清单与第 6 节的秩判据都可在此查证。Johns Hopkins University Press

下一篇 → 7.3 低秩近似与 Eckart–Young

返回 M07 导览去练习场

随堂测 · 4 题

数值难度 1第 1 / 4 题
对 , 等于多少?

源文件:07-SVD/02-SVD的计算与性质.md

输入关键词开始搜索