我有兴趣计算损失的梯度,该梯度是根据 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
作为变量,因为在更大的方案中,两者都是动态更新的,据我所知,最好将这些东西保留为变量,而不是不断地重新分配张量。