2015-11-14 1 views
5

Je m'intéresse au calcul de la dérivée d'un déterminant matriciel en utilisant TensorFlow. Je peux voir d'expérimentation que tensorflow n'a pas mis en oeuvre un procédé de différenciation par l'intermédiaire d'un déterminant:Différenciation du déterminant matriciel dans le flux tensoriel

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

Un peu plus loin enquête a révélé qu'il est en fait possible de calculer la dérivée; Voir par exemple Jacobi's formula. Je résolus que pour mettre en œuvre ce moyen de différenciation par un déterminant que je dois utiliser le décorateur de fonction,

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

Cependant, je ne suis pas assez familier avec le flux tenseur pour comprendre comment cela peut être accompli. Quelqu'un a-t-il un aperçu à ce sujet?

Voici un exemple où je cours dans ce numéro:

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) 

Répondre

8

S'il vous plaît vérifier « Mettre en œuvre Dégradé en Python » section here

En particulier, vous pouvez le mettre en œuvre comme suit

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

Ensuite, une boucle de formation simple pour vérifier que cela fonctionne:

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

Vous pouvez alors visualiser votre perte au fil du temps

import matplotlib.pyplot as plt 

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

devriez voir quelque chose comme ça Loss plot

+0

Très cool! pour une raison quelconque, les docs sur tf causent des problèmes. par exemple: à partir des liens ci-dessus http://tensorflow.org/how_tos/adding_an_op/index.md#AUTOGENERATED-implement-the-gradient-in-python – Blaze

+0

corrigé, les docs ont été déplacés vers http://tensorflow.org/how_tos/ –

0

Je pense que vous êtes confus avec ce qui est un dérivé d'une matrice déterminant.

Le déterminant matriciel est une fonction qui est calculée sur les éléments de la matrice par une formule quelconque. Donc, si tous les éléments de la matrice sont des nombres, vous déterminerez-vous un seul nombre et la dérivée sera 0. Lorsque certains des éléments sont des variables, vous obtiendrez une expression de ces variables. Par exemple:

x, x^2 
1, sin(x) 

Le facteur déterminant sera x*sin(x) - x^2 et le dérivé est 2x + sin(x) + x*cos(x). La formule de Jacobi relie juste le déterminant avec la matrice d'adjonction.


Dans votre exemple, votre matrice A se compose uniquement de chiffres et donc le déterminant est juste un nombre et loss est juste un nombre aussi. GradientDescentOptimizer doit avoir quelques variables libres à minimiser et n'en a pas parce que votre loss est juste un nombre.

+0

Le vrai problème est que la classe MatrixDeterminant ne fournit pas un gradient enregistré. – user1936768

+0

@ user1936768 Oui c'est une des raisons pour lesquelles vous avez l'erreur dans votre problème python, mais ce n'est pas une vraie raison. Supposons que la méthode de gradient existe.Il vous reviendra toujours 0 peu importe quoi. Est-ce que cela vous aidera dans vos 100 itérations? Comment exactement cela va-t-il minimiser quelque chose? –

+0

Non, le dégradé ne sera pas nul. Je minimise par rapport à x et y, et la matrice dépend de x et y à travers sin et cos respectivement. – user1936768

0

Pour ceux qui sont intéressés, j'ai découvert la solution qui fonctionne sur mes problèmes:

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

qui ne recopie pas correctement si vous avez quelque chose au-dessus du déterminant (c'est-à-dire si vous minimisez le déterminant au carré) –