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 将是问题确定之一。
我想可视化 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 将是问题确定之一。