numpy.linalg.svd 必须传入二维数组,一维数组需先用 reshape 或 atleast_2d 升维;设 full_matrices=false 可节省内存,降维时取前 k 项并用 np.diag(s[:k]) 重构,避免维度错误。

numpy.linalg.svd 函数怎么调用才不报错?
直接调用 numpy.linalg.svd 时最常见的错误是传入非二维数组,比如一维 array 或三维张量。SVD 只接受 shape 为 (m, n) 的矩阵,哪怕 m=1 或 n=1 也必须显式 reshape。
- 正确做法:用
arr.reshape(-1, arr.shape[-1])或np.atleast_2d(arr)强制转为二维(注意后者对列向量会变成(1, n),可能不符合预期) - 常见陷阱:读取 CSV 后用
pandas.DataFrame.values得到的是二维,但用df['col'].values是一维,直接喂给svd就会报LinAlgError: SVD did not converge - 如果数据含
NaN或inf,svd会静默返回异常结果(如全零的Vh),务必先用np.isnan()和np.isfinite()检查
full_matrices=False 什么时候必须设?
默认 full_matrices=True 返回的 U 和 Vh 是方阵((m,m) 和 (n,n)),但实际多数场景只需要“经济型”分解——尤其当 m ≫ n(比如 10000×100 的用户-商品矩阵),生成超大 U 会爆内存。
- 降维/推荐系统常用:设
full_matrices=False,得到U形状为(m, k),Vh为(k, n),其中k = min(m, n) - 若后续要重构原矩阵,两种模式都能用
U @ np.diag(s) @ Vh,但经济型更省空间、更快 - 注意:
s总是 1D 数组,长度等于min(m, n),和full_matrices无关
如何用 SVD 做最简降维(比如降到 k 维)?
不是所有奇异值都同等重要——前几个大的 s[0], s[1], ... 承载主要信息,截断小的能压缩并去噪。
- 取前
k个奇异值:U_k = U[:, :k],s_k = s[:k],Vh_k = Vh[:k, :] - 重构近似矩阵:
U_k @ np.diag(s_k) @ Vh_k(注意别漏掉np.diag(),直接乘会广播出错) - 验证误差:用
np.linalg.norm(original - approx, 'fro')看 Frobenius 范数,通常k=50对 1000×1000 矩阵就能压到误差 - 别用
np.linalg.matrix_rank估算k——它依赖默认容差,而 SVD 截断应基于s的衰减曲线人工判断
为什么 svd 结果里 V 是 Vh(共轭转置)?
NumPy 返回的是 Vh(即 V.T.conj()),不是数学教材里常写的 V。这是为了和 LAPACK 接口一致,但容易在手动验证时搞反。
- 验证是否正确:检查
U @ np.diag(s) @ Vh是否接近原矩阵,而不是U @ np.diag(s) @ V.T - 如果需要真正的
V(比如做主成分分析时要取列向量),用V = Vh.T.conj();实数矩阵可简化为V = Vh.T - 特别注意:PCA 中的“主成分”是
Vh的行(不是V的列),因为X ≈ U @ diag(s) @ Vh,所以Vh[i]就是第 i 个主方向
真正麻烦的不是调用函数,而是理解 U、s、Vh 各自的形状含义和物理意义——尤其是 Vh 的行对应特征方向这点,被文档一笔带过,但写错一次就得重跑整个流程。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











