numpy.linalg.inv()是否给出正确的矩阵逆?编辑:为什么inv()会给出数字错误?

Sha*_*ang 6 python numpy matrix matrix-inverse

我的矩阵形状为(4000,4000),我想求逆。(我对倒置矩阵的直觉分解成这么大的矩阵。)

起始矩阵的大小为e-10,具有以下值:print matrix提供输出

[[  2.19885119e-10   2.16462810e-10   2.13062782e-10 ...,  -2.16462810e-10
   -2.19885119e-10  -2.16462810e-10]
 [  2.16462810e-10   2.19885119e-10   2.16462810e-10 ...,  -2.13062782e-10
   -2.16462810e-10  -2.19885119e-10]
 [  2.13062782e-10   2.16462810e-10   2.19885119e-10 ...,  -2.16462810e-10
   -2.13062782e-10  -2.16462810e-10]
 ..., 
 [ -2.16462810e-10  -2.13062782e-10  -2.16462810e-10 ...,   2.19885119e-10
    2.16462810e-10   2.13062782e-10]
 [ -2.19885119e-10  -2.16462810e-10  -2.13062782e-10 ...,   2.16462810e-10
    2.19885119e-10   2.16462810e-10]
 [ -2.16462810e-10  -2.19885119e-10  -2.16462810e-10 ...,   2.13062782e-10
    2.16462810e-10   2.19885119e-10]]
Run Code Online (Sandbox Code Playgroud)

然后,我使用NumPy的numpy.linalg.inv()反转矩阵。

import numpy as np
new_matrix = np.linalg.inv(matrix)
print new_matrix
Run Code Online (Sandbox Code Playgroud)

这是我得到的输出:

[[  1.95176541e+25   9.66643852e+23  -1.22660930e+25 ...,  -1.96621184e+25
   -9.41413909e+24   1.33500310e+25]
 [  2.01500967e+25   1.08946558e+24  -1.25813014e+25 ...,  -2.07717912e+25
   -9.86804459e+24   1.42950556e+25]
 [  3.55575106e+25   2.11333704e+24  -2.25333936e+25 ...,  -3.68616202e+25
   -1.72651875e+25   2.51239524e+25]
 ..., 
 [  3.07255588e+25   1.61759838e+24  -1.95678425e+25 ...,  -3.15440712e+25
   -1.47472306e+25   2.13570651e+25]
 [ -7.24380790e+24  -8.63730581e+23   4.90519245e+24 ...,   8.30663797e+24
    3.70858694e+24  -5.32291734e+24]
 [ -1.95760004e+25  -1.12341031e+24   1.23820305e+25 ...,   2.01608416e+25
    9.40221886e+24  -1.37605863e+25]]
Run Code Online (Sandbox Code Playgroud)

那是巨大的差异!怎么可能 量级矩阵e-10反转为量级矩阵e+25

这在数学上是正确的,还是IEEE浮点值被破坏了?

如果这在数学上是正确的,那么有人可以向我解释其背后的数学直觉吗?

编辑:

根据以下评论,我决定进行测试。

np.dot(matrix, new_matrix) 应该给出单位矩阵A * A ^ T = Identity。

这是我的输出:

[[  0.   -3.  -16.  ...,  16.    8.   12. ]
 [-24.   -1.5  -8.  ...,  32.   -4.   36. ]
 [ 40.    1.  -64.  ...,  24.   20.   24. ]
 ..., 
 [ 32.   -0.5  48.  ..., -16.  -20.   16. ]
 [ 40.    7.   16.  ..., -48.  -36.  -28. ]
 [ 16.    3.   12.  ..., -80.   16.    0. ]]
Run Code Online (Sandbox Code Playgroud)

为什么会numpy.linalg.inv()导致数字错误?

np.allclose( np.dot(matrix, new_matrix), np.identity(4000) )
Run Code Online (Sandbox Code Playgroud)

False

rth*_*rth 5

您的矩阵是病态的,因为

np.linalg.cond(matrix) > np.finfo(matrix.dtype).eps
Run Code Online (Sandbox Code Playgroud)

根据此答案,您可以考虑使用奇异值分解对此类矩阵求逆。

  • 对于数组的dtype,它应该取决于epsilon(即np.finfo(matrix).eps),它可能与sys.float_info.epsilon不同。 (2认同)

gg3*_*349 1

对于两个矩阵的行列式,你有

det(A) * det(A^{-1}) = 1
Run Code Online (Sandbox Code Playgroud)

因此,如果det(A)大,则det(A^{-1})小。对于两个矩阵的范数(如果您选择次乘范数),您

1  =  |A*A^{-1}| >= |A| |A^-1|
Run Code Online (Sandbox Code Playgroud)

哪里 || 是次乘范数的合理选择。在这里,您可以直观地了解所观察到的数字:如果 >= 符号实际上是 ~=,您将恢复与行列式完全正确的相同观察结果。

如果您考虑产品,同样的推理也适用

A * A^{-1} = 1
Run Code Online (Sandbox Code Playgroud)

A对于所有正元素的矩阵。对于 RHS 对角线上的元素,如果 的元素很大,1则需要非常小的数字。A^{-1}A

PS:但请注意,这并不能证明这种趋势总是成立。这只是提供了为什么你会观察到这种缩放的数学直觉。

编辑,回复评论:

最初的问题是“如果这在数学上是正确的,有人可以向我解释这背后的数学直觉吗?”。事实上,给定一个具有较小数字的矩阵,其逆矩阵将具有较大的数字,这在数学上是正确且合理的。上面我解释了为什么会出现这种情况。

回答OP编辑中出现的另一个问题,这就是为什么inv()会导致数值错误:矩阵求逆是一个难题。这就是为什么我们尽可能避免颠倒它们。例如,对于问题

A x = b
Run Code Online (Sandbox Code Playgroud)

我们不计算 的逆A,而是使用其他算法(例如,在实践中,您可以在 python 中调用scipy.linalg.solve)。

  • 查看什么是预处理器[此处](https://en.wikipedia.org/wiki/Preconditioner)。我建议不要反转矩阵,具体取决于您要解决的问题。 (3认同)