如何通过tf.while_loop计算反向传播以用作损失函数

时间:2019-09-17 15:39:35

标签: python-3.x tensorflow

我想对两个图像实施傅立叶环相关损失,以训练GAN。因此,我想循环特定的时间并计算损失。这对于正常的Python循环来说效果很好。为了加快此过程,我想使用tf.while_loop,但不幸的是,我无法通过while循环跟踪渐变。我构建了一个虚拟示例,只是为了在while循环中计算梯度,但是它不起作用。首先,有效的python循环:

x = tf.constant(3.0)
y = tf.constant(2.0)

for i in range(3):    
    y = y * x

grad = tf.gradients(y, x) 
with tf.Session() as ses:
    print("output : ", ses.run(grad))

这有效并提供了输出

[54]

如果我对tf.while_loop做同样的操作,将无法正常工作:

a = tf.constant(0, dtype = tf.int64)
b = tf.constant(3, dtype = tf.int64)

x = tf.constant(3.0)
y = tf.constant(2.0)

def cond(a,b,x,y):
    return tf.less(a,b)

def body(a,b,x,y):

    y = y * x 
    with tf.control_dependencies([y]):
        a = a + 1
    return [a,b,x,y]

results = tf.while_loop(cond, body, [a,b,x,y], back_prop = True)

grad = tf.gradients(y, results[2])

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

输出为:

  

TypeError:获取参数None具有无效的类型'<'class'NoneType'>

所以我猜想tensorflow无法以某种方式进行反向传播。

如果使用tf.GradientTape()而不是tf.gradients(),问题仍然会出现。

1 个答案:

答案 0 :(得分:0)

我更改了代码,以便现在可以输出渐变:

import tensorflow as tf

a = tf.constant(0, dtype = tf.int64)
b = tf.constant(3, dtype = tf.int64)

x = tf.Variable(3.0, tf.float32)
y = tf.Variable(2.0, tf.float32)
dy = tf.Variable(0.0, tf.float32)

def cond(a,b,x,y,dy):
    return tf.less(a,b)

def body(a,b,x,y,dy):

    y = y * x 
    dy = tf.gradients(y, x)[0]
    with tf.control_dependencies([y]):
        a = a + 1
    return [a,b,x,y,dy]

init = tf.global_variables_initializer()

with tf.Session() as ses:
    ses.run(init)
    results = ses.run(tf.while_loop(cond, body, [a,b,x,y,dy], back_prop = True))
    print("grad : ", results[-1])

我修改过的东西

  1. 我将xy制成了变量,并添加了它们的初始化init
  2. 我添加了一个名为dy的变量,它将包含y的梯度。
  3. 我在会议期间移动了tf.while_loop
  4. 将对身体功能的梯度求值

我认为以前的问题是,当您定义grad = tf.gradients(y, results[2])时,循环尚未运行,因此y不是x的函数。因此,没有渐变。

希望这会有所帮助。