首先,应得的功劳:ralf htp 和 Simon 提供的信息有助于我最终找出正确的答案。
在我详细回答我自己的问题之前,here's the original code 我试图用 tf.keras 术语重写,here's my result。
在 Keras 中将行动和优势传递给损失函数的正确方法是什么?
原始 TF 优化器所考虑的损失函数与 Keras 所做的有所不同。直接使用优化器时,它只需要一个张量(惰性或急切,具体取决于您的配置),它将在 tf.GradientTape() 下评估以计算梯度并更新权重。
来自https://medium.com/@asteinbach/actor-critic-using-deep-rl-continuous-mountain-car-in-tensorflow-4c1fb2110f7c的示例:
# Below norm_dist is the output tensor of the neural network we are training.
loss_actor = -tfc.log(norm_dist.prob(action_placeholder) + 1e-5) * delta_placeholder
training_op_actor = tfc.train.AdamOptimizer(
lr_actor, name='actor_optimizer').minimize(loss_actor)
# Later, in the training loop...
_, loss_actor_val = sess.run([training_op_actor, loss_actor],
feed_dict={action_placeholder: np.squeeze(action),
state_placeholder: scale_state(state),
delta_placeholder: td_error})
在此示例中,它计算整个图形,包括进行推理、捕获梯度和调整权重。因此,要将您需要的任何值传递到损失函数/梯度计算中,您只需将必要的值传递到计算图中即可。
Keras 有点more formal 损失函数应该是什么样子:
loss:字符串(目标函数的名称),目标函数或 tf.keras.losses.Loss 实例。请参阅 tf.keras.losses。目标函数是任何具有签名 scalar_loss = fn(y_true, y_pred) 的可调用函数。如果模型有多个输出,您可以通过传递字典或损失列表在每个输出上使用不同的损失。模型将最小化的损失值将是所有单个损失的总和。
Keras 将为您进行推理(前向传递)并将输出传递给损失函数。损失函数应该对预测值和y_true标签做一些额外的计算,并返回结果。为了梯度计算,将跟踪整个过程。
虽然对于传统的训练来说很方便,但是当我们想要传入一些额外的数据时,这有点限制,比如 TD error。可以解决这个问题并将所有额外数据推入y_true,然后在损失函数中将其分开(我在网络上的某个地方找到了这个技巧,但不幸的是丢失了源链接)。
最后我是这样重写上面的:
def loss(y_true, y_pred):
action_true = y_true[:, :n_outputs]
advantage = y_true[:, n_outputs:]
return -tfc.log(y_pred.prob(action_true) + 1e-5) * advantage
# Below, in the training loop...
# A trick to pass TD error *and* actual action to the loss function: join them into a tensor and split apart
# Inside the loss function.
annotated_action = tf.concat([action, td_error], axis=1)
actor_model.train_on_batch([scale_state(state)], [annotated_action])
演员的损失函数涉及计算给定正态分布所采取行动的概率。如何确保损失函数计算期间正态分布的 mu 和 sigma 与预测期间的实际匹配?
当我问这个问题时,我对 TF 计算图的工作原理还不够了解。所以答案很简单:每次调用 sess.run() 时,它都必须从头开始计算整个图。只要图输入(例如观察到的状态)和 NN 权重相同(或相似),分布参数将相同(或相似)。
原来的方式是,actor 的损失函数不关心 y_pred,它只关心与环境交互时选择的动作。这似乎是错误的,但我不确定如何。
错误的是假设“演员的损失函数不关心 y_pred”:) 演员的损失函数涉及 norm_dist(这是动作概率分布),在这种情况下它实际上是 y_pred 的模拟。