想象你被派到一个陌生城市做交通规划。你手里有全市居民的通勤轨迹——每个人每天从哪出发、去哪、走哪条路。数据多到看不过来,但你真正关心的只有一件事:这个城市的主干道到底在哪?是东西向还是南北向?只要抓住这几条主干道,你就能理解整个城市的出行格局。 PCA 干的就是这件事:在纷繁的数据里,找到那个“方差最大”的方向——最能把数据摊开、最能代表整体结构的方向。而 SVD 则像一套给路网做“体检”的工具:它把整张通勤矩阵拆成“出行模式 × 流量大小 × 道路骨架”三块,让你只看最重要的几条路就能重建出接近原样的地图。更妙的是,随机 SVD 相当于“随机抽查几条街道”,就能极快地估算出主干道方向——这正是大矩阵降维加速的秘诀。 这篇文章,我们就沿着这条“城市主干道”把 SVD 与 PCA 的关系一次讲透:从等价性、截断降维,到随机加速,再到实战选型与面试题。
掌握“数据主干道”的寻找术,是数据降维、推荐系统和图像压缩岗位的必备技能,也是面试高频考点,学完即可用 SVD 实现 PCA 降维。
可视化演示
展示SVD与PCA等价性、截断SVD降维过程与奇异值衰减曲线,可视化数据投影到主成分的维度压缩。
本节配有交互动效(进入视口后自动加载,约 3KB)。
SVD降维投影过程 数据点投影到前k个主成分方向,保留最大方差 X_k=U_kΣ_kV_k^T 截断SVD在Frobenius范数下最优低秩近似
PCA降维原理
假设你手里有一张城市通勤地图,上千条线路密密麻麻。要快速抓住全貌,你不会逐条研究每条小路,而是找出少数几条“主干道”——它们承载了绝大多数人流,方向最能代表城市的骨架。PCA 做的正是这件事:在数据里找到最能摊开全貌的那条线。
计算机里,每条通勤记录是一个向量,所有记录构成数据矩阵 X。数据的“人流分散程度”在数学上叫方差。“主干道”就是这样一个方向 w:把数据投影到 w 上之后,投影点的方差最大。
要最大化这个量,还要约束 w 是单位向量,因为方向不随长度变化。解这个约束优化问题,答案就是协方差矩阵 C 的最大特征值对应的特征向量——第一条主干道就此诞生。
找到的第一个 w 就是城市第一条“主干道”——第一主成分。找到它之后,在垂直方向再找第二条,依此类推,城市骨架便一步步勾勒出来。
- 投影坐标每个样本点 x_i 在方向 w 上的坐标是内积 w·x_i,相当于把点“压”到主干道的刻度上。
- 投影方差对所有投影坐标求平方平均,即数据中心化后的方差;方差的本质是“人流在主干道上铺开的宽度”。
- 单位约束加上 ||w|| = 1 去掉方向长短的无关自由度,保证只在“朝向”上比较,不因长度偷分。
协方差特征分解
主干道不会独立存在:如果南北向的主干道堵车,东西向可能也跟着堵。要完整理解路网,你需要一张“路与路之间如何联动”的地图——协方差矩阵就是这张地图。
把 n 条通勤记录整理成矩阵 X(每行一个样本),先对每列减去均值做中心化,再计算 XᵀX/(n−1),就得到 d×d 的协方差矩阵 C。C 的第 i 行第 j 列刻画道路 i 与道路 j 的联动强弱,对角线则是每条路自身的波动幅度。
特征分解把 C 写成 QΛQᵀ。Q 的每一列是一个特征向量(方向),Λ 对角线上的元素是特征值(该方向上的方差大小)。把特征值从大到小排序,对应的特征向量就是第一、第二……主成分方向,城市骨架由此完整列出。
拿到这张“相关性地图”的特征分解,你就拥有了城市主干道的完整目录。但直接走这条路线有个隐患:先平方数据再做分解,数值上容易“失真”——这就是下一节 SVD 登场的原因。
- 数据中心化先让每列均值为 0,否则协方差会被“市中心”的绝对位置污染;我们要看“波动”而不是“位置”。
- 协方差矩阵XᵀX 把所有样本的交叉联动累加后归一化,元素 (i,j) 表示第 i 条路与第 j 条路的联动强不强。
- 特征分解Q 的列给出方向(路网骨架),Λ 的对角元给出每个方向上的“人流宽度”,降序排列后逐条取用。
SVD等价性
同样是研究城市路网,你可以用“相关性地图”(协方差矩阵),也可以直接看“每条通勤记录本身”。SVD 就是直接拆解原始记录的方案:它把整个通勤矩阵拆成三块积木。
对中心化后的数据矩阵 X(n×d)做 SVD:X = UΣVᵀ。U 的列是“出行模式的空间”,V 的列是“道路骨架方向”,Σ 的对角元是奇异值,刻画每个方向的流量大小。把 XᵀX 代进去,会得到一个漂亮的结论。
XᵀX = (UΣVᵀ)ᵀ(UΣVᵀ) = VΣ²Vᵀ。这说明:X 的奇异值平方恰好是 XᵀX 的特征值(λ_i = σ_i²),右奇异向量 V 的列恰好是 XᵀX 的特征向量。换句话说,协方差矩阵的特征分解就是 SVD 的“平方视角”——数学上等价,但数值上 SVD 更稳,因为不用先把数据平方一次。
同一座城市,协方差特征分解像“平方后的地图”,SVD 像“原始测绘数据”。结论一致,但原始数据少了一次平方误差,更稳更准,这也是工程上常用 SVD 实现 PCA 的原因。
- SVD 分解任何 n×d 矩阵都能拆成左奇异向量 U、奇异值 Σ、右奇异向量 Vᵀ 三块,U 与 V 的列各自正交。
- 代入转置相乘把 XᵀX 展开,利用 UᵀU = I 消去中间项,剩下 VΣ²Vᵀ。
- 特征值桥接左右对照,XᵀX 的特征值就是 σ_i²,特征向量就是 V 的各列,二者指向同一副骨架。
截断SVD降维
城市不可能把所有小巷都纳入主干规划。交通规划的常规操作是:从所有道路里挑出流量最大的前 k 条“快速路”,升级为主干网,其余小巷忽略——城市骨架照样清晰。
截断 SVD 就是这个操作:只保留前 k 个最大的奇异值和对应的奇异向量,得到低秩矩阵 X_k = U_k Σ_k V_kᵀ。投影坐标 Z = X V_k 就是降维后的主成分得分,任何新样本都能用这套“快速路网”换上低维坐标。
矩阵可以写成 r 个“秩一外积”之和:X = Σ σ_i u_i v_iᵀ。截断到 k 项后,丢掉的是 σ_{k+1}…σ_r 对应的“小巷”。Eckart–Young 定理保证:在所有秩不超过 k 的矩阵里,X_k 的 Frobenius 重构误差最小,误差恰好等于被丢掉奇异值的平方和开根号。
快速路留多少条,取决于你能容忍多少“地图失真”。实际使用时常看方差保留率——前 k 个奇异值平方和占总平方和的比例——来决定 k,这就是压缩与信息的权衡。
- 外积展开每个 σ_i u_i v_iᵀ 都是一层“道路图层”,σ_i 越大图层越重要,总图由这些图层叠加而成。
- 截断保留只叠前 k 层得到 X_k;它仍是完整的 n×d 矩阵,但摸起来“更粗糙”,丢掉了细节小巷。
- 重构误差Frobenius 范数衡量“重建地图与真实地图的差距”,它等于被丢弃奇异值的平方和开根号,是判断留几条快速路的标尺。
随机SVD加速
如果城市有几十万条路,完整测绘耗时巨大。聪明交通局的做法是:随机抽查一小批街道的流量,先粗略判断主干道的方向,再沿这个方向精确复测——几轮下来,主干道就清清楚楚了。
随机 SVD 正是这套思路。先用 d×ℓ 的高斯随机矩阵 Ω(ℓ = k + p,p 是过采样列数)和 X 相乘得到草图 Y = XΩ,Y 的列就像“抽查的街道”。对 Y 做 QR 分解得到正交基 Q,Q 张成的子空间大概率覆盖了主要奇异方向。
把 X 投影到 Q 的低维子空间上得到小矩阵 B = QᵀX(只有几十到几百行/列),对它做完整 SVD 代价极小,再回代 U ≈ Q U_B。想要更高精度,可先做 q 次幂迭代:用 (XXᵀ)ᵍ XΩ 代替 XΩ,相当于“沿主干道多复查几次”,让次要方向被进一步压制。
抽查带来了惊人的加速:当矩阵达到 10 万行、几千列时,随机 SVD 可能比完整 SVD 快一个数量级,而精度损失往往在可接受范围——这正是“大数据降维加速”的核心武器。
- 随机草图用高斯随机矩阵 Ω 和 X 相乘,把信息压缩到低维空间;ℓ = k + p 多采几列可提高覆盖率。
- 正交化对 Y 做 QR 分解得到列正交的 Q,Q 的列张成一个靠谱的低维子空间,近似“主干道候选方向”。
- 小矩阵消化在低维空间里算 B = QᵀX 再 SVD,计算量从大矩阵级别降到小矩阵级别。
- 回代还原最后用 U ≈ Q U_B 把左奇异向量“搬回”原空间,全程只在大矩阵上做了两次矩阵乘法。
稳定性计算量对比
修主干道有三套方案:A 案把全市每条路都测量三遍(特征分解 + 构造 XᵀX),B 案直接测绘原始记录(完整 SVD),C 案先抽查再精修(随机 SVD)。方案 A 精度未必更高,成本却更高。
数值上最大的坑是“平方灾难”:构造 XᵀX 时把奇异值平方,条件数从 κ(X) 变成 κ(X)²。条件数是“误差放大的倍数”,它一平方,小奇异值对应的方向精度会急剧劣化——这也是为什么工程上用 SVD 而非特征分解。
计算量方面:显式求 XᵀX 要 O(nd²),特征分解 O(d³);完整 SVD 对 n×d 矩阵是 O(nd²),但直接作用于 X 不产生平方误差;截断 SVD 只要 O(ndk);随机 SVD 约 O(ndℓ + ℓ²d),ℓ 远小于 d 时最快,且稀疏矩阵还能吃满稀疏乘法的红利。
方案 A 看似最“正统”,却最伤数值;工程上默认用完整/截断 SVD 替代协方差特征分解,只有矩阵小到可以挥霍时才用特征分解——这是省钱又安全的修路哲学。
- 条件数定义最大与最小奇异值之比,衡量矩阵“多敏感”;比值越大,微小测量误差被放大得越狠。
- 平方放大构造 XᵀX 后条件数变成平方——原本 10 的敏感度变成 100,数值误差被平方放大。
- 复杂度参照完整 SVD 约 O(nd²),截断 SVD 只乘 k 份约 O(ndk),随机 SVD 用 ℓ=k+p 再省一截,选多保贵。
实战应用选型
小县城几十条路,全量测绘即可;特大城市千万条路,必须抽查法;而景区只要画好 k 条观景主干道,就能让你不走回头路。数据场景不同,选型天差地别。
选型三问:数据规模多大(n、d)?要前 k 个方向还是全部?矩阵稠密还是稀疏?小矩阵(几百×几百)直接用 np.linalg.svd 全量分解;中等矩阵用截断 SVD;超大矩阵(d 或 n 上万)用随机 SVD。
典型场景里:图像压缩把 512×512 图像做截断 SVD,只存 U_k、Σ_k、V_kᵀ,k 取 30~50 时压缩率可达 10~20 倍且肉眼难辨差异;推荐系统把用户-物品评分矩阵做随机 SVD 得到隐向量,等价于矩阵分解;人脸识别中的“特征脸”直接用 PCA 的 V 列构成“基础脸”,任何脸都是它们的线性组合。选 k 统一看方差保留率。
主干道不一定越多越好,够承载九成流量即可。选型口诀:小矩阵全量 SVD,中矩阵截断 SVD,大矩阵随机 SVD——三招吃遍降维场景。
- 方差保留率前 k 个奇异值平方和占全部平方和的比例,相当于“主干网承载了全市百分之多少的流量”。
- 阈值选择通常要求 R_k ≥ 90%,取满足条件的最小 k——流量覆盖够用就好,不贪多。
- 应用落点图像压缩、推荐隐向量、特征脸都套同一个流程:SVD → 取前 k 个 → 投影或重构。
AI 应用场景
图像压缩:把照片当“城市地图”修剪
阶段:数据预处理 / 特征压缩
解决的问题:高分辨率图像存储和传输成本高,传统做法按像素块硬压缩容易产生明显失真。数学上,灰度图就是一个数字矩阵,把它交给截断 SVD,只保留前 k 条“快速路图层”,城市骨架清晰,小巷全部丢弃。
具体案例:一张 512×512 的人像灰度图,做截断 SVD 取 k=40,存储量从 512×512=26 万个数降到 512×40 + 40 + 40×512 约 4 万个数,压缩 6 倍以上,人眼几乎看不出差别。工程上通常配合奇异值衰减曲线快速定 k。
推荐系统隐语义:主干道客流预测小巷流量
阶段:特征工程 / 模型输入
解决的问题:用户-物品评分矩阵动辄几十万行、几万列,稀疏度超 99%,直接计算用户相似度又慢又占内存。随机 SVD 把矩阵分解成“用户隐向量 × 重要性 × 物品隐向量”,内积即可预测未评分项——就像用主干道的客流规律推测小巷的流量。
具体案例:某电商平台 10 万用户 × 5 万商品,评分稀疏度 99.2%,用随机 SVD(k=50,过采样 p=10)做矩阵分解,离线 AUC 提升 3%,训练时间从完整 SVD 的 40 分钟降到 3 分钟。
高维基因数据降维可视化
阶段:数据降维 / 可视化
解决的问题:基因表达矩阵常是 2 万基因 × 几百样本,维度极高且数值动态范围大。若先构造 2 万×2 万的协方差矩阵,内存与数值误差双双爆炸;直接用 SVD 对原始矩阵求主方向,再把样本投影到二维散点图,能直观展示样本聚类。
具体案例:某癌症转录组数据集 18000 基因 × 420 样本,用 PCA(底层 SVD)降到 2 维,正常组与肿瘤组在散点图上明显分成两簇,且比协方差特征分解快 5 倍、结果更稳。
Python 演示
import timeimport numpy as np def pca_via_svd(X, k): Xc = X - X.mean(axis=0) U, S, Vt = np.linalg.svd(Xc, full_matrices=False) Z = Xc @ Vt[:k].T # 主成分得分 Xk = Z @ Vt[:k] # k 维重构 return Z, S[:k], Xk def pca_via_eig(X, k): Xc = X - X.mean(axis=0) C = Xc.T @ Xc / (Xc.shape[0] - 1) vals, vecs = np.linalg.eigh(C) order = np.argsort(vals)[::-1][:k] return Xc @ vecs[:, order] def rsvd(X, k, p=5, q=1): ell = k + p Omega = np.random.randn(X.shape[1], ell) Y = X @ Omega for _ in range(q): Y = X @ (X.T @ Y) # 幂迭代压制小奇异方向 Q, _ = np.linalg.qr(Y) B = Q.T @ X Ub, S, Vt = np.linalg.svd(B, full_matrices=False) return Q @ Ub[:, :k], S[:k], Vt[:k] def main(): rng = np.random.default_rng(2024) X = rng.standard_normal((5000, 600)) Z_svd, S, Xk = pca_via_svd(X, 5) Z_eig = pca_via_eig(X, 5) cos = abs(Z_svd[:, 0] @ Z_eig[:, 0]) cos /= np.linalg.norm(Z_svd[:, 0]) * np.linalg.norm(Z_eig[:, 0]) print("SVD 与特征分解得分余弦相似度:", round(cos, 6)) print("前5个奇异值:", np.round(S[:5], 2)) U, Sr, Vt_r = rsvd(X, 5) err_trunc = np.linalg.norm(X - Xk, ord="fro") err_rsvd = np.linalg.norm(X - (X @ Vt_r.T) @ Vt_r, ord="fro") print("截断SVD 重构误差:", round(err_trunc, 4)) print("随机SVD 重构误差:", round(err_rsvd, 4)) t0 = time.time() pca_via_svd(X, 5) t_svd = time.time() - t0 t0 = time.time() rsvd(X, 5) t_rsvd = time.time() - t0 print("完整SVD 耗时 %.3fs, 随机SVD 耗时 %.3fs" % (t_svd, t_rsvd)) if __name__ == "__main__": main()
U, S, Vt = np.linalg.svd(Xc, full_matrices=False)一步完成 SVD,得到左奇异向量、奇异值和右奇异向量。Z = Xc @ Vt[:k].T用 V 的前 k 列投影,算出主成分得分,即降维结果。C = Xc.T @ Xc / (Xc.shape[0] - 1)显式构造协方差矩阵,演示“平方视角”的路线。Y = X @ Omega随机投影:用高斯矩阵把大矩阵压成小草图。Y = X @ (X.T @ Y)幂迭代:沿主要方向“复查”,进一步压制小奇异方向。Q, _ = np.linalg.qr(Y)对草图做 QR 分解,得到靠谱的低维正交基。B = Q.T @ X把原矩阵投影到低维空间,得到小矩阵,后续 SVD 成本极低。
常见误区
误区“PCA 的标准流程就是先算协方差矩阵 C = XᵀX,再做特征分解;用 SVD 是偷懒的近似,不算正规 PCA。”
正解数学上两者完全等价:XᵀX = VΣ²Vᵀ,特征向量就是 V 的列。但工程上用 SVD 直接分解中心化的 X 更稳更快——构造 XᵀX 会把奇异值平方,条件数变成原来的平方,数值误差被放大。正规做法恰恰是 SVD 优先。
为何常见:教科书多先讲特征分解引入 PCA,SVD 版本放在后面,学习者先入为主,以为只有特征分解才算“正统”。
误区“SVD 分解出 X = UΣVᵀ,那么 U 就是下降维后的坐标,直接用 U 的前几列当特征就行。”
正解降维后的得分是样本在新坐标系里的坐标,等于 X V_k = U_k Σ_k;U 的列是左奇异向量,是 XXᵀ 的特征向量,描述的是“样本与方向的关系”,不是坐标本身。要得到特征必须用 V 去投影:Z = X V_k。
为何常见:SVD 输出三个矩阵,初学者最容易把第一个矩阵 U 当成“主成分”,混淆了变换矩阵与结果坐标。
误区“随机 SVD 名字里带'随机',应该是随机抽样数据,丢掉一部分行再分解,所以精度没有保证。”
正解随机 SVD 没有丢任何数据行,它只用随机矩阵做线性投影,所有样本都参与了计算。随机投影配合 QR 正交化和幂迭代,有理论保证能捕获主要奇异子空间;误差通常只比最优截断 SVD 高一点点,但耗时可能差一个数量级。
为何常见:'随机'二字容易让人联想到随机抽样或 dropout,忽略了它只是“换一种方式压缩维度、再精确还原”。
误区“截断 SVD 压缩矩阵,就是把元素里绝对值小的数清零,省存储。”
正解元素置零和低秩近似是两回事。截断 SVD 是整体丢弃“秩一图层”σ_i u_i v_iᵀ,丢层后矩阵的每个元素都会随之整体调整,但它保证了 Frobenius 范数下的最优重构误差——这是逐元素置零做不到的。
为何常见:“压缩 = 清零”是生活常识带来的直觉,但矩阵的低秩结构与元素大小没有直接关系。
面试题
Q1. 用 SVD 实现 PCA 时,样本在新空间中的主成分得分应如何计算?
- A.取左奇异向量 U 的前 k 列作为得分
- B.取右奇异向量 V 的前 k 列作为得分
- C.用中心化数据乘 V 的前 k 列← 正确答案
- D.用中心化数据乘 U 的前 k 列
答案:C。得分是样本在“主干道方向”上的坐标,方向由 V 的列给出,所以 Z = XV_k。A 的 U 列是 XXᵀ 的特征向量,描述样本与方向的关系而非坐标;B 的 V 列本身只是方向;D 维度对不上且含义错误。
Q2. 中心化后的数据矩阵 X,其 XᵀX 的特征值 λ 与奇异值 σ 的关系是?
- A.λ = σ²← 正确答案
- B.λ = √σ
- C.λ = σ
- D.λ = 1/σ
答案:A。由 XᵀX = VΣ²Vᵀ 可知特征值恰为奇异值平方。这就像“人流宽度”的平方视角:σ 是原始流量,λ 是流量平方后的量。B、C、D 都不满足这个代数推导。
Q3. Eckart–Young 定理说明截断 SVD 的最优性体现在哪里?
- A.重构误差在所有低秩矩阵中最小← 正确答案
- B.计算速度一定快于特征分解
- C.保留的奇异值个数总是越少越好
- D.重构结果一定等于原数据矩阵
答案:A。定理保证:在所有秩不超过 k 的矩阵里,截断 SVD 的 Frobenius 重构误差最小。B 是工程现象不是定理内容;C 违背信息损失权衡;D 与截断含义相反,k<r 时不会完全等于原矩阵。
Q4. 随机 SVD 算法的第一步通常做什么?
- A.用高斯随机矩阵对数据做投影← 正确答案
- B.把数据矩阵的每个元素求倒数
- C.对数据矩阵做完整特征分解
- D.把矩阵转置后再做一次乘法
答案:A。随机 SVD 先做 Y = XΩ 的随机投影,得到“抽查草图”。B 是数值变换但没有意义;C 是完整方法,违背随机加速初衷;D 单独转置不构成算法步骤。
Q5. 为什么工程上更倾向用 SVD 而不是协方差特征分解做 PCA?
- A.因为奇异值分解只适用于稀疏矩阵
- B.因为构造协方差矩阵会平方放大误差← 正确答案
- C.因为特征分解在任何情况下都更慢
- D.因为协方差矩阵多数情况不可对角化
答案:B。构造 XᵀX 会把条件数变成 κ(X)²,数值误差被平方放大;SVD 直接分解原始矩阵更稳。A 错误,SVD 对稠密矩阵同样适用;C 过于绝对;D 错误,实对称协方差矩阵必然可对角化。
Q6. 中心化矩阵 X 做 SVD 得 X=UΣVᵀ,关于 U 的列正确的是?
- A.它们是数据矩阵 XᵀX 的特征向量
- B.它们是矩阵 XXᵀ 的特征向量← 正确答案
- C.它们是协方差矩阵的右奇异向量
- D.它们是主成分得分矩阵的转置
答案:B。由 XXᵀ = UΣ²Uᵀ 可知 U 的列是 XXᵀ 的特征向量。A 中的特征向量是 V 的列;C 中协方差矩阵是 XᵀX(取 X 的右奇异向量);D 的得分是 XV_k = U_kΣ_k,不等于 U 本身。
Q7. 截断 SVD 重构误差 ||X−X_k||_F 的精确表达是?
- A.被丢弃奇异值的平方和再开根号← 正确答案
- B.被保留奇异值的平方和再开根号
- C.最大奇异值减去最小奇异值的差
- D.被保留的奇异值个数 k 的平方根
答案:A。Eckart–Young 定理给出误差 = √(Σ_{i=k+1}^r σ_i²),即“小巷图层”的总能量。B 是保留部分的能量而非误差;C 是奇异值跨度与误差无关;D 只与个数有关,显然不正确。
Q8. 随机 SVD 中提升低秩近似精度的常用技巧有哪些?
- A.增加过采样列数以保证覆盖← 正确答案
- B.做一到两次幂迭代压制小方向← 正确答案
- C.把矩阵元素全部取绝对值参与计算
- D.只保留最大的一个奇异值做近似
答案:AB。过采样(p 更大)提高随机投影覆盖完整子空间的概率;幂迭代 (XXᵀ)ᵍXΩ 让小奇异方向指数衰减,逼近最优。C 是破坏信息的非线性操作;D 等于 k=1 的暴力截断,不是精度技巧。
Q9. 关于 SVD 与 PCA 的等价性,下列说法正确的有?
- A.右奇异向量 V 的列就是主成分方向← 正确答案
- B.奇异值平方等于 XᵀX 的特征值← 正确答案
- C.直接做 SVD 数值上更稳定← 正确答案
- D.左奇异向量 U 就是降维后的得分
答案:ABC。由 XᵀX = VΣ²Vᵀ,V 的列即主方向,σ² 即特征值,故 A、B 正确。构造 XᵀX 使条件数平方放大,因此 C 正确。D 错误:得分是 XV_k = U_kΣ_k,U 本身不是坐标。
Q10. 面对十万行、五千列的大矩阵做 PCA,合理做法有哪些?
- A.用随机 SVD 加速分解过程← 正确答案
- B.用截断 SVD 只求前 k 个方向← 正确答案
- C.显式构造五千乘五千协方差矩阵
- D.用完整 SVD 求出全部奇异向量
答案:AB。超大矩阵下,随机 SVD 与截断 SVD 都能显著降计算量且精度可控。C 的问题在于构造 XᵀX 既费时又放大数值误差,5000×5000 矩阵的特征分解代价高昂;D 求全部奇异向量在 10 万×5000 规模上几乎不可行。