Python Tensorflow不能得到变量的梯度,但可以得到张量
我感兴趣的是计算一个损失的梯度,这个梯度是由TensorFlow中的矩阵乘法的乘积计算出来的。如果乘积是作为张量计算的,我可以这样做,但如果它是Python Tensorflow不能得到变量的梯度,但可以得到张量,python,tensorflow,eager-execution,Python,Tensorflow,Eager Execution,我感兴趣的是计算一个损失的梯度,这个梯度是由TensorFlow中的矩阵乘法的乘积计算出来的。如果乘积是作为张量计算的,我可以这样做,但如果它是assign()ed,则不能这样做。以下是大大简化的代码: import tensorflow as tf import numpy as np tf.enable_eager_execution() multipliers_net = tf.get_variable("multipliers", shape=(1, 3, 3, 1),
assign()
ed,则不能这样做。以下是大大简化的代码:
import tensorflow as tf
import numpy as np
tf.enable_eager_execution()
multipliers_net = tf.get_variable("multipliers", shape=(1, 3, 3, 1),
initializer=tf.random_normal_initializer())
activations_net = tf.Variable(tf.ones_like(multipliers_net))
output_indices = [(0, 1, 2, 0)]
def step():
global activations_net
#### PROBLEMATIC ####
activations_net.assign(multipliers_net * activations_net)
#### NO PROBLEM ####
# activations_net = multipliers_net * activations_net
return tf.gather_nd(activations_net, output_indices)
def train(targets):
for y in targets:
with tf.GradientTape() as tape:
out = step()
print("OUT", out)
loss = tf.reduce_mean(tf.square(y - out))
print("LOSS", loss)
de_dm = tape.gradient(loss, multipliers_net)
print("GRADIENT", de_dm, sep="\n")
multipliers_net.assign(LEARNING_RATE * de_dm)
targets = [[2], [3], [4], [5]]
train(targets)
目前,此代码将显示正确的OUT和LOSS值,但渐变将打印为None。但是,如果对“PROBLEM”下面的行进行了注释,而对“NO PROBLEM”未进行注释,那么梯度的计算就可以了。我推断这是因为在第二种情况下,activations\u net
变成了一个张量,但我不知道为什么会突然使梯度变得可计算,而以前不是
我很确定我应该把
activations\u net
和multiplier\u net
作为变量,因为在更大的情况下,两者都是动态更新的,据我所知,这些东西最好作为变量保存,而不是不断地重新分配张量。我将尽力解释。
该问题发生在该生产线的一个生产线中
de_dm = tape.gradient(loss, multipliers_net)
如果在“有问题”和“没有问题”两种情况下都打印(tape.wasted_variables()),您将看到在第一种情况下,磁带会两次“监视”相同的乘数。
您可以尝试tape.reset()
和tape.watch()
,但只要您将assign op传递给它,它就没有效果。
如果您尝试在tf.GradientTape()
中使用multipliers\u net.assign(任何变量)
,您会发现它不起作用。但是如果您尝试分配产生张量的东西,例如tf.ones\u like()
,它会起作用
multipliers_net.assign(LEARNING_RATE * de_dm)
这是出于同样的原因。它似乎只接受eager\u张量
希望这能有所帮助看起来assign
op没有梯度,不管你在分配什么…是的。我实际上有点混淆了它的行为,尤其是eager.Variable.assign,它应该可以工作,但它不工作。read\u value参数也可以。但我认为只要你做乘法器\u net.assign
你就会得到一个resourceVariable这就是你想要的