我有一个脚本,可以执行类似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)
答案 0 :(得分:2)
这里的第一个问题是GradientTape仅跟踪tf.Tensor对象上的操作。当您调用tensor.numpy()时,在那里执行的操作不在磁带之内。
第二个问题是您的第一个示例从未在要区分的图像上调用tape.watche。