0

I am trying to write some custom TensorFlow functions in python (using tf.py_func) where I want to calculate both the results and the gradients in python. I'm using the gradient_override_map trick (for example from from https://gist.github.com/harpone/3453185b41d8d985356cbe5e57d67342 and How to make a custom activation function with only Python in Tensorflow?).

However, while the function in the forward direction gets a numpy array as an input, the function for the gradient gets Tensors. This is a problem, depending on when the function gets called, because there may not be a default session, and/or there may not be a feed_dict with all the required values yet (for example, in a tf.train optimizer).

How do I do a py_func where both the forward and backward functions get (and return) numpy arrays?

Sample code:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt

def sin_func(x):
    return np.sin(x)

def sin_grad_func(op, grad):
    x = op.inputs[0].eval()
    grad = grad.eval() # <--- this is what I'd like to avoid
    output_grad = np.cos(x) * grad
    return tf.convert_to_tensor(output_grad)

def py_func(func, inp, Tout, stateful=True, name=None, grad_func=None):
    grad_name = 'PyFuncGrad_' + str(np.random.randint(0, 1E+8))
    tf.RegisterGradient(grad_name)(grad_func)
    g = tf.get_default_graph()
    with g.gradient_override_map({"PyFunc": grad_name}):
        return tf.py_func(func, inp, Tout, stateful=stateful, name=name)

with tf.Session() as sess:
    np_x = np.linspace(0, np.pi, num=1000, dtype=np.float32)
    x = tf.constant(np_x)
    y = py_func(sin_func,
                [x],
                [tf.float32],
                name='np_sin',
                grad_func=sin_grad_func)
    y = y[0]
    gr = tf.gradients(y, [x])
    tf.global_variables_initializer().run()
    plt.plot(y.eval())
    plt.plot(gr[0].eval())

1 Answer 1

1

If you want to include arbitrary Python code in your gradient function, the easiest solution is to create another tf.py_func() inside sin_grad_func():

def sin_grad_func_impl(x, grad):
    return np.cos(x) * grad

def sin_grad_func(op, grad):
    return tf.py_func(sin_grad_func_impl, [x, grad], grad.dtype)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.