用Theano计算特征值

时间:2016-04-18 14:59:01

标签: theano eigenvalue

我想用theano.tensor.nlinalg.eig来计算非对称方阵的特征值。

问题是:如何获得特征值/特征向量的复数值?

似乎theano.tensor.nlinalg.eig只返回它们的真实部分(参见下面的代码)。

谢谢大家。

import numpy as np
import theano
rng = np.random
T = theano.tensor

# Create an asymmetric (random) square matrix
N = 3
asymm_Matrix = rng.randn(N,N)

# Compute eigenv* with numpy
np_eigenvalues, np_eigenvectors = np.linalg.eig(asymm_Matrix)

# Define a theano node that computes eigenv*
symMatrix = T.dmatrix("symMatrix")
symEigenvalues, eigenvectors = T.nlinalg.eig(symMatrix)
get_Eigen = theano.function([symMatrix], [symEigenvalues, eigenvectors] )

# Compute eigenv* with theano
theano_eigenvalues, theano_eigenvectors = get_Eigen(asymm_Matrix)

print("---- asymm_Matrix :")
print(asymm_Matrix)
print()
print("---- np.linalg.eig")
print("eigenvalues :")
print(np_eigenvalues)
print("eigenvectors :")
print(np_eigenvectors)
print()
print("---- T.nlinalg.eig")
print("eigenvalues :")
print(theano_eigenvalues)
print("eigenvectors :")
print(theano_eigenvectors)

输出:

 ---- asymm_Matrix :
 [[-0.163  -0.2099  1.1227]
  [-1.132  -0.9667 -1.0436]
  [-0.0974 -0.4395 -0.3839]]

 ---- np.linalg.eig
 eigenvalues :
 [-1.0136+0.1346j -1.0136-0.1346j  0.5136+0.j    ]
 eigenvectors :
 [[-0.3948-0.1604j -0.3948+0.1604j  0.6638+0.j    ]
  [ 0.7736+0.j      0.7736-0.j     -0.6977+0.j    ]
  [ 0.4630+0.0742j  0.4630-0.0742j  0.2696+0.j    ]]

 ---- T.nlinalg.eig
 eigenvalues :
 [-1.0136 -1.0136  0.5136]
 eigenvectors :
 [[-0.3948 -0.3948  0.6638]
  [ 0.7736  0.7736 -0.6977]
  [ 0.463   0.463   0.2696]]

1 个答案:

答案 0 :(得分:1)

我没有找到T.nlinalg.eig如何工作的明确文档,但似乎它的输出始终与输入的类型相同(参见nlinalg.eig代码https://github.com/Theano/Theano/blob/master/theano/tensor/nlinalg.py中的第321行)。

因此,为了获得复杂的输出,我只是将输入symMatrix定义为复杂的:symMatrix = T.cmatrix("symMatrix")

由于symMatrix现在很复杂,当你调用get_Eigen时,参数asymm_Matrix也必须很复杂,所以我将其相应地转换为一个新变量:c_asymm_Matrix = asymm_Matrix.astype('complex64')

以下代码也返回虚部:

import numpy as np
import theano
rng = np.random
T = theano.tensor

# Create an asymmetric (random) square matrix
N = 3
asymm_Matrix = rng.randn(N,N)

# Compute eigenv* with numpy
np_eigenvalues, np_eigenvectors = np.linalg.eig(asymm_Matrix)

# Define a theano node that computes eigenv*
# symMatrix defined as complex so that nlinalg.eig outputs are complex as well
symMatrix = T.cmatrix("symMatrix") 
symEigenvalues, eigenvectors = T.nlinalg.eig(symMatrix)
get_Eigen = theano.function([symMatrix], [symEigenvalues, eigenvectors] ) 

# Compute eigenv* with theano
# Our input for get_Eigen has to be complex too now
c_asymm_Matrix = asymm_Matrix.astype('complex64') 

theano_eigenvalues, theano_eigenvectors = get_Eigen(c_asymm_Matrix) #this one gives error because it expects float64 input and tries to downcast

print("---- asymm_Matrix :")
print(asymm_Matrix)
print()
print("---- np.linalg.eig")
print("eigenvalues :")
print(np_eigenvalues)
print("eigenvectors :")
print(np_eigenvectors)
print()
print("---- T.nlinalg.eig")
print("eigenvalues :")
print(theano_eigenvalues)
print("eigenvectors :")
print(theano_eigenvectors)

输出:

---- asymm_Matrix :
[[ 1.16270655  0.7266984  -0.87479655]
 [-3.04065245 -1.09469397 -1.57315266]
 [ 0.4850981   0.56072627  1.16248949]]
()
---- np.linalg.eig
eigenvalues :
[ 0.03696641+1.49515503j  0.03696641-1.49515503j  1.15656924+0.j        ]
eigenvectors :
[[ 0.22084674+0.37455923j  0.22084674-0.37455923j -0.66915708+0.j        ]
 [-0.87172957+0.j         -0.87172957-0.j          0.57392013+0.j        ]
 [ 0.20022446+0.10454574j  0.20022446-0.10454574j  0.47206407+0.j        ]]
()
---- T.nlinalg.eig
eigenvalues :
[ 0.03696636 +1.49515510e+00j  0.03696636 -1.49515510e+00j
  1.15656924 +1.52098596e-17j]
eigenvectors :
[[-0.22084673 -3.74559224e-01j -0.22084673 +3.74559224e-01j
   0.66915709 +0.00000000e+00j]
 [ 0.87172955 +0.00000000e+00j  0.87172955 +0.00000000e+00j
  -0.57392007 +5.55111512e-17j]
 [-0.20022446 -1.04545735e-01j -0.20022446 +1.04545735e-01j
  -0.47206411 +3.88578059e-16j]]

输出稍有不同,但这只是因为在Theano输出中显示的一些非常小的虚部在numpy输出中为零。