¿Escribir una función de degradado basada en Python personalizada para una operación? (sin implementación de C ++)

Estoy tratando de escribir una función de gradiente personalizada para ‘my_op’ que, por el bien del ejemplo, contiene solo una llamada a tf.identity () (idealmente, podría ser cualquier gráfico).

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

Lamentablemente me sale el siguiente error:

 Traceback (most recent call last): File "custom_op.py", line 19, in  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:  

Sé que es posible crear una operación C ++ personalizada, pero en mi caso solo necesito escribir un gradiente personalizado para una función que se pueda escribir fácilmente en Python utilizando las operaciones estándar de TensorFlow, así que me gustaría evitar escribir código C ++ innecesario .

Además, estoy usando la versión anterior de TensorFlow de GitHub.

Tenga en cuenta que python_grad_func necesita la misma interfaz que ops.RegisterGradient ( https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/framework/function.py#L349 ).

Aquí está el ejemplo del código modificado:

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

Salida:

 [ 0.00669286 0.98201376 0.04742587 0.88079709 0.7310586 ] 

Lo siguiente parece funcionar bien. ¿Tienes alguna razón para preferir python_grad_func en su lugar?

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