tf.GradientTape 外积 returns None
tf.GradientTape with outer product returns None
我正在尝试在计算损失函数之前对模型的预测进行后处理,因为我的真实数据 (y_train) 是 NN 输出的外积。我已按照以下步骤操作:
- 我知道我尝试使用 numpy 进行的操作是:
nX = 201
nT = 101
nNNout = nX+nT
nBatch = 32
NNout = np.random.rand(nBatch, nNNout)
f = NNout[:, :nX]
g = NNout[:,nX:]
test = np.empty([nBatch, nX*nT])
for i in range(nBatch):
test[i,:] = np.outer(f[i,:], g[i,:]).flatten('F')
其中 NN 输出包含 f 和 g。我真正需要的是每个批处理实例的 f 和 g 外积的矢量化版本。
- 我在紧凑的张量流操作中将其翻译为:
test2 = tf.Variable([tf.reshape(tf.transpose(tf.tensordot(f[i,:],g[i,:], axes=0)),[nX*nT]) for i in range(nBatch)])
我已经检查过它是正确的,并且输出的值与步骤 1 中的值相同。
- 然后,我只是想在我的模型预测之后添加这个操作:
n_epochs = 20
batch_size = 32
n_steps = len(x_train) // batch_size
optimizer = keras.optimizers.Nadam(learning_rate=0.01)
loss_fn = keras.losses.mean_squared_error
mean_loss = keras.metrics.Mean()
metrics = [keras.metrics.MeanAbsoluteError()]
# ------------ Training ------------
for epoch in range(1, n_epochs + 1):
print("Epoch {}/{}".format(epoch, n_epochs))
for step in range(1, n_steps + 1):
X_batch, y_batch = random_batch(x_train, np.array(y_train))
with tf.GradientTape() as tape:
y_pred = model(X_batch, training=True)
u_pred = tf.Variable([tf.reshape(tf.transpose(tf.tensordot(y_pred[i, :nX], y_pred[i, nX:], axes=0)), [nX * nT]) for i in
range(batch_size)])
main_loss = tf.reduce_mean(loss_fn(y_batch, u_pred))
loss = tf.add_n([main_loss] + model.losses)
gradients = tape.gradient(loss, model.trainable_variables)
我的主要问题是,当我添加操作时,渐变变成了一个无列表。如果我简单地用模型的预测计算损失函数 (y_pred),代码就能够计算梯度。
你能帮我找出我在这里犯的错误吗?
您正在 u_pred 中创建一个新的(可训练的)变量,从而打破了 u_pred 对 y_pred 的任何依赖。值匹配的原因是因为你 initialise 你的新变量与预测,但它没有 functional 相互依赖了,没有梯度流动。
我猜你这样做是因为你需要一个 tf.Tensor 而不是一个列表,而且你最终遇到了类型错误。您可能想要使用 tf.concatenate
而不是 tf.Variable
行中的内容。
我正在尝试在计算损失函数之前对模型的预测进行后处理,因为我的真实数据 (y_train) 是 NN 输出的外积。我已按照以下步骤操作:
- 我知道我尝试使用 numpy 进行的操作是:
nX = 201
nT = 101
nNNout = nX+nT
nBatch = 32
NNout = np.random.rand(nBatch, nNNout)
f = NNout[:, :nX]
g = NNout[:,nX:]
test = np.empty([nBatch, nX*nT])
for i in range(nBatch):
test[i,:] = np.outer(f[i,:], g[i,:]).flatten('F')
其中 NN 输出包含 f 和 g。我真正需要的是每个批处理实例的 f 和 g 外积的矢量化版本。
- 我在紧凑的张量流操作中将其翻译为:
test2 = tf.Variable([tf.reshape(tf.transpose(tf.tensordot(f[i,:],g[i,:], axes=0)),[nX*nT]) for i in range(nBatch)])
我已经检查过它是正确的,并且输出的值与步骤 1 中的值相同。
- 然后,我只是想在我的模型预测之后添加这个操作:
n_epochs = 20
batch_size = 32
n_steps = len(x_train) // batch_size
optimizer = keras.optimizers.Nadam(learning_rate=0.01)
loss_fn = keras.losses.mean_squared_error
mean_loss = keras.metrics.Mean()
metrics = [keras.metrics.MeanAbsoluteError()]
# ------------ Training ------------
for epoch in range(1, n_epochs + 1):
print("Epoch {}/{}".format(epoch, n_epochs))
for step in range(1, n_steps + 1):
X_batch, y_batch = random_batch(x_train, np.array(y_train))
with tf.GradientTape() as tape:
y_pred = model(X_batch, training=True)
u_pred = tf.Variable([tf.reshape(tf.transpose(tf.tensordot(y_pred[i, :nX], y_pred[i, nX:], axes=0)), [nX * nT]) for i in
range(batch_size)])
main_loss = tf.reduce_mean(loss_fn(y_batch, u_pred))
loss = tf.add_n([main_loss] + model.losses)
gradients = tape.gradient(loss, model.trainable_variables)
我的主要问题是,当我添加操作时,渐变变成了一个无列表。如果我简单地用模型的预测计算损失函数 (y_pred),代码就能够计算梯度。
你能帮我找出我在这里犯的错误吗?
您正在 u_pred 中创建一个新的(可训练的)变量,从而打破了 u_pred 对 y_pred 的任何依赖。值匹配的原因是因为你 initialise 你的新变量与预测,但它没有 functional 相互依赖了,没有梯度流动。
我猜你这样做是因为你需要一个 tf.Tensor 而不是一个列表,而且你最终遇到了类型错误。您可能想要使用 tf.concatenate
而不是 tf.Variable
行中的内容。