Tensorflow 2.0 不计算梯度

Wil*_*ill 8 python gradient-descent conv-neural-network tensorflow

我想可视化 CNN 中给定特征图所学的模式(在本例中,我使用的是 vgg16)。为此,我创建了一个随机图像,通过网络馈送到所需的卷积层,选择特征图并找到相对于输入的梯度。这个想法是以这样一种方式改变输入,以最大化所需特征图的激活。使用 tensorflow 2.0 我有一个 GradientTape 跟随函数然后计算梯度,但是梯度返回 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)
Run Code Online (Sandbox Code Playgroud)

xdu*_*ch0 15

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

另外,我不确定索引 ( pic[0]) 是否有效,因此您可能想要删除它——因为pic在第一维中只有一个条目,无论如何都无关紧要。

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