对于y = x ** 2,如果从TensorArray中检索到x,则不会计算梯度dy_dx。
如何将x和y操作存储在TensorArray中,然后检索它们,并调用tf.gradients来计算渐变?
用例是:一个构建一个while_loop,在迭代中生成一堆不同的值(即x,y),它们被推入TensorArrays,然后在循环之外我想获得导数一个数组相对于另一个数组。
说明问题的示例:
import tensorflow as tf
import numpy as np
x = tf.Variable(np.array([3]).astype(np.float32), trainable=False)
y = x ** 2
xa = tf.TensorArray(tf.float32, 1).write(0, x)
ya = tf.TensorArray(tf.float32, 1).write(0, y)
sess = tf.Session()
sess.run(tf.global_variables_initializer())
# these work as expected:
print(sess.run(tf.gradients(y, x))) # stdout: [array([ 6.], dtype=float32)]
print(sess.run(tf.gradients(ya.stack(), x))) # stdout: [array([ 6.], dtype=float32)]
# why no gradient?
print(tf.gradients(ya.stack(), xa.stack())) # stdout: [None]
print(tf.gradients(ya.read(0), xa.read(0))) # stdout: [None]
# desperate attempt, doesn't work either
za = tf.TensorArray(tf.float32, 1).write(0, xa.read(0) ** 2)
print(tf.gradients(za.read(0), xa.read(0))) # stdout: [None]
答案 0 :(得分:1)
原因是函数tf.gradients
用词不当。实际上,tf.gradients实现了backprop算法;并且只能在图中连接在一起的节点之间提供梯度计算。因为ya绝不依赖于xa,所以没有连接,backprop不起作用。该示例将提供渐变:
x = tf.Variable(np.array([3]).astype(np.float32), trainable=False)
y = x ** 2
xa = tf.TensorArray(tf.float32, 1).write(0, x)
ya = tf.TensorArray(tf.float32, 1).write(0, xa.read(0))
tf.gradients(ya.stack(), x)
但以下不会:
y = x ** 2
z = x + 1
tf.gradients(y, z) # None
因为从z到y没有DAG路径。
后一个示例与您在问题中尝试的内容更相似。