【问题标题】:tf.gradients() won't work with 'tf.assign()', but works with '='tf.gradients() 不适用于 'tf.assign()',但适用于 '='
【发布时间】:2018-01-13 17:48:30
【问题描述】:

在下面的简单代码中,梯度得到正确计算。

import tensorflow as tf

x = tf.constant([1, 2, 3, 4], dtype=tf.float32)
y = tf.Variable(tf.ones_like(x), dtype=tf.float32)

y = 2*x
grad = tf.gradients(y, x)

ini = tf.global_variables_initializer()


with tf.Session() as ses:
    ses.run(ini)
    print(ses.run(grad))

正如预期的那样,结果是[array([ 2., 2., 2., 2.], dtype=float32)]。 尝试使用 tf.assign 进行函数计算时遇到问题。以下代码:

import tensorflow as tf

x = tf.constant([1, 2, 3, 4], dtype=tf.float32)
y = tf.Variable(tf.ones_like(x), dtype=tf.float32)

func = tf.assign(y, 2*x)
grad = tf.gradients(y, x)

ini = tf.global_variables_initializer()

with tf.Session() as ses:
    ses.run(ini)
    ses.run(func)
    print(ses.run(grad))

... 产生错误:

TypeError: Fetch argument None 的类型无效<class 'NoneType'>

为什么会这样? xy 节点之间的连接是否通过 tf.assign 操作“丢失”了?

【问题讨论】:

    标签: python tensorflow graph autograd


    【解决方案1】:

    在第二个示例中,xy 之间没有依赖关系。 func 是一个依赖于两者的操作,并且恰好修改了y。如果你检查对应的tf.assign op,你会看到:

    op: "Assign"
    input: "Variable"   # this is y
    input: "mul"        # this is 2*x
    

    但是xy是独立的,这就是引擎无法采用梯度的原因。

    【讨论】:

    • 马克西姆,谢谢您的回答!我可以要求再澄清一下吗?在梯度计算的情况下,我通常是否应该期望一个函数不是图形节点,就像我上面的第一段代码一样?这有点违反直觉,因为我假设图表应该包含所有关键计算......这让我有点困惑什么应该和不应该在图表中。
    • @Broono 在张量流方面,每个节点都是一个操作(简称:op)。该变量也是一组操作:读/写/初始化。您对 function 的看法是更高级别的抽象。所以这样说比较好:assign op是一个图节点,可以运行。
    • 我明白了……显然我需要在图形架构上映射逻辑流。感谢您的回答!