奇异矩阵的高效和pythonic检查

Dr.*_*rew 23 python numpy linear-algebra

在这里研究一些矩阵代数.有时我需要反转可能是单数或病态的矩阵.我知道简单地执行此操作是pythonic:

try:
    i = linalg.inv(x)
except LinAlgErr as err:
    #handle it
Run Code Online (Sandbox Code Playgroud)

但我不确定它的效率如何.这会不会更好?

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it
Run Code Online (Sandbox Code Playgroud)

numpy.linalg只是简单地执行我禁止的测试吗?

Dav*_*veP 15

你的第一个解决方案就是你的矩阵是如此奇特以至于numpy根本无法应对的情况 - 可能是极端的情况.你的第二个解决方案更好,因为它捕获了numpy给出答案的情况,但是答案可能因舍入错误而被破坏 - 这似乎更明智.

如果您试图反转病态矩阵,那么您应该考虑使用奇异值分解.如果小心使用,它可以在其他例程失败时为您提供合理的答案.

如果您不想要SVD,那么另请参阅我关于使用lu_factor而不是inv的评论.


Dr.*_*rew 12

所以基于这里的输入,我用显式测试作为解决方案标记我的原始代码块:

if linalg.cond(x) < 1/sys.float_info.epsilon:
    i = linalg.inv(x)
else:
    #handle it
Run Code Online (Sandbox Code Playgroud)

令人惊讶的是,numpy.linalg.inv函数不执行此测试.我检查了代码,发现它经历了所有的阴谋,然后只是调用lapack例程 - 看起来非常低效.此外,我还要提到DaveP提出的观点:除非明确需要,否则不应计算矩阵的逆矩阵.

  • 您应该将epsilon用于数组本身的dtype,即“ np.finfo(x.dtype).eps”,它可能与“ sys.float_info.epsilon”不同 (2认同)

Nic*_*bey 5

您应该计算矩阵的条件数以查看它是否可逆。

import numpy.linalg

if numpy.isfinite(numpy.linalg.cond(A)):
    B = numpy.linalg.inv(A)
else:
    # handle it
Run Code Online (Sandbox Code Playgroud)

  • 当条件数接近 1/epsilon 时,矩阵将是病态的。因此,问题中提出的第二个解决方案比您的解决方案更好,后者只能捕获非常大的条件数。 (3认同)