Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/355.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 急切模式下的张量流梯度返回零_Python_Tensorflow_Eager Execution - Fatal编程技术网

Python 急切模式下的张量流梯度返回零

Python 急切模式下的张量流梯度返回零,python,tensorflow,eager-execution,Python,Tensorflow,Eager Execution,问题:我正在从保存的检查点加载一个简单的VGG16。我想在推理过程中生成图像的显著性。当我计算这个所需的梯度(丢失wrt输入图像)时,我得到的所有梯度都是零。任何关于我在这里缺少什么的想法都非常感谢 tf版本:tensorflow-2.0alpha-gpu 模型: import tensorflow as tf from tensorflow.keras.applications.vgg16 import VGG16 as KerasVGG16 from tensorflow.keras.mod

问题:我正在从保存的检查点加载一个简单的VGG16。我想在推理过程中生成图像的显著性。当我计算这个所需的梯度(丢失wrt输入图像)时,我得到的所有梯度都是零。任何关于我在这里缺少什么的想法都非常感谢

tf版本:
tensorflow-2.0alpha-gpu

模型:

import tensorflow as tf
from tensorflow.keras.applications.vgg16 import VGG16 as KerasVGG16
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Flatten, Dense

class VGG16(Model):

    def __init__(self, num_classes, use_pretrained=True):

        super(VGG16, self).__init__()
        self.num_classes = num_classes
        self.use_pretrained = use_pretrained

        if use_pretrained:
            self.base_model = KerasVGG16(weights='imagenet', include_top=False)
            for layer in self.base_model.layers:
                layer.trainable = False
        else:
            self.base_model = KerasVGG16(include_top=False)

        self.flatten1 = Flatten(name='flatten')
        self.dense1 = Dense(4096, activation='relu', name='fc1')
        self.dense2 = Dense(100, activation='relu', name='fc2')
        self.dense3 = Dense(self.num_classes, activation='softmax', name='predictions')

    def call(self, inputs):

        x = self.base_model(tf.cast(inputs, tf.float32))
        x = self.flatten1(x)
        x = self.dense1(x)
        x = self.dense2(x)
        x = self.dense3(x)
        return x
我训练此模型并将其保存到检查点,然后通过以下方式将其加载回:

model = VGG16(num_classes=2, use_pretrained=False)
checkpoint = tf.train.Checkpoint(net=model)
        status = checkpoint.restore(tf.train.latest_checkpoint('./my_checkpoint'))
status.assert_consumed()
我验证砝码是否正确加载

获取测试图像

# load my image and make sure its float
img = tf.convert_to_tensor(image, dtype=tf.float64)
support_class = tf.convert_to_tensor(support_class, dtype=tf.float64)
获取渐变:

with tf.GradientTape(persistent=True) as g_tape:
    g_tape.watch(img)
    #g_tape.watch(model.base_model.trainable_variables)
    #g_tape.watch(model.trainable_variables)
    loss = tf.losses.CategoricalCrossentropy()(support_class, model(img))    
    gradients_wrt_image = g_tape.gradient(loss,
                                    img, unconnected_gradients=tf.UnconnectedGradients.NONE)

当我检查我的梯度时,它们都是零!你知道我错过了什么吗?提前谢谢

梯度不是零,尽管它们非常小:

def几乎等于(a,b,十进制=6):
尝试:
np.testing.assert_几乎等于(a,b,decimal=decimal)
除断言错误外:
返回错误
返回真值
image=[abs(np.random.normal(大小=(32,32,3)))表示范围(20)]
label=[[0,1]如果i%3==0,则为范围(20)内的i指定[1,0]
img=tf.convert_to_tensor(图,dtype=tf.float64)
支持将类转换为张量(标签,dtype=tf.float64)
损失_fn=tf.loss.CategoricalCrossentropy()
使用tf.GradientTape(persistent=True)作为磁带:
磁带.手表(img)
softmaxed=型号(img)
损耗=损耗\u fn(支持类,软件最大化)
梯度=磁带梯度(损耗、img、未连接的梯度=tf.未连接的梯度。无)
#将所有坡度加总,并在所有尺寸上减少:
打印(tf.reduce_sum(梯度,轴=无).numpy())#0.07137820225818814
#与零相比:
zeros_like_grads=np.zeros_like(grads.numpy())
对于范围(10,0,-1)内的小数:
打印('decimal:{0}:{1}'。格式(十进制,
几乎等于(零就像梯度一样,
grads.numpy(),
十进制=十进制)
#小数点:10:False
#小数点:9:False
#小数点:8:False
#小数点:7:False
#小数点:6:False
#小数点:5:False
#小数点:4:False
#小数点:3:True
#小数点:2:True
#小数点:1:True

如您所见,仅从
decimal=3
开始,它开始返回
True

,因此,网络没有任何问题。这个问题与我在最后的
Dense
层中使用的softmax激活行为有关。我没有考虑过来自SoftMax的非常自信的预测(例如我的一个预测[〔1 0000000 E+00 00 950767 8E-25]〕会使梯度为零(理论上非常接近于零但实际上是零)。讨论此问题以及如何应对此问题的有用线程:


我的解决方案:当我想计算输入图像的梯度时,请关闭softmax激活

如何定义
支持类
?它只是一个热张量,例如,[[0.0,1.0]]为什么您认为梯度为零<代码>梯度=g_磁带梯度(损耗、img、未连接的梯度=tf.未连接的梯度。无);打印(tf.reduce_sum(梯度,轴=无))不打印零。它可能接近于零,但不是零zero@Vlad对不起,我的菲恩。是的,我也希望梯度不是零(并且接近零)。我对所有渐变进行了numpy检查,以查看其中是否有非零渐变。使用
image=[np.random.normal(size=(32,32,3))]
的代码,我不会得到零渐变。感谢@Vlad帮助调试网络。你的检查证实了网络是正确的。我贴出了一个答案,帮助我找回梯度:)@borarak很高兴听到这个消息。