Java 和 Python 计算特征向量的差异
Difference in calculating eigenvectors wih Java and Python
作为当前任务,我需要计算 120*120 矩阵的特征值和特征向量。首先,我在 Java(Apache Commons 数学库)和 Python 2.7(Numpy 库)中用一个简单的 2 x 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));
}
特征向量的输出显示为{real_value + imaginary_value; real_value + imaginary_value}:
//Java output
eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
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])
Python 中特征向量的输出类似地显示,[real+imag real+imag]:
[ 0.35355339+0.61237244j 0.70710678+0.j ]
[ 0.35355339-0.61237244j 0.70710678-0.j ]
我担心的是,为什么这些向量不同?有什么我想念的吗? Ty 寻求任何帮助或建议
我认为你无法让它发挥作用。原因如下:
- 测试套件only tests real eigenvalues
- mapMultiplyToSelf 不支持复数参数(因此不能乘以包括特征值在内的复数)
As of 2.0, this class supports only symmetric matrices, and hence computes only real realEigenvalues. This implies the D matrix returned by getD() is always diagonal and the imaginary values returned getImagEigenvalue(int) and getImagEigenvalues() are always null. (c) EigenDecomposition JavaDoc
在 Apache Commons Math 3 中,EigenDecomposition
接受非对称矩阵,但它 return 使用 类 RealVector
和 RealMatrix
结果。要获得实际的复数结果,您必须将适当的实数结果组合成复数共轭对。
对于特征向量,您得到:
eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
这两个向量都与复共轭特征值对 getRealEigenvalue(0) + getImagEigenvalue(0)*i
和 getRealEigenvalue(1) + getImagEigenvalue(1)*i
相关联,但这些向量不是实际的特征向量。实际特征向量是复共轭对
eigenvector[0] + eigenvector[1]*i
和 eigenvector[0] - eigenvector[1]*i
.
这些向量仍然没有 "match" 由 numpy return 编辑的结果,但那是因为两个库没有使用相同的规范化。特征向量不是唯一的;特征向量乘以任何非零标量(包括复标量)仍然是特征向量。 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]
如果您将第一个特征向量乘以 -(sqrt(2)/2)*i,将第二个特征向量乘以 (sqrt(2)/2)*i,您将得到 return 通过 numpy.
这是一个包含该计算的 ipython 会话。 v1
和 v2
是上面显示的向量。
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 ])
将 v1
乘以 -(sqrt(2)/2)*i 得到第一个特征向量 return 由 numpy.linalg.eig
:
In [24]: v1*(-np.sqrt(2)/2*1j)
Out[24]: array([ 0.35355339+0.61237244j, 0.70710678-0.j ])
将 v2
乘以 (sqrt(2)/2)*i 得到第二个特征向量 return 乘以 numpy.linalg.eig
:
In [25]: v2*(np.sqrt(2)/2*1j)
Out[25]: array([ 0.35355339-0.61237244j, 0.70710678+0.j ])
为方便起见,这里重复了 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 ]])
作为当前任务,我需要计算 120*120 矩阵的特征值和特征向量。首先,我在 Java(Apache Commons 数学库)和 Python 2.7(Numpy 库)中用一个简单的 2 x 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));
}
特征向量的输出显示为{real_value + imaginary_value; real_value + imaginary_value}:
//Java output
eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
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])
Python 中特征向量的输出类似地显示,[real+imag real+imag]:
[ 0.35355339+0.61237244j 0.70710678+0.j ]
[ 0.35355339-0.61237244j 0.70710678-0.j ]
我担心的是,为什么这些向量不同?有什么我想念的吗? Ty 寻求任何帮助或建议
我认为你无法让它发挥作用。原因如下:
- 测试套件only tests real eigenvalues
- mapMultiplyToSelf 不支持复数参数(因此不能乘以包括特征值在内的复数)
As of 2.0, this class supports only symmetric matrices, and hence computes only real realEigenvalues. This implies the D matrix returned by getD() is always diagonal and the imaginary values returned getImagEigenvalue(int) and getImagEigenvalues() are always null. (c) EigenDecomposition JavaDoc
在 Apache Commons Math 3 中,EigenDecomposition
接受非对称矩阵,但它 return 使用 类 RealVector
和 RealMatrix
结果。要获得实际的复数结果,您必须将适当的实数结果组合成复数共轭对。
对于特征向量,您得到:
eigenvector[0] = {-0.8660254038; 0}
eigenvector[1] = {0.5; 1}
这两个向量都与复共轭特征值对 getRealEigenvalue(0) + getImagEigenvalue(0)*i
和 getRealEigenvalue(1) + getImagEigenvalue(1)*i
相关联,但这些向量不是实际的特征向量。实际特征向量是复共轭对
eigenvector[0] + eigenvector[1]*i
和 eigenvector[0] - eigenvector[1]*i
.
这些向量仍然没有 "match" 由 numpy return 编辑的结果,但那是因为两个库没有使用相同的规范化。特征向量不是唯一的;特征向量乘以任何非零标量(包括复标量)仍然是特征向量。 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]
如果您将第一个特征向量乘以 -(sqrt(2)/2)*i,将第二个特征向量乘以 (sqrt(2)/2)*i,您将得到 return 通过 numpy.
这是一个包含该计算的 ipython 会话。 v1
和 v2
是上面显示的向量。
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 ])
将 v1
乘以 -(sqrt(2)/2)*i 得到第一个特征向量 return 由 numpy.linalg.eig
:
In [24]: v1*(-np.sqrt(2)/2*1j)
Out[24]: array([ 0.35355339+0.61237244j, 0.70710678-0.j ])
将 v2
乘以 (sqrt(2)/2)*i 得到第二个特征向量 return 乘以 numpy.linalg.eig
:
In [25]: v2*(np.sqrt(2)/2*1j)
Out[25]: array([ 0.35355339-0.61237244j, 0.70710678+0.j ])
为方便起见,这里重复了 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 ]])