2015-11-14 6 views
5

Меня интересует вычисление производной матричного определителя с использованием TensorFlow. Я могу видеть из экспериментов, которые TensorFlow не реализовали метод дифференцирования через определитель:матричное детерминантное дифференцирование в тензорном потоке

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

Немного дальнейшее исследование показало, что на самом деле можно вычислить производную; см., например, Jacobi's formula. Я решил, что для того, чтобы осуществить это означает, дифференцироваться через определитель, что мне нужно использовать функцию декоратора,

@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) 

ответ

8

Пожалуйста, раздел проверки «Реализовать Градиент в 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) 

должны увидеть что-то вроде этого Loss plot

+0

Очень круто! по какой-то причине документы по tf вызывают проблемы. например: из ссылок выше http://tensorflow.org/how_tos/adding_an_op/index.md#AUTOGENERATED-implement-the-gradient-in-python – Blaze

+0

исправлено, документы перенесены на http://tensorflow.org/how_tos/ –

0

Я думаю, что вы запутались с тем, что является производным матрицы определителя.

Матричный определитель - это функция, которая вычисляется по элементам матрицы по какой-либо формуле. Поэтому, если все элементы матрицы являются числами, вы определитель вы получите только одно число, а производная будет 0. Когда некоторые из элементов являются переменными, вы получите выражение этих переменных. Например:

x, x^2 
1, sin(x) 

Определитель будет x*sin(x) - x^2 и производная 2x + sin(x) + x*cos(x). Формула Якоби просто связывает определитель с адъюнктной матрицей.


В вашем примере ваша матрица A состоит только из чисел и, следовательно, определитель только число и loss просто номер, а также. GradientDescentOptimizer должен иметь некоторые свободные переменные, чтобы свести к минимуму и не имеет никаких ограничений, потому что ваш loss - это просто номер.

+0

Реальная проблема здесь состоит в том, что MatrixDeterminant класс не обеспечивает зарегистрированного градиента. – user1936768

+0

@ user1936768 да, это причина, по которой вы получили ошибку в своей проблеме python, но это не настоящая причина. Предположим, что существует метод градиента.Он всегда будет возвращать вам 0 независимо от того, что. Будет ли эта помощь в ваших 100 итерациях? Как именно это минимизирует что-нибудь? –

+0

Нет градиента не будет равным нулю. Я минимизирую по x и y, и матрица зависит от x и y через sin и cos соответственно. – user1936768

0

Для тех, кто заинтересован, я обнаружил, что решение, которое работает на моих проблем:

@tf.RegisterGradient("MatrixDeterminant") 
def _MatrixDeterminant(op, grad): 
    """Gradient for MatrixDeterminant.""" 
    return op.outputs[0] * tf.transpose(tf.matrix_inverse(op.inputs[0])) 
+1

, который не работает правильно, если у вас есть что-то сверху детерминанта (т. Е. Если вы минимизируете квадрат детерминанта) –