2015-11-14 11 views
5

Sono interessato a calcolare la derivata di una matrice determinante utilizzando TensorFlow. Posso vedere dalla sperimentazione che tensorflow non ha implementato un metodo di differenziazione attraverso un determinante:differenziazione della matrice determinante in tensorflow

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

Poco un'ulteriore indagine ha rivelato che in realtà è possibile calcolare la derivata; vedere ad esempio Jacobi's formula. Ho deciso che al fine di attuare questo mezzo di differenziazione attraverso un determinante che ho bisogno di utilizzare la funzione di decoratore,

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

Tuttavia, non sono abbastanza familiarità con il flusso tensore per capire come questo possa essere realizzato. Qualcuno ha qualche idea in merito?

Ecco un esempio in cui mi imbatto in questo numero:

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) 

risposta

8

prega sezione controllare "Implementare Gradient in Python" here

In particolare, è possibile implementare nel modo seguente

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

Poi un semplice ciclo di formazione per verificare che funziona:

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

Quindi è possibile visualizzare la vostra perdita nel corso del tempo

import matplotlib.pyplot as plt 

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

dovrebbe vedere qualcosa di simile Loss plot

+0

Molto bello! per qualche motivo i documenti su TF stanno causando problemi. ad esempio: dai link sopra http://tensorflow.org/how_tos/adding_an_op/index.md#AUTOGENERATED-implement-the-gradient-in-python – Blaze

+0

corretti, i documenti sono stati spostati su http://tensorflow.org/how_tos/ –

0

Penso che si sono confusi con quello che è un derivato di una matrice determinante.

Il determinante della matrice è una funzione calcolata sugli elementi della matrice mediante una formula. Quindi se tutti gli elementi della matrice sono numeri, il fattore determinante sarà un solo numero e la derivata sarà 0. Quando alcuni degli elementi sono variabili, otterrai un'espressione di queste variabili. Ad esempio:

x, x^2 
1, sin(x) 

Il determinante sarà x*sin(x) - x^2 ed il derivato è 2x + sin(x) + x*cos(x). La formula di Jacobi collega semplicemente il determinante con la matrice aggiuntiva.


Nel tuo esempio tua matrice A costituito da soli numeri e quindi il determinante è solo un numero e la loss è solo un numero pure. GradientDescentOptimizer ha bisogno di avere alcune variabili libere da minimizzare e non ne possiede perché il tuo loss è solo un numero.

+0

Il vero problema qui è che la classe MatrixDeterminant non fornisce un gradiente registrato. – user1936768

+0

@ user1936768 sì, questo è un motivo per cui hai riscontrato l'errore nel tuo problema Python, ma questo non è un vero motivo. Supponiamo che esista il metodo del gradiente.Ti restituirà sempre 0, non importa cosa. Questo sarà di aiuto nelle tue 100 iterazioni? Come minimizzerà esattamente qualcosa? –

+0

No il gradiente non sarà zero. Sto minimizzando rispetto a x e y, e la matrice dipende da xey per sin e cos rispettivamente. – user1936768

0

Per coloro che sono interessati, ho scoperto la soluzione che funziona sui miei problemi:

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

che non esegue il backprop correttamente se si ha qualcosa sopra il determinante (cioè, se si minimizza il determinante al quadrato) –