2016-08-08 40 views
4

Ich versuche, eine benutzerdefinierte Gradientenfunktion für 'my_op' zu schreiben, die für das Beispiel nur einen Aufruf von tf.identity() enthält (im Idealfall könnte es ein beliebiger Graph sein).Schreiben Sie benutzerdefinierte Python-basierte Verlaufsfunktion für eine Operation? (ohne C++ - Implementierung)

import tensorflow as tf 
from tensorflow.python.framework import function 


def my_op_grad(x): 
    return [tf.sigmoid(x)] 


@function.Defun(a=tf.float32, python_grad_func=my_op_grad) 
def my_op(a): 
    return tf.identity(a) 


a = tf.Variable(tf.constant([5., 4., 3., 2., 1.], dtype=tf.float32)) 

sess = tf.Session() 
sess.run(tf.initialize_all_variables()) 

grad = tf.gradients(my_op(a), [a])[0] 

result = sess.run(grad) 

print(result) 

sess.close() 

Leider bekomme ich folgende Fehlermeldung:

Traceback (most recent call last): 
    File "custom_op.py", line 19, in <module> 
    grad = tf.gradients(my_op(a), [a])[0] 
    File "/Users/njk/tfm/lib/python3.5/site-packages/tensorflow/python/framework/function.py", line 528, in __call__ 
    return call_function(self._definition, *args, **kwargs) 
    File "/Users/njk/tfm/lib/python3.5/site-packages/tensorflow/python/framework/function.py", line 267, in call_function 
    compute_shapes=False) 
    File "/Users/njk/tfm/lib/python3.5/site-packages/tensorflow/python/framework/ops.py", line 2285, in create_op 
    raise TypeError("Input #%d is not a tensor: %s" % (idx, a)) 
TypeError: Input #0 is not a tensor: <tensorflow.python.ops.variables.Variable object at 0x1080d2710> 

Ich weiß, dass es möglich ist, eine benutzerdefinierte C++ Betrieb zu schaffen, aber in meinem Fall ich brauche nur einen benutzerdefinierten Verlauf für eine Funktion zu schreiben, die kann einfach mit Standard-TensorFlow-Operationen in Python geschrieben werden, daher möchte ich vermeiden, unnötigen C++ - Code zu schreiben.

Auch ich benutze die Upstream-Version von TensorFlow von GitHub.

+0

Haben Sie @ ops.RegisterGradient ("my_op") versucht? Sie können dem Beispiel für den Python-Teil folgen und den C++ - Teil überspringen: https://www.tensorflow.org/versions/r0.10/how_tos/adding_an_op/index.html#implement-the-gradient-in-python –

+0

Ich denke, dass die Eingabe für ops.RegisterGradient() ein Name einer registrierten TensorFlow-Operation ist, es ist nicht nur der Name einer Python-Funktion, die TensorFlow-Operationen enthält. Also, irgendwie muss ich zuerst eine Operation registrieren, oder? – njk

+0

Ich denke, Sie haben Recht und der Code ist in der Nähe, aber funktioniert nicht wegen eines Fehlers hier: https://github.com/tensorflow/tensorflow/issues/3710 Beachten Sie, dass python_grad_func die gleiche Schnittstelle wie ops.RegisterGradient benötigt https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/framework/function.py#L349 –

Antwort

3

Beachten Sie, dass python_grad_func dieselbe Schnittstelle wie ops.RegisterGradient (https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/framework/function.py#L349) benötigt. Hier

ist das modifizierte Codebeispiel:

def my_op_grad(op, grad): ### instead of my_op_grad(x)             
    return tf.sigmoid(op.inputs[0])            

@function.Defun(a=tf.float32, python_grad_func=my_op_grad)      
def my_op(a):                  
    return tf.identity(a)               

def main(unused_argv):               

    a = tf.Variable(tf.constant([-5., 4., -3., 2., 1.], dtype=tf.float32))   
    sess = tf.Session()                
    sess.run(tf.initialize_all_variables())           

    a = tf.identity(a) #workaround for bug github.com/tensorflow/tensorflow/issues/3710 

    grad = tf.gradients(my_op(a), [a])[0]           
    result = sess.run(grad)               

    print(result)                 

    sess.close()  

Ausgang:

[ 0.00669286 0.98201376 0.04742587 0.88079709 0.7310586 ] 
+0

Durch Ausführen Ihres Codes habe ich NotFoundError: Op Typ nicht registriert 'my_op_2f8a34ee' –

+0

Das Ausführen gibt mir: 'ValueError: Unbekannte Schlüsselwortargumente: dict_keys (['a'])' bei my_op (a). Was soll ich machen? – nikpod

+0

Einen Workaround gefunden, der [hier] (https://github.com/tensorflow/tensorflow/issues/6804) erwähnt wurde. Beispiel: Definiere 'y = my_op (a)' vor 'sess.run (tf.initialize_all_variables())' Löst mein Problem und @EverettYou Problem – nikpod

2

Die folgende scheint gut funktionieren. Haben Sie einen Grund, python_grad_func stattdessen zu bevorzugen?

@tf.function.Defun(tf.float32, tf.float32) 
def bprop(x, dy): 
    return tf.sigmoid(x) 

@tf.function.Defun(tf.float32, grad_func=bprop) 
def fprop(x): 
    return x # identity 

a = tf.Variable(tf.constant([-5., 4., -3., 2., 1.], dtype=tf.float32)) 
grad = tf.gradients(fprop(a), [a])           

with tf.Session() as sess:                
    sess.run(tf.initialize_all_variables()) 
    result = sess.run(grad)               

print(result)                 
+0

Ich bekomme 'tensorflow.python.framework.errors_impl.NotFoundError: Op-Typ nicht registriert 'fprop_da39a3ee''. – Albert

+0

Hoppla. Es tut uns leid. Aktualisieren Sie den Beispielcode. Lass es mich wissen, wenn es für dich funktioniert. Die oft schwierige Sache hier ist, dass die Funktionsdefinition im selben Diagramm wie seine Verwendung sein sollte. – zfc