Tensorflow 2.0 не вычисляет градиент - PullRequest
2 голосов
/ 06 июля 2019

Я хочу визуализировать шаблоны, которые изучила данная карта объектов в CNN (в этом примере я использую vgg16).Для этого я создаю случайное изображение, пропускаю по сети до нужного сверточного слоя, выбираю карту объектов и нахожу градиенты относительно входных данных.Идея состоит в том, чтобы изменить входные данные таким образом, чтобы максимизировать активацию нужной карты объектов.Используя тензор потока 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)

1 Ответ

1 голос
/ 06 июля 2019

Это распространенная ошибка с GradientTape; лента отслеживает только те тензоры, которые установлены как «наблюдаемые», и по умолчанию ленты будут наблюдать только обучаемые переменные (то есть tf.Variable объекты, созданные с trainable=True). Чтобы посмотреть тензор pic, вы должны добавить tape.watch(pic) в качестве самой первой строки в контексте ленты.

Кроме того, я не уверен, сработает ли индексация (pic[0]), поэтому вы можете удалить это - поскольку pic имеет только одну запись в первом измерении, это не должно иметь значения в любом случае.

Более того, вы не можете использовать model.predict, потому что это возвращает пустой массив, который в основном "разрушает" цепочку вычислительных графов, так что градиенты не будут распространяться обратно. Вы должны просто использовать модель как вызываемую, то есть predictions = model(pic).

...