首页 > 解决方案 > opt.apply_gradients() 返回“尝试更新张量”错误

问题描述

我的问题如下:给定一个深度学习模型和一个损失函数,我想评估损失函数相对于模型输入的梯度,然后相应地更新输入。

我尝试解决这个问题的方法与本教程的“从头开始编写训练循环”非常相似;我必须更改评估梯度然后.apply_gradients()应用的变量。

这是我的代码:

target = 0.5 * np.ones(data1.shape)

optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)

epochs = 180

for epoch in range(epochs):
  with tf.GradientTape() as tape:
    data1 = tf.convert_to_tensor(data1)
    tape.watch(data1)
    logits = pred_block(data1, training=False)
    loss_value = tf.keras.losses.MSE(target, logits)
  grads = tape.gradient(loss_value, data1)
  optimizer.apply_gradients(zip(grads, data1))

GradientTape()范围内被data1转换为张量,然后被磁带监视,否则我无法获取关于 的梯度data1

但是,我收到以下错误:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py in apply_grad_to_update_var(var, grad)
    592       """Apply gradient to variable."""
    593       if isinstance(var, ops.Tensor):
--> 594         raise NotImplementedError("Trying to update a Tensor ", var)
    595 
    596       apply_kwargs = {}

NotImplementedError: ('Trying to update a Tensor ', <tf.Tensor: shape=(5,), dtype=float64, numpy=array([0.30344828, 0.30344828, 0.30344828, 0.        , 0.        ])>)

它所引用的张量是data1,因此我尝试将其转换为 a numpy.array。最后一行代码修改为:

optimizer.apply_gradients(zip(grads, np.array(data1)))

但我收到以下错误:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py in _prepare(self, var_list)
    782         var_devices = var._devices   # pylint: disable=protected-access
    783       else:
--> 784         var_devices = [var.device]
    785       var_dtype = var.dtype.base_dtype
    786       for var_device in var_devices:

AttributeError: 'numpy.ndarray' object has no attribute 'device'

如果我也转换,也会发生同样的情况grads

我想可能和形状有关data1,也就是(5756,5)因为给出的错误NotImplementedError: ('Trying to .... shape = (5,)),所以我试着给它加个维度data1。在打开for循环之前:

data1 = data1[:, np.newaxis, :] 

for epoch in range(epochs):
    ...

但是同样的错误信息会出现:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py in apply_grad_to_update_var(var, grad)
    592       """Apply gradient to variable."""
    593       if isinstance(var, ops.Tensor):
--> 594         raise NotImplementedError("Trying to update a Tensor ", var)
    595 
    596       apply_kwargs = {}

NotImplementedError: ('Trying to update a Tensor ', <tf.Tensor: shape=(1, 5), dtype=float64, numpy=array([[0.30344828, 0.30344828, 0.30344828, 0.        , 0.        ]])>)

即使将training标志从False更改为 也会True产生相同的错误。

我还尝试将代码的最后两行更改如下:

  grads = tape.gradient(loss_value, data1)
  grads = tf.distribute.get_replica_context().all_reduce('sum', grads)
  optimizer.apply_gradients(zip(grads, data1), 
                            experimental_aggregate_gradients=False) 

同样,同样的错误消息出现:

/usr/local/lib/python3.6/dist-packages/tensorflow/python/keras/optimizer_v2/optimizer_v2.py in apply_grad_to_update_var(var, grad)
    592       """Apply gradient to variable."""
    593       if isinstance(var, ops.Tensor):
--> 594         raise NotImplementedError("Trying to update a Tensor ", var)
    595 
    596       apply_kwargs = {}

NotImplementedError: ('Trying to update a Tensor ', <tf.Tensor: shape=(5,), dtype=float64, numpy=array([0.30344828, 0.30344828, 0.30344828, 0.        , 0.        ])>)

我做错了什么吗?

谢谢!

标签: pythontensorflowkerastensorflow2.0tf.keras

解决方案


如果你想更新你的输入,它应该是一个tf.Variable,而不是一个张量。优化器文档apply_gradients说明:

将渐变应用于变量。

tf.Variable您可以在指南中阅读更多信息:变量简介

用变量替换你的 data1 张量应该可以完成这项工作:

target = 0.5 * np.ones(data1.shape)
optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3)

epochs = 180
# the Variable must be created out out of the training loop
data_variable = tf.Variable(data1)


for epoch in range(epochs):
  with tf.GradientTape() as tape:
    tape.watch(data_variable)
    logits = pred_block(data_variable, training=False)
    loss_value = tf.keras.losses.MSE(target, logits)
  grads = tape.gradient(loss_value, data_variable)
  optimizer.apply_gradients(zip([grads], [data_variable]))

推荐阅读