接着我上一个问题,我想研究一下当一个监视变量在计算中被多次使用时,特别是当一个神经元有一个输入时 GradientTape 会做什么......
接着 我之前的问题 ,我想研究一下当一个监视变量在计算中被多次使用时,GradientTape 会做什么,特别是当一个神经元的输入来自它自己的输出时。
我创建了这个最小演示,其中有一个神经元,有两个输入 - 一个来自外部,一个来自其自身的输出。其输出计算两次。
import tensorflow as tf
@tf.function
def one_training_step(X, y, loss_fn, activation_fn):
with tf.GradientTape() as tape:
out = tf.zeros((1,1))
for _ in range(2):
a = tf.concat(axis=1, values=[X, out])
out = activation_fn(a @ w + b)
loss_value = loss_fn(y_true=y, y_pred=out)
grads = tape.gradient(loss_value, [w, b])
tf.print(f"Watched: {tape.watched_variables()}")
tf.print(f"Grads: {grads}")
X = tf.constant([[1.0]], dtype=float, name='X')
y = tf.constant([[1.0]], dtype=float, name='y')
w = tf.Variable([[2.0], [3.0]], dtype=float, name='w')
b = tf.Variable([[4.0]], dtype=float, name='b')
activation_fn = tf.keras.activations.get('sigmoid')
loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=False)
one_training_step(X, y, loss_fn, activation_fn)
这将打印以下内容:
Watched: (<tf.Variable 'w:0' shape=(2, 1) dtype=float32>, <tf.Variable 'b:0' shape=(1, 1) dtype=float32>)
Grads: [<tf.Tensor 'AddN_1:0' shape=(2, 1) dtype=float32>, <tf.Tensor 'AddN_2:0' shape=(1, 1) dtype=float32>]
这并没有告诉我发生了什么。我不明白为什么权重的梯度现在被记录为加法(而不是在没有递归时记录为乘法)。
我真正想要看到的是所有记录的可微分步骤的列表,这样我就能知道即使在这种复发的情况下,GradientTape 是否也能正确应用它们。