scipy.linalg.eig是否提供正确的左特征向量?

4
我有一个问题,关于scipy.linalg.eig如何计算左右特征向量。也许我误解了一切,但事情似乎对我来说不太对...

从一开始。为了获得特征值和两个特征向量,我使用了以下方法:

ev,left_v,right_v = scipy.linalg.eig(A,left = True)

根据手册,在调用函数时设置left=True后,我应该期望得到左特征向量作为left_v的列,其中第i列是第i个特征值的左特征向量。然而,结果并不是我预期的,所以我进行了简单的检查。

我两次调用该函数来计算右特征向量和左特征向量(详情请见这里):

right_ev, right_v_2 = scipy.linalg.eig(A)
left_ev, left_v_2 = scipy.linalg.eig(A.T)

left_v_2的列是与left_ev中相应值相关联的特征向量。 需要强调的是,right_ev_2left_ev_2都给出了相同的特征值,但它们的顺序不同,这需要加以考虑。

left_evleft_ev_2(根据特征值重新排序后)进行比较,可以快速发现前者是后者的共轭,因此使用scipy.linalg.eigleft=True得到的left_ev不是有效的左特征向量。

还可以基于以下事实对特征向量的有效性进行检查:对于任意实方阵,左右特征向量是双正交的,即:

left_v.T.dot(right_v)应该给出一个对角矩阵,但它没有, 直到我将其更改为:left_v.T.conj().dot(right_v),

而:

left_v_2.T.dot(right_v_2)给出了预期的对角矩阵。

有人遇到过类似的问题吗?我的说法正确吗?SciPy手册在描述eig时是否有些不准确?你能给出任何建议吗?

非常感谢!

1个回答

4
关于 vleig 的文档字符串如下所示:
a.H vl[:,i] = w[i].conj() b.H vl[:,i]

或者,对两边取共轭转置(即厄米共轭转置)(这就是 .H 的意思),并假设 b 是单位矩阵。

vl[:,i].H a = w[i] vl[:,i].H

因此,vl的共轭转置的行是a的实际左特征向量。

Numpy数组实际上没有.H属性,所以必须使用.conj().T。

这是一个验证计算的脚本:

import numpy as np
from scipy.linalg import eig

# This only affects the printed output.
np.set_printoptions(precision=4)

a = np.array([[6, 2],
              [-1, 4]])

w, vl, vr = eig(a, left=True)

print "eigenvalues:", w
print

# check the left eigenvectors one-by-one:
for k in range(a.shape[0]):
    val = w[k]
    # Use a slice to maintain shape; vec is a 2x1 array.
    # That allows a meaningful transpose using .T.
    vec = vl[:, k:k+1]
    # rowvec is 1x2; it is the conjugate transpose of vec.
    # This should be the left eigenvector.
    rowvec = vec.conj().T
    # Verify that rowvec is a left eigenvector
    lhs = rowvec.dot(a)
    rhs = val * rowvec
    print "Compare", lhs, "to", rhs
    print rowvec, "is",
    if not np.allclose(lhs, rhs):
        print "*NOT*",
    print "a left eigenvector for eigenvalue", val

print
print "Matrix version:"
print "This"
print vl.conj().T.dot(a)
print "should equal this"
print np.diag(w).dot(vl.conj().T)

输出:

eigenvalues: [ 5.+1.j  5.-1.j]

Compare [[ 1.6330+2.4495j  4.0825+0.8165j]] to [[ 1.6330+2.4495j  4.0825+0.8165j]]
[[ 0.4082+0.4082j  0.8165-0.j    ]] is a left eigenvector for eigenvalue (5+1j)
Compare [[ 1.6330-2.4495j  4.0825-0.8165j]] to [[ 1.6330-2.4495j  4.0825-0.8165j]]
[[ 0.4082-0.4082j  0.8165+0.j    ]] is a left eigenvector for eigenvalue (5-1j)

Matrix version:
This
[[ 1.6330+2.4495j  4.0825+0.8165j]
 [ 1.6330-2.4495j  4.0825-0.8165j]]
should equal this
[[ 1.6330+2.4495j  4.0825+0.8165j]
 [ 1.6330-2.4495j  4.0825-0.8165j]]

现在,eig的文档字符串还在返回值的描述中提到:
vl : double or complex ndarray
    The normalized left eigenvector corresponding to the eigenvalue
    ``w[i]`` is the column v[:,i]. Only returned if ``left=True``.
    Of shape ``(M, M)``.

这可能会引起误解,因为传统的左特征向量定义(例如http://mathworld.wolfram.com/LeftEigenvector.htmlhttp://en.wikipedia.org/wiki/Eigenvalues_and_eigenvectors#Left_and_right_eigenvectors)是一个行向量,因此它是vl的列的共轭转置,实际上是左特征向量。

谢谢,沃伦。我明白你确认vl的共轭转置是按照常用约定左特征向量。现在问题是为什么eig函数提供了这种模棱两可的信息? - MKK_
Fwiw,A = np.array([ [0., -1], [1, 0] ]); w, L, R = eig(A, left=True, right=True); print "L* . R: \n", L.conj().T.dot(R) 得到的结果是 - I,如果你期望得到 I 的话就会有问题。一般来说它可能是 np.diag( 1 -1 -1 1 ),所以没有快速解决方案?(版本:numpy 1.14.1,scipy 1.0.0,python 2.7.14,mac 10.10.5) - denis
1
一般来说,L.conj().T.dot(R)必须是对角线,但不一定是单位矩阵。存在左右特征向量使得它们的乘积是单位矩阵,但eig不能保证计算出这样的特征向量。 - Warren Weckesser

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