我对计算损耗的梯度感兴趣,该梯度是根据TensorFlow与Eager Execution中的矩阵乘法乘积计算得出的。如果乘积计算为张量,则可以这样做,但是如果将其assign()
固定在变量中,则不能这样做。这是精巧的简化代码:
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值,但GRADIENT将显示为None 。但是,如果注释了“ PROBLEMATIC”下方的行,并且未对“ NO PROBLEM”进行注释,则可以很好地计算出梯度。我推断这是因为在第二种情况下,activations_net
成为张量,但我不知道为什么突然使梯度可计算,而之前却不是。
我非常确定我应该将activations_net
和multiplier_net
保留为变量,因为在较大的方案中,两者都是动态更新的,并且据我所知,最好将它们保留为变量,而不是不断地重新分配张量。
答案 0 :(得分:1)
我将尽我所能解释。 该行中出现问题
de_dm = tape.gradient(loss, multipliers_net)
如果在“有问题”和“没有问题”两种情况下print(tape.watched_variables()
,您都会看到在第一种情况下,磁带“监视”相同的multipliers_net
变量两次。
您可以尝试tape.reset()
和tape.watch()
,但是只要您将assign op传递给它,它就不会起作用。
如果您在multipliers_net.assign(any_variable)
内尝试tf.GradientTape()
,则会发现它不起作用。但是如果您尝试分配产生张量的东西,例如tf.ones_like()
,它将起作用。
multipliers_net.assign(LEARNING_RATE * de_dm)
这是出于相同的原因。似乎只接受eager_tensors
希望对您有帮助