首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >GradientTape丢失变量的跟踪

GradientTape丢失变量的跟踪
EN

Stack Overflow用户
提问于 2019-07-27 03:01:38
回答 1查看 933关注 0票数 1

我有一个脚本,可以执行类似Gatys的神经样式转换。它使用样式损失和总变化损失。我正在使用GradientTape()来计算我的梯度。我实现的损失似乎工作得很好,但是我添加的一个新损失没有被GradientTape()正确地说明。我使用的是启用了急切执行的TensorFlow。

我怀疑这与我如何根据输入变量计算损失有关。输入是4D张量(batch,h,w,channels)。在最基本的级别上,输入是浮点图像,为了计算这种新的损失,我需要将其转换为二进制图像,以计算一个像素颜色与另一个像素颜色的比率。我不想在每次迭代中像这样改变图像,所以我只复制张量(以numpy形式),并对其进行操作来计算损失。我不理解GradientTape的局限性,但我认为它正在“失去主线”,即当输入变量被转换为numpy数组时,如何使用它来弥补损失。

我可以复制图像张量并使用它执行二值化操作和损失计算吗?或者我是在要求tensorflow做它不能做的事情?

我的新损失函数:

代码语言:javascript
复制
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的实现:

代码语言:javascript
复制
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'

示例:

代码语言:javascript
复制
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)

编辑:

根据我目前的理解,出现的问题是我使用.numpy()操作使梯度带失去了计算梯度的变量的跟踪。我这样做的最初原因是因为我的损失操作需要我物理上更改张量的值,而我不想实际更改用于正在优化的张量的值。因此,为了正确计算损失,需要使用numpy()副本。有什么办法可以解决这个问题吗?或者,我是否应该认为我的损失计算是不可能实现的,因为必须在输入张量上执行本质上不可逆的操作?

EN

回答 1

Stack Overflow用户

发布于 2019-08-17 04:25:22

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

第二个问题是,您的第一个示例从未对您想要区分的映像调用tape.watche。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57225716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档