如何通过 tf.py_func 传递梯度

这是使用 TensorFlow 实现的 Faster R-CNN。
proposal_layer 是用 Python 实现

我很好奇梯度是否可以通过 tf.py_func 传递,
权重和偏置一直在变化,
所以我认为梯度成功传递回来了

然后我做了一个小测试

import tensorflow as tfimport numpy as npdef addone(x):    # print type(x)    return x + 1def pyfunc_test():    # create data    x_data = tf.placeholder(dtype=tf.float32, shape=[None])    y_data = tf.placeholder(dtype=tf.float32, shape=[None])    w = tf.Variable(tf.constant([0.5]))    b = tf.Variable(tf.zeros([1]))    y1 = tf.mul(w, x_data, name='y1')    y2 = tf.py_func(addone, [y1], tf.float32)    y = tf.add(y2, b)    loss = tf.reduce_mean(tf.square(y - y_data))    optimizer = tf.train.GradientDescentOptimizer(0.5)    train = optimizer.minimize(loss)    with tf.Session() as sess:        sess.run(tf.global_variables_initializer())        for step in xrange(201):            ran = np.random.rand(115).astype(np.float32)            ans = ran * 1.5 + 3            dic = {x_data: ran, y_data: ans}            tt, yy, yy1= sess.run([train, y1, y2], feed_dict=dic)            if step % 20 == 0:                print 'step {}'.format(step)                print '{}, {}'.format(w.eval(), b.eval())        test = sess.run(y, feed_dict={x_data:[1]})        print 'test = {}'.format(test)if __name__ == '__main__':    pyfunc_test()

变量 b 一直在变化,但 w 在初始化后保持不变

sess.run(tf.gradients(loss, b), feed_dict=dic) 得到值
sess.run(tf.gradients(loss, w), feed_dict=dic) 得到 {TypeError}Fetch argument None has invalid type <type 'NoneType'>

我知道有些问题建议使用 tf.RegisterGradientgradient_override_map
但我在 faster rcnn 仓库中(帖子顶部的链接)找不到这些,
我是否做错了什么或遗漏了什么,导致 w 被冻结


回答:

py_func 的梯度是 None(只需检查 ops.get_gradient_function(y2.op))。这里有一个由 @harpone 提供的 gist,展示了如何为 py_func 使用梯度覆盖映射。

这是修改后的示例,使用了该方法

import numpy as npimport tensorflow as tfdef addone(x):    # print(type(x)    return x + 1def addone_grad(op, grad):    x = op.inputs[0]    return xfrom tensorflow.python.framework import opsimport numpy as np# 定义自定义 py_func,它也接受一个 grad op 作为参数:def py_func(func, inp, Tout, stateful=True, name=None, grad=None):    # 需要生成一个唯一名称以避免重复:    rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))    tf.RegisterGradient(rnd_name)(grad)  # 参见 _MySquareGrad 了解 grad 示例    g = tf.get_default_graph()    with g.gradient_override_map({"PyFunc": rnd_name}):        return tf.py_func(func, inp, Tout, stateful=stateful, name=name)def pyfunc_test():    # create data    x_data = tf.placeholder(dtype=tf.float32, shape=[None])    y_data = tf.placeholder(dtype=tf.float32, shape=[None])    w = tf.Variable(tf.constant([0.5]))    b = tf.Variable(tf.zeros([1]))    y1 = tf.mul(w, x_data, name='y1')    y2 = py_func(addone, [y1], [tf.float32], grad=addone_grad)[0]    y = tf.add(y2, b)    loss = tf.reduce_mean(tf.square(y - y_data))    optimizer = tf.train.GradientDescentOptimizer(0.01)    train = optimizer.minimize(loss)    print("Pyfunc grad", ops.get_gradient_function(y2.op))    with tf.Session() as sess:        sess.run(tf.global_variables_initializer())        for step in range(10):            #            ran = np.random.rand(115).astype(np.float32)            ran = np.ones((115)).astype(np.float32)            ans = ran * 1.5 + 3            dic = {x_data: ran, y_data: ans}            tt, yy, yy1= sess.run([train, y1, y2], feed_dict=dic)            if step % 1 == 0:                print('step {}'.format(step))                print('{}, {}'.format(w.eval(), b.eval()))        test = sess.run(y, feed_dict={x_data:[1]})        print('test = {}'.format(test))if __name__ == '__main__':    pyfunc_test()

Related Posts

使用LSTM在Python中预测未来值

这段代码可以预测指定股票的当前日期之前的值,但不能预测…

如何在gensim的word2vec模型中查找双词组的相似性

我有一个word2vec模型,假设我使用的是googl…

dask_xgboost.predict 可以工作但无法显示 – 数据必须是一维的

我试图使用 XGBoost 创建模型。 看起来我成功地…

ML Tuning – Cross Validation in Spark

我在https://spark.apache.org/…

如何在React JS中使用fetch从REST API获取预测

我正在开发一个应用程序,其中Flask REST AP…

如何分析ML.NET中多类分类预测得分数组?

我在ML.NET中创建了一个多类分类项目。该项目可以对…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注