Python numpy总是得到复数的特征值和错误的特征向量

Python numpy总是得到复数的特征值和错误的特征向量,python,numpy,Python,Numpy,我正在用numpy做简单的线性代数运算。到目前为止,一切都非常好,当我取一些简单的2x2矩阵,它们的特征值和向量我都知道,然后用它们测试numpy 例如,在下面的示例矩阵中,存在单个特征值e=1和单个相关特征向量[-3,1]: A = np.array([[-2, -9], [ 1, 4]]) vals, vects = np.linalg.eig(A) vals2, vects2 = np.linalg.eigh(A) vals3 = np.linalg.ei

我正在用numpy做简单的线性代数运算。到目前为止,一切都非常好,当我取一些简单的2x2矩阵,它们的特征值和向量我都知道,然后用它们测试numpy

例如,在下面的示例矩阵中,存在单个特征值e=1和单个相关特征向量[-3,1]:

A = np.array([[-2, -9],
              [ 1,  4]])


vals, vects = np.linalg.eig(A)
vals2, vects2 = np.linalg.eigh(A)
vals3 = np.linalg.eigvals(A)

print("Eigenvalues (linalg.eig): \n", vals)
print("Eigenvalues (linalg.eigvals): \n", vals3)
print("Eigenvectors: \n", vects)
结果如下:

Eigenvalues (linalg.eig):
 [1.+1.89953279e-08j 1.-1.89953279e-08j]

Eigenvalues (linalg.eigvals):
  [1.+1.89953279e-08j 1.-1.89953279e-08j]

Eigenvectors:
 [[ 0.9486833 +0.00000000e+00j  0.9486833 -0.00000000e+00j]
 [-0.31622777-2.00228337e-09j -0.31622777+2.00228337e-09j]] 
我知道特征向量是列格式的。如果忽略小的虚部,两个向量几乎都是单个正确特征向量的标量倍数

我的矩阵不是对称的或共轭对称的,因此
linalg.eigh
不应该工作,但我还是尝试了。它给了我真实的价值,但它们完全是假的

我还搜索了其他类似的问题,没有找到令人满意的答案。我得到的最接近的答案是一个建议写一个函数来去除它们的小虚部的特征值的答案。这是可行的,但仍然会留下不正确的特征向量

这是怎么回事?我如何简单地修复它?编写自己的函数来修正这样一个完善的库,以使其得到正确的简单计算,这似乎有点过分。

Numpy为每个特征值返回一个标准化的特征向量;因为这里的特征值有重数2,它返回相同的特征向量两次。如果关闭,您可以使用
np.real\u重新转换为real:

In [156]: A = np.array([[-2, -9],
     ...:               [ 1,  4]])
     ...: 
     ...: w, v = np.linalg.eig(A)
     ...: v = np.real_if_close(v, tol=1)
     ...: v
Out[156]: 
array([[ 0.9486833 ,  0.9486833 ],
       [-0.31622777, -0.31622777]])
健全性检查:

In [157]: v * 10**.5
Out[157]: 
array([[ 3.,  3.],
       [-1., -1.]])
如果您想要精确的解决方案,而不是那些容易发生机器错误的解决方案,我建议您使用
sympy

In [159]: from sympy import Matrix
     ...: m = Matrix(A)
     ...: m.eigenvects()
Out[159]: 
[(1,
  2,
  [Matrix([
   [-3],
   [ 1]])])]

这里我们得到了特征值
1
,它的多重性
2
,以及与之相关的特征向量。

这里你注意到的是相对近似误差

Numpy并不是精确地计算特征值和特征向量,而是利用强大的优化数值算法,结果不是精确的答案,而是非常接近的答案。对于这些应用程序,它使用的是较旧的LAPACK库
dggev


如果你正在寻找一个确切的答案,那么Numpy不是你的解决方案。相反,请看一看Sympy。这里也讨论了一个类似的问题:

快速子问题。。。Sympy的文档似乎都是教程。在哪里可以找到带有参数和返回类型的类和方法的实际文档?例如,在您的答案中,
Out[159]
是一个非常复杂的返回值。具有示例和适当的文档。