张量流中的矩阵行列式微分
matrix determinant differentiation in tensorflow
我对使用 TensorFlow 计算矩阵行列式的导数很感兴趣。实验可以看出TensorFlow并没有实现通过行列式求微分的方法:
LookupError: No gradient defined for operation 'MatrixDeterminant'
(op type: MatrixDeterminant)
进一步调查表明,实际上可以计算导数;例如参见 [=13=]。我确定,为了实现这种通过行列式进行区分的方法,我需要使用函数装饰器,
@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)
我认为您对什么是矩阵行列式的导数感到困惑。
矩阵行列式是通过某种公式计算矩阵元素的函数。因此,如果矩阵的所有元素都是数字,那么行列式将只有一个数字,导数将为 0
。当一些元素是变量时,你会得到这些变量的表达式。例如:
x, x^2
1, sin(x)
行列式为 x*sin(x) - x^2
,导数为 2x + sin(x) + x*cos(x)
。雅可比公式只是将行列式与辅助矩阵连接起来。
在您的示例中,您的矩阵 A
仅包含数字,因此行列式只是一个数字,而 loss
也只是一个数字。 GradientDescentOptimizer
需要一些自由变量来最小化,但没有,因为你的 loss
只是一个数字。
对于那些感兴趣的人,我发现了解决我的问题的方法:
@tf.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminant(op, grad):
"""Gradient for MatrixDeterminant."""
return op.outputs[0] * tf.transpose(tf.matrix_inverse(op.inputs[0]))
请检查 "Implement Gradient in Python" 部分 here
具体可以如下实现
@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)
应该看到这样的东西
我对使用 TensorFlow 计算矩阵行列式的导数很感兴趣。实验可以看出TensorFlow并没有实现通过行列式求微分的方法:
LookupError: No gradient defined for operation 'MatrixDeterminant'
(op type: MatrixDeterminant)
进一步调查表明,实际上可以计算导数;例如参见 [=13=]。我确定,为了实现这种通过行列式进行区分的方法,我需要使用函数装饰器,
@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)
我认为您对什么是矩阵行列式的导数感到困惑。
矩阵行列式是通过某种公式计算矩阵元素的函数。因此,如果矩阵的所有元素都是数字,那么行列式将只有一个数字,导数将为 0
。当一些元素是变量时,你会得到这些变量的表达式。例如:
x, x^2
1, sin(x)
行列式为 x*sin(x) - x^2
,导数为 2x + sin(x) + x*cos(x)
。雅可比公式只是将行列式与辅助矩阵连接起来。
在您的示例中,您的矩阵 A
仅包含数字,因此行列式只是一个数字,而 loss
也只是一个数字。 GradientDescentOptimizer
需要一些自由变量来最小化,但没有,因为你的 loss
只是一个数字。
对于那些感兴趣的人,我发现了解决我的问题的方法:
@tf.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminant(op, grad):
"""Gradient for MatrixDeterminant."""
return op.outputs[0] * tf.transpose(tf.matrix_inverse(op.inputs[0]))
请检查 "Implement Gradient in Python" 部分 here
具体可以如下实现
@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)
应该看到这样的东西