Numpy计算特征向量是不正确的

时间:2017-09-15 20:31:09

标签: python numpy scipy sympy

我在Python中运行以下内容并期望E [1]中的列是A的特征向量,但它们不是。只有Sympy.Matrix.eigenvects()似乎做得对。为什么会出现这个错误?

{{1}}

2 个答案:

答案 0 :(得分:5)

  • 特征向量是正确的,在预期的误差范围内。
  • 你发现用元素划分测试特征向量是一个坏主意。

更好的方法是计算matrix*vectoreigenvalue*vector之间差异的范数。

NumPy在浮点算术中执行计算,限制为52位精度(双精度)。这意味着它的任何答案都可能包含数字误差,至少相对大小为2 **( - 52),大约为2e-16。所以,当你看到一个像2e-16这样的数字来自一个数字大小为1-3的计算时,结论是:“这个数字应该可能为零,而我们所拥有的数值可能只是噪音”。如果你除以那个数字,就会得到噪音。

另一方面,SymPy执行符号操作,因此它的答案(当它可以得到一个时)正是理论所预测的。

答案 1 :(得分:1)

来自其文档:

  

如果存在向量v使得点(a,v)= w * v,则数w是a的特征值。因此,数组a,w和v满足等式dot(a [:,]: ],v [:,i])= w [i] * v [:,i] for i \ in {0,...,M-1}。

使用矩阵:

In [1]: A = np.array([[-3,  3,  2],
   ...:         [ 1, -1, -2],
   ...:         [-1, -3,  0]])
   ...:         
In [2]: w,v=np.linalg.eig(A)
In [3]: w
Out[3]: array([ 2., -4., -2.])
In [4]: v
Out[4]: 
array([[ -9.39932874e-17,   9.48683298e-01,   8.94427191e-01],
       [  5.54700196e-01,  -3.16227766e-01,   1.93473310e-16],
       [ -8.32050294e-01,  -4.08811066e-17,   4.47213595e-01]])
In [5]: np.dot(A,v)
Out[5]: 
array([[ -2.22044605e-16,  -3.79473319e+00,  -1.78885438e+00],
       [  1.10940039e+00,   1.26491106e+00,  -7.77156117e-16],
       [ -1.66410059e+00,   4.44089210e-16,  -8.94427191e-01]])
In [6]: w*v
Out[6]: 
array([[ -1.87986575e-16,  -3.79473319e+00,  -1.78885438e+00],
       [  1.10940039e+00,   1.26491106e+00,  -3.86946619e-16],
       [ -1.66410059e+00,   1.63524427e-16,  -8.94427191e-01]])
In [7]: np.dot(A,v)-w*v
Out[7]: 
array([[ -3.40580301e-17,   8.88178420e-16,   2.22044605e-16],
       [  8.88178420e-16,  -6.66133815e-16,  -3.90209498e-16],
       [ -2.22044605e-16,   2.80564783e-16,  -3.33066907e-16]])
In [8]: np.allclose(np.dot(A,v), w*v)
Out[8]: True

所以,是的,记录的测试在浮点范围内得到满足。

einsum可用于在i计算中突出显示dot轴。

In [10]: np.einsum('...k,ki->...i',A,v)
Out[10]: 
array([[ -2.22044605e-16,  -3.79473319e+00,  -1.78885438e+00],
       [  1.10940039e+00,   1.26491106e+00,  -7.77156117e-16],
       [ -1.66410059e+00,   3.88578059e-16,  -8.94427191e-01]])

当我除以v(元素方式)时,结果与特征值匹配,2 -4,-2,除了vdot几乎为0(1e-) 16或更小)。

In [11]: np.einsum('...k,ki->...i',A,v)/v
Out[11]: 
array([[ 2.36234534, -4.        , -2.        ],
       [ 2.        , -4.        , -4.01686475],
       [ 2.        , -9.50507681, -2.        ]])