Матричный определитель дифференцирования в тензорном потоке
Я заинтересован в вычислении производной матричного определителя, используя TensorFlow. Из экспериментов видно, что в TensorFlow не реализован метод дифференциации по определителю:
LookupError: No gradient defined for operation 'MatrixDeterminant'
(op type: MatrixDeterminant)
Небольшое дальнейшее исследование показало, что на самом деле можно вычислить производную; см., например , формулу Якоби. Я решил, что для реализации этого средства дифференциации через определитель мне нужно использовать функцию декоратор,
@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)
3 ответа
Пожалуйста, проверьте раздел "Внедрить градиент в 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)
Для тех, кто заинтересован, я нашел решение, которое работает над моими проблемами:
@tf.RegisterGradient("MatrixDeterminant")
def _MatrixDeterminant(op, grad):
"""Gradient for MatrixDeterminant."""
return op.outputs[0] * tf.transpose(tf.matrix_inverse(op.inputs[0]))
Я думаю, что вы запутались с тем, что является производной от матричного детерминанта.
Определитель матрицы - это функция, которая вычисляется по элементам матрицы по некоторой формуле. Так что, если все элементы матрицы являются числами, вы определяете, будете ли вы просто одно число, а производная будет 0
, Когда некоторые элементы являются переменными, вы получите выражение этих переменных. Например:
x, x^2
1, sin(x)
Определитель будет x*sin(x) - x^2
и производная 2x + sin(x) + x*cos(x)
, Формула Якоби просто связывает определитель с дополнительной матрицей.
В вашем примере ваша матрица A
состоит только из чисел и, следовательно, определитель является просто числом, а loss
это просто число. GradientDescentOptimizer
необходимо иметь несколько свободных переменных, чтобы свести к минимуму и не имеет, потому что ваши loss
это просто число.