GradientTape丢失变量的轨迹

时间:2019-07-26 19:01:38

标签: python-3.x tensorflow tensorflow2.0

我有一个脚本,可以执行类似Gatys的神经样式转换。它使用样式损失和总的变化损失。我正在使用GradientTape()计算我的渐变。我实现的损失似乎工作得很好,但是GradientTape()并不能适当地弥补我添加的新损失。

我怀疑这与我如何根据输入变量计算损失有关。输入是一个4D张量(批,h,w,通道)。在最基本的层次上,输入是浮点图像,为了计算此新损耗,我需要将其转换为二进制图像,以计算一种像素颜色与另一种像素颜色的比率。我不想在每次迭代期间都去改变像这样的图像,所以我只是制作张量的副本(以numpy形式)并对其进行运算以计算损失。我不了解GradientTape的局限性,但我相信它是输入变量如何转换为numpy数组时如何“丢失”线程的方法。

我可以复制图像张量并使用该图像执行二值化操作和损耗计算吗?还是我要tensorflow做它做不到的事情?

我新的损失函数:

def compute_loss(self, **kwargs):
   loss = 0
   image = self.model.deprocess_image(kwargs['image'].numpy())
   binarized_image = self.image_decoder.binarize_image(image)
   volume_fraction = self.compute_volume_fraction(binarized_image)
   loss = np.abs(self.volume_fraction_target - volume_fraction)
   return loss

我使用GradientTape的实现:

def compute_grads_and_losses(self, style_transfer_state):
        """
        Computes gradients with respect to input image
        """
        with tf.GradientTape() as tape:
            loss = self.loss_evaluator.compute_total_loss(style_transfer_state)
        total_loss = loss['total_loss']
        return tape.gradient(total_loss, style_transfer_state['image']), loss

我认为一个例子可以说明我的困惑。最奇怪的是,我的代码运行没有问题。它似乎并没有使新的损失项最小化。但是此示例甚至由于以下属性错误而无法运行:AttributeError: 'numpy.float64' object has no attribute '_id'

示例:

import tensorflow.contrib.eager as tfe
import tensorflow as tf

def compute_square_of_value(x):
    a = turn_to_numpy(x['x'])
    return a**2

def turn_to_numpy(arg):
    return arg.numpy() #just return arg to eliminate the error

tf.enable_eager_execution()
x = tfe.Variable(3.0, dtype=tf.float32)
data_dict = {'x': x}
with tf.GradientTape() as tape:
  tape.watch(x)
  y = compute_square_of_value(data_dict)

dy_dx = tape.gradient(y, x) # Will compute to 6.0

print(dy_dx)

1 个答案:

答案 0 :(得分:2)

这里的第一个问题是GradientTape仅跟踪tf.Tensor对象上的操作。当您调用tensor.numpy()时,在那里执行的操作不在磁带之内。

第二个问题是您的第一个示例从未在要区分的图像上调用tape.watche。