【发布时间】:2019-07-26 19:01:38
【问题描述】:
我有一个执行类似 Gatys 的神经风格迁移的脚本。它使用样式损失和总变化损失。我正在使用 GradientTape() 来计算我的渐变。我实施的损失似乎工作正常,但我添加的一个新损失没有被 GradientTape() 正确解释。我正在使用启用了 Eager Execution 的 TensorFlow。
我怀疑这与我如何根据输入变量计算损失有关。输入是一个 4D 张量(batch, h, w, channels)。在最基本的层面上,输入是一个浮点图像,为了计算这个新的损失,我需要将它转换为一个二值图像来计算一个像素颜色与另一个像素颜色的比率。我不想在每次迭代期间都去改变图像,所以我只是制作张量的副本(以 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)
编辑:
根据我目前的理解,出现的问题是我使用 .numpy() 操作导致梯度磁带无法跟踪计算梯度的变量。我这样做的最初原因是因为我的损失操作需要我在物理上更改张量的值,并且我不想实际更改用于正在优化的张量的值。因此,使用 numpy() 副本来处理以正确计算损失。有没有办法解决?还是因为必须对输入张量执行基本不可逆操作的限制,我是否应该认为我的损失计算无法实现?
【问题讨论】:
标签: python-3.x tensorflow tensorflow2.0