这是使用 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.RegisterGradient
和 gradient_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()