Python 梯度如何通过tf.py_func

Python 梯度如何通过tf.py_func,python,machine-learning,tensorflow,neural-network,Python,Machine Learning,Tensorflow,Neural Network,这是tensorflow中更快的R-CNN实现。 这是由python编写的 我很好奇梯度是否可以通过tf.py_func 权重和偏差不断变化 因此,我认为梯度反馈成功 然后我做一个小测试 import tensorflow as tf import numpy as np def addone(x): # print type(x) return x + 1 def pyfunc_test(): # create data x_data = tf.placeh

这是tensorflow中更快的R-CNN实现。
这是由python编写的

我很好奇梯度是否可以通过
tf.py_func

权重和偏差不断变化
因此,我认为梯度反馈成功

然后我做一个小测试

import tensorflow as tf
import numpy as np

def addone(x):
    # print type(x)
    return x + 1

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 = 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\u dict=dic)
get value
sess.run(tf.gradients(loss,w),feed_dict=dic)
get
{TypeError}Fetch参数无无效类型


我知道有些问题建议使用
tf.RegisterGradient
渐变覆盖图

但我在更快的rcnn回购(帖子顶部的链接)中找不到这些内容

我是做错了什么还是遗漏了什么,以至于
w
冻结了
py\u函数的梯度
None
(只需检查
ops.get\u Gradient\u函数(y2.op)
)。@harpone展示了如何对py_func使用渐变覆盖贴图

下面是您的示例,已修改为使用该配方

import numpy as np
import tensorflow as tf

def addone(x):
    # print(type(x)
    return x + 1

def addone_grad(op, grad):
    x = op.inputs[0]
    return x

from tensorflow.python.framework import ops
import numpy as np

# Define custom py_func which takes also a grad op as argument:
def py_func(func, inp, Tout, stateful=True, name=None, grad=None):

    # Need to generate a unique name to avoid duplicates:
    rnd_name = 'PyFuncGrad' + str(np.random.randint(0, 1E+8))

    tf.RegisterGradient(rnd_name)(grad)  # see _MySquareGrad for grad example
    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()

谢谢你的回答,我知道harpone的要点,但是我在更快的rcnn回购中找不到
tf.RegisterGradient
,所以我想知道是否可能只通过py_func而不使用
tf.RegisterGradient
,或者跳过层
tf.RegisterGradient
是核心TensorFlow的一部分,请尝试
帮助(tf.RegisterGradient)
在Python shellok中,我发现更快的R-CNN repo中的
tf.py_func
的梯度无法传递,但一些损失是由
tf.py_func
之前的值计算出来的。因此,即使
tf.py_func
的梯度为零,在
tf.py_func
之前的权重也可以更新。为什么在
addone_grad
中返回
x
而不是返回
grad
?您可以返回grad,这只是一个非标准梯度的例子