Tensorflow计算特征值/向量的不正确梯度w.r.t.基础矩阵

时间:2017-12-12 01:21:02

标签: python tensorflow linear-algebra gradient-descent

我在评估基础矩阵的特征值/特征向量的梯度方面存在问题。 Tensorflow评估梯度,但这些与分析推导不一致。

我们使用tf.self_adjoint_eig来评估张量流变量输入的频谱分解。我们用对称矩阵初始化它以满足自伴运算符属性。我们希望得到单个特征值或特征向量相对于原始矩阵的导数(对于特征向量的注释,我们从一个特征向量中取一个元素,例如特征向量1中的元素2,以避免现在的梯度聚合问题。)

评估特征值的分析梯度和对称实矩阵的向量的方法可以在论文"关于区分特征值和特征向量"作者:Magnus(1985),Theorem 1 eqn(6)+(7)。我们使用输入矩阵评估了本文下的梯度,并将其与张量流评估的梯度和有限差分近似的梯度进行了比较。对于特征值,梯度是相似的(在对角线条目上相同,在非对角线元素上偏离2倍),然而特征向量在对角线条目之外相当远。首先,定义矩阵A(任何关于在帖子中呈现矩阵的建议都会有所帮助!)

A =

  • -3 -2 4
  • -2 1 1
  • 4 1 5

在A上使用np.linalg.eig和tf.self_adjoint_eig(我只是用A初始化变量并计算tf实现的渐变)

张量流特征值:[ - 5.43071561 1.76904987 6.66166575] Python特征值:[ - 5.43071561 6.66166575 1.76904987]

我现在想要评估特征值1(-5.43071561)w.r.t的梯度。甲

分析梯度(Magnus 1985):

  • 0.75896178 0.28555906 -0.31842553
  • 0.28555906 0.10744148 -0.11980748
  • -0.31842553 -0.11980748 0.13359674

Tensorflow梯度:

  • 0.75896178 0 0
  • 0.57111812,0.10744148 0
  • -0.63685107 -0.23961495 0.13359674

对角线条目是相同的,但非对角条目明显偏离了2倍。现在我们尝试评估特征向量的渐变。

张量流特征向量:

  • -0.87118413 -0.31452619 -0.37697678
  • -0.32778267 0.94426587 -0.0303395
  • 0.36550888 0.09713517 -0.92572567

Python特征向量:

  • 0.87118413 0.37697678 -0.31452619
  • 0.32778267 0.0303395 0.94426587
  • -0.36550888 0.92572567 0.09713517

我们尝试找到特征向量1元素2的梯度(+/- 0.32778267)。我们期望张量流梯度等于分析梯度(在考虑符号差异之后)。

分析梯度:

  • 0.03511309 -0.10795607 -0.01312188
  • 0.01321128 -0.04061843 -0.0049371
  • 0.01473184 0.04529341 0.00550534

Tensorflow梯度:

  • -0.03511309,0。,0。
  • 0.09474478,0.04061843,0。
  • 0.02785372,-0.04035631,-0.00550534

除了非对角线上的条目不同之外,一个问题是张量流仅返回梯度的下三角形。尽管A是对称的,但对梯度的贡献不是对称的,如上面的分析评估所示。谢谢你的阅读!

TL:DR,我认为梯度计算不正确。有任何想法或类似经历吗?

下面重现的代码:

import tensorflow as tf
import numpy as np
from numpy.linalg import eig
from numpy.linalg import pinv

#create upper triangular matrix
A_vec = np.array([-3,-2,4,-2,1,1,4,1,5])
A = np.reshape(A_vec,[3,3])
e = eig(A)
#extract eigenvalues and eigenvectors
e_val = e[0]
e_vec = e[1]

#tensorflow variables
A_tf = tf.Variable(tf.constant(A,dtype=tf.float64))
e_tf = tf.self_adjoint_eig(A_tf)
#extract eigenvalues and eigenvectors
e_val_tf = e_tf[0]
e_vec_tf = e_tf[1]

#initialise variables and run session
sess = tf.Session()
sess.run(tf.global_variables_initializer())

#print A
print("A:")
print(A)

#show eigenvalues for Tensorflow and R
print("Tensorflow eigenvalues:",sess.run(e_val_tf))
print("Python eigenvalues:",e_val)


############# Eigenvector element gradient #############

eval_grad_tf = tf.gradients(e_val_tf[0], A_tf) #Tensorflow gradient of first eigenvalue w.r.t. A

#analytical gradient
eigenvec = e_vec[:,0]

#analytical deriv from analytical gradient of eigenvalue from Magnus (1985), "On differentiating
#Eigenvalues and Eigenvectors", Theorem 1 eqn (6)
eval_grad_analytical = np.outer(eigenvec,eigenvec)

print("Analytical gradient:")
print(eval_grad_analytical)
print("Tensorflow gradient:")
print(sess.run(eval_grad_tf))


############# Eigenvector element gradient #############

print("Tensorflow eigenvectors:")
print(sess.run(e_vec_tf))
print("Python eigenvectors:")
print(e_vec)

#tensorflow gradient
evec_grad_tf = tf.gradients(e_vec_tf[1,0], A_tf)

#analytical gradient

#analytical deriv from analytical gradient of eigenvalue from Magnus (1985), "On differentiating
#Eigenvalues and Eigenvectors", Theorem 1 eqn (7)

evec_grad_analytical = np.kron(eigenvec, pinv(e_val[0]*np.eye(3)-A)) #calculates derivatives for each component of eigenvector 3
evec_grad_analytical1 = np.reshape(evec_grad_analytical[1,:],[3,3]) #retrieves column 2 which should correspond to the gradient of eigenvector 3 element 2 w.r.t. A

print("Analytical gradient:")
print(evec_grad_analytical1)
print("Tensorflow gradient:")
print(sess.run(evec_grad_tf))

0 个答案:

没有答案