因为矩阵行列式为0,没有数学意义上的逆矩阵,NumPy拒绝计算——这不是bug而是正确行为;常见于特征重复、列线性相关、欠定系统或条件数过大(>1e16)导致数值不稳定。

为什么 numpy.linalg.inv() 会报 LinAlgError: Singular matrix
因为矩阵行列式为 0,没有数学意义上的逆矩阵。NumPy 拒绝计算——这不是 bug,是正确行为。常见于:特征向量重复、数据列完全线性相关(比如两列一模一样)、欠定系统(行数
用 numpy.linalg.pinv() 替代求“伪逆”
当你要的是最小二乘解(比如做线性回归、求解 Ax = b),pinv() 是最直接的替代方案。它基于 SVD,对奇异/非方阵都安全:
import numpy as np A = np.array([[1, 2], [2, 4]]) # 显然奇异(第二行是第一行的2倍) A_pinv = np.linalg.pinv(A) # 不报错,返回 Moore-Penrose 伪逆 x = A_pinv @ np.array([3, 6]) # 解出一个最小范数解
-
pinv()默认使用rcond=1e-15判定奇异值是否截断;若数值噪声大,可适当调高(如rcond=1e-10) - 结果不满足
A_pinv @ A == I,但满足A @ A_pinv @ A == A等伪逆性质 - 比
inv()慢,尤其对大矩阵;SVD 开销不可忽略
检查秩和条件数,提前预警
别等 inv() 崩溃才处理。先用 np.linalg.matrix_rank() 和 np.linalg.cond() 评估矩阵健康度:
A = np.random.randn(100, 100)
A[:, 0] = A[:, 1] # 强制一列冗余
print("Rank:", np.linalg.matrix_rank(A)) # 输出 99,而非 100
print("Cond:", np.linalg.cond(A)) # 可能 > 1e16,说明病态- 秩
- 条件数 > 1e12 通常意味着数值不稳定,即使
inv()不报错,结果也可能严重失真 - 注意:
matrix_rank()默认用tol=None,对浮点误差敏感;必要时传入显式tol
从源头避免构造奇异矩阵
很多奇异问题来自数据或建模方式本身,不是 NumPy 的锅:
立即学习“Python免费学习笔记(深入)”;
- 做多元线性回归前,用
np.corrcoef(X.T)查看特征间相关性,剔除高度共线的列 - PCA 或
sklearn.decomposition.TruncatedSVD降维后再构建设计矩阵 - 正则化:在求解时改用
np.linalg.solve(A.T @ A + λ * np.eye(n), A.T @ b)(岭回归形式),λ > 0 强制可逆 - 用
scipy.linalg.pinv2()(基于 SVD)或scipy.linalg.lstsq()(更稳定地解最小二乘)替代手写伪逆
真正棘手的不是怎么绕过错误,而是判断当前场景下“伪逆”是否语义合理——比如在求协方差矩阵逆用于马氏距离时,强行用 pinv() 可能掩盖特征工程缺陷。


















