我的部分代码使用numpy.linalg.inv反转矩阵(实际上是一个ndarray)。但是,这经常出错如下:
numpy.linalg.linalg.LinAlgError: Singular matrix
如果矩阵实际上是奇异的,那就没问题了。但事实似乎并非如此。
例如,我在尝试反转矩阵之前打印矩阵。所以在错误发生之前就打印出来了:
[[ 0.76400334 0.22660491]
[ 0.22660491 0.06721147]]
...然后在尝试反转该矩阵时返回上述奇点错误。但据我所知,这个矩阵是可逆的。 Numpy甚至在稍后问到时似乎也同意。
>>> numpy.linalg.inv([[0.76400334, 0.22660491], [0.22660491, 0.06721147]])
array([[ 2.88436275e+07, -9.72469076e+07],
[ -9.72469076e+07, 3.27870046e+08]])
这是确切的代码段:
print np.dot(np.transpose(X), X)
print np.linalg.inv(np.dot(np.transpose(X),X))
第一行打印上面的矩阵;第二行失败了。
那么上述两种行为的区别是什么呢?为什么独立代码即使在我的脚本中出错也能正常工作?
编辑:按照Beauvel上校的要求,如果我这样做try:
print np.dot(np.transpose(X), X)
z = np.linalg.inv(np.dot(np.transpose(X), X))
except:
z = "whoops"
print z
输出
[[ 0.01328185 0.1092696 ]
[ 0.1092696 0.89895982]]
whoops
但是我自己尝试了这个
>>> numpy.linalg.inv([[0.01328185, 0.1092696], [0.1092696, 0.89895982]])
array([[ 2.24677775e+08, -2.73098420e+07],
[ -2.73098420e+07, 3.31954382e+06]])
答案 0 :(得分:2)
这是印刷精度的问题。您最有可能使用的IEEE 754双精度数大约为16位十进制数,您需要写出17 to preserve the binary value。
这是一个小例子。首先创建一个单元矩阵:
In [1]: import numpy as np
In [2]: np.random.seed(0)
In [3]: a, b, c = np.random.rand(3)
In [4]: d = b*c / a
In [5]: X = np.array([[a, b],[c, d]])
打印并尝试将其反转:
In [6]: X
Out[6]:
array([[ 0.5488135 , 0.71518937],
[ 0.60276338, 0.78549444]])
In [7]: np.linalg.inv(X)
LinAlgError: Singular matrix
尝试反转印刷的矩阵:
In [8]: Y = np.array([[ 0.5488135 , 0.71518937],
...: [ 0.60276338, 0.78549444]])
In [9]: np.linalg.inv(Y)
Out[9]:
array([[-85805775.2940297 , 78125795.99532071],
[ 65844615.19517545, -59951242.76033063]])
SUCCES!
提高打印精度,然后重试:
In [10]: np.set_printoptions(precision=17)
In [11]: X
Out[11]:
array([[ 0.54881350392732475, 0.71518936637241948],
[ 0.60276337607164387, 0.78549444195576024]])
In [12]: Z = np.array([[ 0.54881350392732475, 0.71518936637241948],
...: [ 0.60276337607164387, 0.78549444195576024]])
In [13]: np.linalg.inv(Z)
LinAlgError: Singular matrix
答案 1 :(得分:1)
我只计算行列式:
In [130]: m = np.array([[ 0.76400334, 0.22660491],[ 0.22660491,0.06721147]])
In [131]: np.linalg.det(m)
Out[131]: 2.3302017068132921e-09
# which is in fact for a 2D matrix 0.76400334*0.06721147 - 0.22660491*0.22660491
已经退出0
附近。
如果可以反转矩阵m
,则可以在数学上计算伴随并除以行列式以得到反转矩阵。
在数值上,如果行列式太小,这可能会导致您遇到的那种错误......