Keras DDPG(Tensroflow 2)演员更新

Keras DDPG(Tensroflow 2)演员更新,keras,reinforcement-learning,tensorflow2.0,Keras,Reinforcement Learning,Tensorflow2.0,在tensorflow 2中实现DDPG代理时,我面临一个大问题。 虽然批评家网络的更新是清晰和简单的(只需在损失上做一个梯度下降),但演员的更新要难一点 这是我对“actor_update”函数的实现: def actor_train(self, minibatch): s_batch, _, _, _, _ = minibatch with tf.GradientTape() as tape1: with tf.GradientTape() as tape2:

在tensorflow 2中实现DDPG代理时,我面临一个大问题。 虽然批评家网络的更新是清晰和简单的(只需在损失上做一个梯度下降),但演员的更新要难一点

这是我对“actor_update”函数的实现:

def actor_train(self, minibatch):
    s_batch, _, _, _, _ = minibatch
    with tf.GradientTape() as tape1:
        with tf.GradientTape() as tape2:
            mu = self.actor_network(s_batch)
            q = self.critic_network([s_batch, mu])
        mu_grad = tape1.gradient(mu, self.actor_network.trainable_weights)
    q_grad = tape2.gradient(q, self.actor_network.trainable_weights)

    x = np.array(q_grad)*np.array(mu_grad)
    x /= -len(minibatch)
    self.actor_optimizer.apply_gradients(zip(x, self.actor_network.trainable_weights))
如本文所述,优化是两个梯度的乘积:一个是Q函数的梯度wrt的行动,另一个是演员函数的梯度wrt的权重

当所有网络的权重在-1e-3和1e-3之间均匀分布时,参与者似乎不会更新其权重。 相反,绘制评论家的结果(使用MountainCarContinous作为测试环境)显示出与数据的一点差异

这是评论家的完整性准则:

def critic_train(self, minibatch):
    s_batch, a_batch, r_batch, s_1_batch, t_batch = minibatch

    mu_prime = np.array(self.actor_target_network(s_1_batch))
    q_prime = self.critic_target_network([s_1_batch, mu_prime])
    ys = r_batch + self.GAMMA * (1 - t_batch) * q_prime


    with tf.GradientTape() as tape:
        predicted_qs = self.critic_network([s_batch, a_batch])
        loss = tf.keras.losses.MSE(ys, predicted_qs)
        dloss = tape.gradient(loss, self.critic_network.trainable_weights)

    self.critic_optimizer.apply_gradients(zip(dloss, self.critic_network.trainable_weights))
作为一个额外的演员,在一集获胜的剧集之后,他似乎已经饱和了。(意味着每次输入都会卡在+1或-1上)

问题在哪里?更新功能正确吗?或者这只是一个超参数优化问题


这是回购协议,有人想更好地了解这个问题:

我没有查看回购协议,但我可以在您发布的代码片段中发现一些东西:

  • 评论家网络一目了然。但它使用的是MSE损耗。没什么大不了的,但是报纸 使用Huber损耗,如果这样做,代理将更加稳定
  • 向演员灌输批评梯度是不正确的
  • 回想一下,反向传播在网络中逐层向后应用链式规则,因此前一层的梯度取决于为下一层计算的梯度。相反,在您发布的代码中,两个整个网络的渐变将一起广播并应用于参与者

    您需要计算来自评论家的动作渐变,并将它们作为演员的初始渐变输入。把它想象成一层一层地,从评论家的输出到演员的输入,就像两个网络被链接在一起一样

    更具体地说:

    • Calcualte action gradients(计算动作梯度)-相对于(wrt.)动作输入的批评家输出的梯度。直观地说,这些梯度表示批评家的动作输入对Q值的贡献程度。在此之后,我们应该有一个形状梯度的张量/列表[批次大小,动作大小]
    • 参与者的输出也是[批量大小,动作大小]。我们希望将这些梯度输入到演员的输出层,以便反向传播以改变我们的动作输出,使Q值最大化
    因此,您的代码最终看起来是这样的(我没有检查它的正确性,但您应该能够使它工作。特别是,我不太熟悉渐变磁带,因此您可能希望确保渐变的范围是有效的):


    如果您的代码能够正常工作,那么最好将其发布在答案中,以便其他具有相同问题的人在搜索过程中登陆此页面时可以获得一个正常工作的示例。

    我曾尝试让您的代码在TF2.0中工作,但问题是
    mu
    不是可训练的变量,并且不受磁带监视,所以当你计算q_grad时,你什么都没有。我也有同样的问题,你找到解决方案了吗?如果我没记错的话,代码是正确的。问题在于,我忘了扩展一些我现在不记得的TF2接口,抱歉……无论如何,谢谢。你能把正确代码的链接发给我吗?我将尝试比较并找出我在回购协议中发布的错误。如果不在那里我就把密码丢了
    with tf.GradientTape() as tape1:
        mu = self.actor_network(s_batch)
        with tf.GradientTape() as tape2:
            q = self.critic_network([s_batch, mu])
        q_grad = tape2.gradient(q, mu) # grads of Q output wrt. action inputs [batch_size, action_dims]
    mu_grad = tape1.gradient(mu, self.actor_network.trainable_weights, -q_grad) # grads of actions wrt. network vars, feeding in the action grads as initial grads
    
    x = mu_grad / len(minibatch) # gradient() sums over batch dim, so take the mean to apply
    self.actor_optimizer.apply_gradients(zip(x, self.actor_network.trainable_weights))