Numpy特征向量计算错误

3

我正在使用numpy获取矩阵的特征值/特征向量。我的矩阵是对称且正定的。

> mat

  matrix([[ 1.,  1.,  0.,  0.,  0.,  0.,  0.],
          [ 1.,  2.,  0.,  0.,  0.,  0.,  0.],
          [ 0.,  0.,  1.,  0.,  0.,  0.,  0.],
          [ 0.,  0.,  0.,  2.,  1.,  1.,  0.],
          [ 0.,  0.,  0.,  1.,  2.,  1.,  0.],
          [ 0.,  0.,  0.,  1.,  1.,  1.,  0.],
          [ 0.,  0.,  0.,  0.,  0.,  0.,  1.]])

我使用np.eigh,因为我的矩阵是对称的。

> import numpy.linalg as la
> la.eigh(mat)

  (array([ 0.27,  0.38,  1.  ,  1.  ,  1.  ,  2.62,  3.73]),
   matrix([[ 0.  , -0.85, -0.  ,  0.  ,  0.  ,  0.53,  0.  ],
          [ 0.  ,  0.53, -0.  ,  0.  ,  0.  ,  0.85,  0.  ],
          [ 0.  ,  0.  , -0.  ,  1.  ,  0.  ,  0.  ,  0.  ],
          [-0.33, -0.  , -0.71, -0.  , -0.  , -0.  , -0.63],
          [-0.33, -0.  ,  0.71, -0.  , -0.  , -0.  , -0.63],
          [ 0.89, -0.  , -0.  , -0.  , -0.  , -0.  , -0.46],
          [-0.  , -0.  , -0.  , -0.  ,  1.  , -0.  , -0.  ]]))

我的问题是很多这些值的符号都是错误的。特别是,主特征向量(矩阵中最右边的列)全是负数,但它应该是正数。我已经用matlab和octave进行了检查。这只是一个精度误差,还是我漏了什么?
如果这是一个错误,有没有办法检测并纠正这种错误?
编辑:这个计算是Hubs and Authorities的一部分,上面的矩阵是A*A^T。这是原始论文(见第9页、第10页)的结果,枢纽得分收敛于A*A^T的主特征向量。最终,我们想要将这些枢纽得分相互比较,因此符号实际上很重要。
在第10页,论文还说:“另外(作为推论),如果M只有非负条目,则M的主特征向量只有非负条目。”这就是我提出这个问题的原因。

3
结果是正确的。特征向量的符号未定义,并且是任意的。 - pv.
这两个参考资料都没有违背特征向量的符号未定义这一事实。当然,如果您的问题需要,您可以修复相位约定,但通常不这样做(因为问题各不相同)。 - pv.
2个回答

9

特征向量的符号是任意的。据我所知,这方面没有正确或错误的答案。


谢谢,迈克。我实际上关心特征向量的符号 - 我编辑了我的原始问题。 - mayhewsw
1
看起来作者有些马虎。他本应该说,“此外(作为推论),如果M只有非负元素,则存在一个主特征向量,其只有非负元素。”(或者用更清晰的措辞),这才是Perron-Frobenius定理实际上所说的内容。 - Mike Graham
1
为了得到所需的符号,可以随意翻转整个向量上的符号。 - Mike Graham
是的,Perron-Frobenius定理正是我也在研究的内容。显然,论文中描述的迭代方法只能得到非负结果,但这并不是普遍适用的。我的问题现在是,我能否确定主特征向量的所有元素都具有相同的符号?这更多涉及数学而非numpy。 - mayhewsw
类似于 eigvals,eigvecs = la.eigh(mat) principal = eigvecs [:,eigvals.argmax()] if(principal> = 0).all()or(pricipal <= 0).all():print' all the same'?(未运行/测试/等。还可能遇到 -0.000000000218 应被视为0的数值问题。最好一开始就检查 mat)。 - Mike Graham

1

如果你利用MM == QQ*DD*QQ.T,其中DD=diag([lam_1, lam2_,...])是一个对角线上有特征值的矩阵,而QQ是特征向量矩阵,你可以轻松地检查对称矩阵MM的特征分解是否正确。

lam,QQ = la.eigh(MM)

# Check result:
DD = np.diag(lam)
MM2 = np.dot(np.dot(QQ, DD), QQ.T)
print(MM-MM2)  # should be zero

在您的情况下,正确的是14位数字。

请注意,特征向量可以乘以任何常数,因为特征值的定义方程为MM*x == lambda*x <=> MM*(c*x) == lambda *(c*x),其中c是任何非零常数。 c取决于数值 - Numpy将向量归一化为1。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接