You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Numpy求奇异矩阵逆时不报错?探究其判定逻辑

关于Numpy处理奇异矩阵求逆的行为解析

核心问题原因

1. 奇异矩阵调用np.linalg.inv()不抛出异常

Numpy的np.linalg.inv()底层依赖LAPACK库的LU分解实现,它不是通过数学上的严格奇异性判断,而是基于数值精度下的主元阈值检测:

  • 当矩阵进行LU分解时,若某个主元的绝对值小于eps * max(abs(A))(eps为机器浮点精度,约1e-16),才会判定矩阵奇异并抛出异常。
  • 你生成的低秩协方差矩阵,虽然数学上是奇异的,但由于浮点数运算的舍入误差,分解出的主元可能并未低于这个阈值,因此不会触发异常。

2. 返回矩阵并非原矩阵的逆

这种情况下np.linalg.inv()返回的是数值近似的“伪逆”(但不是严格的Moore-Penrose伪逆),本质是LU分解在主元未达奇异阈值时强行计算出的结果。由于原矩阵数学上不可逆,这个结果自然无法满足A @ inv(A) = I的严格逆矩阵条件。

Numpy判定奇异性的逻辑:不止依赖条件数

条件数是衡量矩阵接近奇异程度的指标,但Numpy的奇异性检测直接基于LU分解的主元大小,而非条件数:

  • 条件数是max奇异值 / min奇异值,属于全局指标,无法反映分解过程中单个主元的数值情况。
  • 你的测试案例中,两个矩阵条件数接近,但第二个矩阵的主元在浮点精度下更接近0,触发了LAPACK的奇异检测阈值,因此调用inv()时抛出异常;而第一个矩阵的主元刚好高于阈值,所以能完成计算。

代码验证解析

案例1:奇异协方差矩阵求逆无报错

import numpy as np
from scipy.stats import ortho_group

def generate_random_cov_matrix(sz, rank, eig_val_scale):
    """
    生成指定秩的随机协方差矩阵,基于特征向量和特征值构造
    :param sz: 矩阵维度 sz x sz
    :param rank: 矩阵的秩
    :param eig_val_scale: 特征值的缩放系数(基于卡方分布采样)
    :return: 协方差矩阵、特征向量、特征值
    """
    if rank > sz:
        raise ValueError('秩不能大于矩阵维度')

    eig_vecs = ortho_group.rvs(dim=sz)
    eig_vecs = eig_vecs[:, 0:rank]
    eig_vals = np.random.chisquare(1, rank) * eig_val_scale
    eig_vals = np.sort(eig_vals)[::-1]
    cov = eig_vecs @ np.diag(eig_vals) @ eig_vecs.T
    return cov, eig_vecs, eig_vals


n_variables = 20
rank = 10
cov_mat,_,_ = generate_random_cov_matrix(n_variables,rank,100)

assert np.isclose(np.linalg.det(cov_mat),[0.])

print(np.mean(cov_mat))

try:
    cov_inv = np.linalg.inv(cov_mat)
    print('No exception was raised')
except:
    print('An exception was raised')

try:
    assert np.isclose(cov_mat @ cov_inv,np.identity(n_variables))
except AssertionError:
    print('The computed inverse is not a proper inverse')

这段代码生成的低秩协方差矩阵,虽然行列式为0(数学奇异),但浮点数值下的LU分解主元未达奇异阈值,因此inv()不报错,返回的结果也不满足逆矩阵的严格条件。

案例2:条件数相同但奇异性判定结果不同

# 运行无报错
arr = np.array([[1.0, 1.2], [2.0 + 1e-14, 2.4 + 1e-14]])
rank = np.linalg.matrix_rank(arr)
cond = np.linalg.cond(arr)
np.linalg.inv(arr)
print("rank: ", rank)
print("cond: ", cond)

# 条件数相同但求逆失败
arr = np.array([[1.0, 1.2], [2.0 + 1e-15, 2.4 + 1e-15]])
rank = np.linalg.matrix_rank(arr)
np.testing.assert_approx_equal(cond, np.linalg.cond(arr))
cond = np.linalg.cond(arr)
print("rank: ", rank)
print("cond: ", cond)
np.linalg.inv(arr)

两个矩阵的条件数接近,但第二个矩阵的LU分解主元更接近机器精度阈值,因此被判定为奇异,触发异常;第一个矩阵的主元刚好高于阈值,因此能完成计算。这说明Numpy的奇异性检测是基于分解过程中的主元数值,而非条件数。

内容的提问来源于stack exchange,提问作者Harry Matthews

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 07:37:48