numpy.linalg.inv不能用于奇异矩阵,因其数学上无逆(行列式为0),会抛出linalgerror;近似奇异矩阵(条件数>1e15)亦导致数值失真。

为什么 numpy.linalg.inv 不能直接用于奇异矩阵
因为矩阵不可逆时,numpy.linalg.inv 会抛出 LinAlgError: Singular matrix。这不是 bug,而是数学限制——行列式为 0 的矩阵没有严格意义上的逆矩阵。实际中遇到的“近似奇异”(如条件数 > 1e15)也容易导致结果数值失真,比如解 np.linalg.solve(A, b) 出现巨大误差或符号翻转。
实操建议:
- 先用
np.linalg.cond(A)检查条件数,> 1e12 就该警惕 - 避免对
A.T @ A这类显式构造的 Gram 矩阵直接求逆(易放大误差),改用np.linalg.lstsq或scipy.linalg.solve_triangular - 若必须用逆,优先用
np.linalg.pinv(A)(Moore–Penrose 伪逆),它对奇异/欠定/超定系统都稳定
用 np.linalg.solve 替代 inv + dot 更快更准
很多人写 np.linalg.inv(A) @ b 解 Ax = b,但这是低效且危险的做法:既多算了一次逆(O(n³)),又引入额外舍入误差。NumPy 内部对 solve 做了专门优化,底层调用 LAPACK 的 dgesv,直接分解+回代。
实操建议:
- 永远优先写
x = np.linalg.solve(A, b),而不是x = np.linalg.inv(A) @ b -
A必须是方阵、非奇异;b可以是 1D 向量或 2D 列向量,solve自动广播 - 如果
A是对称正定,用np.linalg.cholesky+solve分两步,速度提升约 2×
当矩阵不是方阵时,该用 np.linalg.lstsq 还是 np.linalg.pinv
非方阵没有传统逆,但常需最小二乘解:min ||Ax - b||²。两者都能算,但行为不同:lstsq 默认返回最小范数解(对欠定系统),并附带残差、秩、奇异值信息;pinv 总是返回 Moore–Penrose 解,但不反馈数值稳定性线索。
实操建议:
- 调试阶段用
np.linalg.lstsq(A, b, rcond=None),检查返回的rank和s(奇异值数组),判断是否病态 - 生产代码中若已知
A秩满且稳定,可用np.linalg.pinv(A) @ b,但务必设rcond(如rcond=1e-10)来截断小奇异值 - 不要对
A手动拼接单位阵再调用inv——那是教科书陷阱,数值上极不稳定
在 PyTorch/TensorFlow 中复用 NumPy 的逆逻辑要注意什么
PyTorch 的 torch.inverse 和 TensorFlow 的 tf.linalg.inv 行为与 NumPy 高度一致,但关键差异在于设备和梯度:NumPy 运算不支持 GPU 和自动微分,而深度学习框架中的逆操作默认可导(除非显式 .detach())。这意味着在训练循环里误用 np.linalg.inv 会导致梯度断裂。
实操建议:
- 模型前向中一律用框架原生函数:
torch.inverse(A)或tf.linalg.inv(A),别混用 NumPy - 预处理阶段(如数据归一化矩阵计算)可用 NumPy,但结果要转成对应框架张量:
torch.tensor(np.linalg.inv(A), dtype=torch.float32) - 注意 PyTorch 的
inverse对 batch 维度不友好(需循环或改用torch.linalg.inv,v1.9+)
数值稳定性永远比代码行数重要。哪怕只多写一行 np.linalg.cond(A),也可能帮你避开凌晨三点的 NaN 调试。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











