TF1 中的渐变到 TF2 中的 GradientTape

Posted

技术标签:

【中文标题】TF1 中的渐变到 TF2 中的 GradientTape【英文标题】:Gradient in TF1 to GradientTape in TF2 【发布时间】:2022-01-11 01:22:27 【问题描述】:

我正在实现本书“使用python的深度学习”第05章中的示例。

我知道我可以通过 disable_eager_execution() 禁用 Eager,但这是我的第二选择。

这里是示例代码:

from tensorflow.keras.applications import VGG16
from tensorflow.keras import backend as K
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np

def deprocess_image(x):
    x -= x.mean()
    
    x /= (x.std()+ 1e-5)
    x *= 0.1
    x += 0.5
    x = np.clip(x, 0, 1)
    x *= 255
    x = np.clip(x, 0, 255).astype('uint8')

    return x



def generate_pattern(layer_name, filter_index, size = 150):
    layer_output = model.get_layer(layer_name).output
    loss = K.mean(layer_output[:, :, :, filter_index])
    grads = K.gradients(loss, model.input)[0]                       <------- here
    grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
    iterate = K.function([model.input], [loss, grads])
    input_img_data = np.random.random((1, size, size, 3)) * 20 + 128.
    step = 1.
    for i in range(40):
        loss_value, grads_value = iterate([input_img_data])
        input_img_data += grads_value * step
    img = input_img_data[0]
    return deprocess_image(img)

def generate_pattern_grid(layer_name):
    size = 64
    margin = 5

    results = np.zeros((8 * size + 7 * margin, 8 * size + 7 * margin, 3))
    for i in range(8):
        for j in range(8):
            filter_img = generate_pattern(layer_name, i + (j * 8), size = size)

            horizontal_start = i * size + i * margin
            horizontal_end = horizontal_start + size
            vertical_start = j * size + j * margin
            vertical_end = vertical_start + size

            results[horizontal_start : horizontal_end, 
                   vertical_start : vertical_end, :] = filter_img

    plt.figure(figsize = (20, 20))
    plt.imshow(results.astype('uint8'))


model = VGG16(weights = "imagenet",
             include_top=False)

layer_name = "block3_conv1"

generate_pattern_grid(layer_name)

这会给我

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

我已经阅读了doc 并试试这个:

def generate_pattern(layer_name, filter_index, size = 150):
    layer_output = model.get_layer(layer_name).output
    loss = K.mean(layer_output[:, :, :, filter_index])
    with tf.GradientTape() as tape:
        loss = K.mean(layer_output[:, :, :, filter_index])
    grads = tape.gradient(loss, model.input)
    grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)
    iterate = K.function([model.input], [loss, grads])
    input_img_data = np.random.random((1, size, size, 3)) * 20 + 128.
    step = 1.
    for i in range(40):
        loss_value, grads_value = iterate([input_img_data])
        input_img_data += grads_value * step
    img = input_img_data[0]
    return deprocess_image(img)

但是得到了

AttributeError: 'KerasTensor' object has no attribute '_id'

有什么解决办法吗?

我想如果有任何方法可以将 kerasTensor 转换为 tfTensor,那么我可能会解决这个问题,但我找不到。

【问题讨论】:

这能回答你的问题吗? tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead @OmG 我已经读过,但我不知道如何在我的情况下实现它。 【参考方案1】:

Tf.gradients 在 Tensorflow v2 中已弃用。正如错误消息所说,使用tf.GradientTape 代替 Tf.gradient。欲了解更多信息,请访问tf.GradientTape

对于 TensorFlow v1,禁用急切执行。

看看tf.GradientTape for Keras users。

【讨论】:

以上是关于TF1 中的渐变到 TF2 中的 GradientTape的主要内容,如果未能解决你的问题,请参考以下文章

TensorFlow 和 Keras 入门:过去 (TF1) 现在 (TF2)

Tf 2.0 : RuntimeError: GradientTape.gradient 只能在非持久性磁带上调用一次

Tensorflow1 和 Tensorflow2 中的批处理

css3中的gradient详细用法

Internet Explorer 9 中的渐变

字体渐变