8

我对使用 TensorFlow 计算矩阵行列式的导数很感兴趣。我从实验中可以看出,TensorFlow 没有实现通过行列式进行区分的方法:

LookupError: No gradient defined for operation 'MatrixDeterminant' 
(op type: MatrixDeterminant)

进一步调查表明,实际上可以计算导数。例如,参见Jacobi 公式。我确定,为了实现这种通过行列式进行区分的方法,我需要使用函数装饰器,

@tf.RegisterGradient("MatrixDeterminant")
def _sub_grad(op, grad):
    ...

但是,我对张量流不够熟悉,无法理解如何实现这一点。有人对此事有任何见解吗?

这是我遇到此问题的示例:

x = tf.Variable(tf.ones(shape=[1]))
y = tf.Variable(tf.ones(shape=[1]))

A = tf.reshape(
    tf.pack([tf.sin(x), tf.zeros([1, ]), tf.zeros([1, ]), tf.cos(y)]), (2,2)
)
loss = tf.square(tf.matrix_determinant(A))


optimizer = tf.train.GradientDescentOptimizer(0.001)
train = optimizer.minimize(loss)

init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)


for step in xrange(100):
    sess.run(train)
    print sess.run(x)
4

3 回答 3

9

请在此处查看“在 Python 中实现渐变”部分

特别是,您可以按如下方式实现它

@ops.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminantGrad(op, grad):
  """Gradient for MatrixDeterminant. Use formula from 2.2.4 from
  An extended collection of matrix derivative results for forward and reverse
  mode algorithmic differentiation by Mike Giles
  -- http://eprints.maths.ox.ac.uk/1079/1/NA-08-01.pdf
"""
  A = op.inputs[0]
  C = op.outputs[0]
  Ainv = tf.matrix_inverse(A)
  return grad*C*tf.transpose(Ainv)

然后是一个简单的训练循环来检查它是否有效:

a0 = np.array([[1,2],[3,4]]).astype(np.float32)
a = tf.Variable(a0)
b = tf.square(tf.matrix_determinant(a))
init_op = tf.initialize_all_variables()
sess = tf.InteractiveSession()
init_op.run()

minimization_steps = 50
learning_rate = 0.001
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train_op = optimizer.minimize(b)

losses = []
for i in range(minimization_steps):
  train_op.run()
  losses.append(b.eval())

然后你可以想象你的损失随着时间的推移

import matplotlib.pyplot as plt

plt.ylabel("Determinant Squared")
plt.xlabel("Iterations")
plt.plot(losses)

应该看到这样的东西 损失图

于 2015-11-15T04:30:13.827 回答
0

对于那些感兴趣的人,我发现了适用于我的问题的解决方案:

@tf.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminant(op, grad):
    """Gradient for MatrixDeterminant."""
    return op.outputs[0] * tf.transpose(tf.matrix_inverse(op.inputs[0]))
于 2015-11-15T03:10:32.200 回答
0

我认为您对什么是矩阵行列式的导数感到困惑。

矩阵行列式是通过某些公式对矩阵元素进行计算的函数。因此,如果矩阵的所有元素都是数字,那么行列式将是一个数字,而导数将是0。当某些元素是变量时,您将获得这些变量的表达式。例如:

x, x^2
1, sin(x)

行列式是x*sin(x) - x^2,导数是2x + sin(x) + x*cos(x)。Jacobi 公式只是将行列式与辅助矩阵连接起来。


在您的示例中,您的矩阵A仅包含数字,因此行列式只是一个数字,而loss也只是一个数字。GradientDescentOptimizer需要有一些自由变量来最小化并且没有任何变量,因为你loss只是一个数字。

于 2015-11-15T01:04:55.510 回答