Tensorflow 2.0不计算梯度

时间:2019-07-06 17:38:51

标签: python tensorflow conv-neural-network gradient-descent

我想可视化CNN中给定特征图学习的模式(在本例中,我使用的是vgg16)。为此,我创建了一个随机图像,通过网络馈送至所需的卷积层,选择特征图并找到相对于输入的梯度。想法是,以最大程度激活所需特征图的方式更改输入。使用tensorflow 2.0,我有一个GradientTape跟随该函数然后计算梯度,但是该梯度返回None,为什么它无法计算梯度?<​​/ p>

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)

3 个答案:

答案 0 :(得分:1)

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

此外,我不确定索引(pic[0])是否会起作用,因此您可能要删除它-因为pic在第一个维度中只有一个条目,因此不应反正很重要。

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

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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