用Java和Python计算特征向量的差异

bor*_*ter 6 python java numpy eigenvector apache-commons-math

作为当前任务,我需要计算120*120矩阵的特征值和特征向量.首先,我在Java(Apache Commons Math库)和Python 2.7(Numpy库)中以简单的2×2矩阵测试了这些计算.我有一个问题,特征向量值不匹配,如下所示:

//Java
import org.apache.commons.math3.linear.EigenDecomposition;
import org.apache.commons.math3.linear.MatrixUtils;
import org.apache.commons.math3.linear.RealMatrix;

public class TemporaryTest {

  public static void main(String[] args) {

    double[][] testArray = {{2, -1}, {1, 1}};
    RealMatrix testMatrix = MatrixUtils.createRealMatrix(testArray);
    EigenDecomposition decomposition = new EigenDecomposition (testMatrix);
    System.out.println("eigenvector[0] = " + decomposition.getEigenvector(0));
    System.out.println("eigenvector[1] = " + decomposition.getEigenvector(1));
}
Run Code Online (Sandbox Code Playgroud)

特征向量的输出显示为{real_value + imaginary_value; real_value + imaginary_value}:

//Java output
eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
Run Code Online (Sandbox Code Playgroud)

Python中的代码相同,但使用Numpy库:

# Python
import numpy as np
from numpy import linalg as LA

w, v = LA.eig(np.array([[2, -1], [1, 1]]))
print (v[:, 0])
print (v[:, 1])
Run Code Online (Sandbox Code Playgroud)

Python中的特征向量输出类似,[real + imag real + imag]:

[ 0.35355339+0.61237244j  0.70710678+0.j        ]
[ 0.35355339-0.61237244j  0.70710678-0.j        ]
Run Code Online (Sandbox Code Playgroud)

我担心的是,为什么这些载体不同?有什么东西我错过了吗?Ty提供任何帮助或建议

War*_*ser 2

在 Apache Commons Math 3 中,EigenDecomposition接受非对称矩阵,但它使用类RealVector和返回结果RealMatrix。要获得实际的复数结果,您必须将适当的实数结果组合成复数共轭对。

对于特征向量,您得到:

eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
Run Code Online (Sandbox Code Playgroud)

这两个向量都与复共轭特征值对相关联getRealEigenvalue(0) + getImagEigenvalue(0)*igetRealEigenvalue(1) + getImagEigenvalue(1)*i但这些向量不是实际的特征向量。实际的特征向量是复共轭对 eigenvector[0] + eigenvector[1]*ieigenvector[0] - eigenvector[1]*i

这些向量仍然与 numpy 返回的结果不“匹配”,但这是因为这两个库没有使用相同的标准化。特征向量不是唯一的;特征向量乘以任何非零标量(包括复标量)仍然是特征向量。Java 结果和 numpy 结果之间的唯一区别是标量乘数。

为了方便起见,我将把浮点值转换为其精确值。即-0.8660254038是 的浮点近似值-sqrt(3)/2。Java 数学库给出以下特征向量:

 [-sqrt(3)/2 + (1/2)*i]    and    [-sqrt(3)/2 - (1/2)*i]
 [      0    +     1*i]           [      0    -     1*i]
Run Code Online (Sandbox Code Playgroud)

如果将第一个特征向量乘以 -(sqrt(2)/2)*i,将第二个特征向量乘以 (sqrt(2)/2)*i,您将得到 numpy 返回的特征向量。

这是一个包含该计算的 ipython 会话。 v1v2是上面显示的向量。

In [20]: v1 = np.array([-np.sqrt(3)/2 + 0.5j, 1j])

In [21]: v1
Out[21]: array([-0.8660254+0.5j,  0.0000000+1.j ])

In [22]: v2 = np.array([-np.sqrt(3)/2 - 0.5j, -1j])

In [23]: v2
Out[23]: array([-0.8660254-0.5j,  0.0000000-1.j ])
Run Code Online (Sandbox Code Playgroud)

乘以v1-(sqrt(2)/2)*i 即可得到 所返回的第一个特征向量numpy.linalg.eig

In [24]: v1*(-np.sqrt(2)/2*1j)
Out[24]: array([ 0.35355339+0.61237244j,  0.70710678-0.j        ])
Run Code Online (Sandbox Code Playgroud)

乘以v2(sqrt(2)/2)*i 即可得到 所返回的第二个特征向量numpy.linalg.eig

In [25]: v2*(np.sqrt(2)/2*1j)
Out[25]: array([ 0.35355339-0.61237244j,  0.70710678+0.j        ])
Run Code Online (Sandbox Code Playgroud)

为了方便起见,这里重复 numpy 计算。的列evecs是特征向量。

In [28]: evals, evecs = np.linalg.eig(a)

In [29]: evecs
Out[29]: 
array([[ 0.35355339+0.61237244j,  0.35355339-0.61237244j],
       [ 0.70710678+0.j        ,  0.70710678-0.j        ]])
Run Code Online (Sandbox Code Playgroud)