Tensorflow 2.0 不计算梯度

Tensorflow 2.0 doesn't compute the gradient

我想可视化 CNN 中给定特征图所学习的模式(在本例中我使用的是 vgg16)。为此,我创建了一个随机图像,通过网络提供给所需的卷积层,选择特征图并找到与输入相关的梯度。这个想法是以最大化激活所需特征图的方式改变输入。使用tensorflow 2.0我有一个GradientTape跟随函数然后计算梯度,但是梯度returns None,为什么它无法计算梯度?

import tensorflow as tf
import matplotlib.pyplot as plt
import time
import numpy as np
from tensorflow.keras.applications import vgg16

class maxFeatureMap():

    def __init__(self, model):

        self.model = model
        self.optimizer = tf.keras.optimizers.Adam()

    def getNumLayers(self, layer_name):

        for layer in self.model.layers:
            if layer.name == layer_name:
                weights = layer.get_weights()
                num = weights[1].shape[0]
        return ("There are {} feature maps in {}".format(num, layer_name))

    def getGradient(self, layer, feature_map):

        pic = vgg16.preprocess_input(np.random.uniform(size=(1,96,96,3))) ## Creates values between 0 and 1
        pic = tf.convert_to_tensor(pic)

        model = tf.keras.Model(inputs=self.model.inputs, 
                               outputs=self.model.layers[layer].output)
        with tf.GradientTape() as tape:
            ## predicts the output of the model and only chooses the feature_map indicated
            predictions = model.predict(pic, steps=1)[0][:,:,feature_map]
            loss = tf.reduce_mean(predictions)
        print(loss)
        gradients = tape.gradient(loss, pic[0])
        print(gradients)
        self.optimizer.apply_gradients(zip(gradients, pic))

model = vgg16.VGG16(weights='imagenet', include_top=False)


x = maxFeatureMap(model)
x.getGradient(1, 24)

这是 GradientTape 的一个常见陷阱;磁带仅跟踪设置为 "watched" 的张量,默认情况下磁带将仅监视可训练变量(意味着 tf.Variable 使用 trainable=True 创建的对象)。要查看 pic 张量,您应该添加 tape.watch(pic) 作为磁带上下文中的第一行。

此外,我不确定索引 (pic[0]) 是否有效,因此您可能想要删除它——因为 pic 在第一维中只有一个条目,它应该反正没关系。

此外,您不能使用 model.predict,因为此 returns 是一个 numpy 数组,它基本上是 "destroys" 计算图链,因此不会反向传播梯度。您应该简单地将模型用作可调用对象,即 predictions = model(pic).

你有没有定义自己的损失函数?您是否在损失函数中将张量转换为 numpy?

作为大一新生,我也遇到了同样的问题: 当使用 tape.gradient(loss, variables) 时,结果是 None 因为我在自己的损失函数中将张量转换为 numpy 数组。这似乎是一个愚蠢但对新生来说很常见的错误。

仅供参考:当 GradientTape 不工作时,可能是 TensorFlow 问题。如果正在使用的 TF 函数存在已知问题,则检查 TF github 将是问题确定之一。