Tf 2.0 : RuntimeError: GradientTape.gradient 只能在非持久性磁带上调用一次
Posted
技术标签:
【中文标题】Tf 2.0 : RuntimeError: GradientTape.gradient 只能在非持久性磁带上调用一次【英文标题】:Tf 2.0 : RuntimeError: GradientTape.gradient can only be called once on non-persistent tapes 【发布时间】:2019-09-28 01:40:41 【问题描述】:在tensorflow 2.0 guide 的 tf 2.0 DC Gan 示例中,有两个渐变磁带。见下文。
@tf.function
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as gen_tape, tf.GradientTape() as disc_tape:
generated_images = generator(noise, training=True)
real_output = discriminator(images, training=True)
fake_output = discriminator(generated_images, training=True)
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)
gradients_of_generator = gen_tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = disc_tape.gradient(disc_loss, discriminator.trainable_variables)
generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))
您可以清楚地看到有两个渐变胶带。我想知道使用单个磁带有什么不同,并将其更改为以下内容
@tf.function
def train_step(images):
noise = tf.random.normal([BATCH_SIZE, noise_dim])
with tf.GradientTape() as tape:
generated_images = generator(noise, training=True)
real_output = discriminator(images, training=True)
fake_output = discriminator(generated_images, training=True)
gen_loss = generator_loss(fake_output)
disc_loss = discriminator_loss(real_output, fake_output)
gradients_of_generator = tape.gradient(gen_loss, generator.trainable_variables)
gradients_of_discriminator = tape.gradient(disc_loss, discriminator.trainable_variables)
generator_optimizer.apply_gradients(zip(gradients_of_generator, generator.trainable_variables))
discriminator_optimizer.apply_gradients(zip(gradients_of_discriminator, discriminator.trainable_variables))
这给了我以下错误:
RuntimeError: GradientTape.gradient can only be called once on non-persistent tapes.
我想知道为什么需要两盘磁带。 到目前为止,关于 tf2.0 API 的文档很少。任何人都可以解释或指出正确的文档/教程吗?
【问题讨论】:
【参考方案1】:来自GradientTape
的documentation:
默认情况下,GradientTape 持有的资源会在 GradientTape.gradient() 方法被调用时立即释放。要在同一计算中计算多个梯度,请创建一个持久梯度磁带。这允许对 gradient() 方法进行多次调用,因为当磁带对象被垃圾回收时会释放资源。
可以使用with tf.GradientTape(persistent=True) as tape
创建持久渐变,并且可以/应该使用del tape
手动删除(此@zwep、@Crispy13 的功劳)。
【讨论】:
出于实用目的,您可以通过定义tf.GradientTape(persistent=True)
来做到这一点
这应该被接受。对了,用tape
后,做del tape
。【参考方案2】:
技术原因是gradient
被调用了两次,这在(非持久性)磁带上是不允许的。
然而,在目前的情况下,根本原因是 GANS 的训练通常是通过交替优化生成器和判别器来完成的。每个优化都有自己的优化器,通常对不同的变量进行操作,现在即使是最小化的损失也不同(代码中的gen_loss
和disc_loss
)。
所以你最终会得到两个梯度,因为训练 GAN 本质上是以交替的方式优化两个不同的(对抗性)问题。
【讨论】:
以上是关于Tf 2.0 : RuntimeError: GradientTape.gradient 只能在非持久性磁带上调用一次的主要内容,如果未能解决你的问题,请参考以下文章
RuntimeError: `set_session` 在使用 TensorFlow 2.0 时不可用
如何在 Tensorflow-2.0 中绘制 tf.keras 模型?