【问题标题】:DQN - Q-Loss not convergingDQN - Q-Loss 不收敛
【发布时间】:2018-04-12 16:07:42
【问题描述】:

我正在使用 DQN 算法在我的环境中训练代理,如下所示:

  • 代理通过选择离散动作(左、右、上、下)来控制汽车
  • 目标是在不撞到其他车辆的情况下以所需的速度行驶
  • 状态包含代理的汽车和周围汽车的速度和位置
  • 奖励:-100 碰撞其他车辆,根据与所需速度的绝对差值获得正奖励(如果以所需速度行驶,则 +50)

我已经调整了一些超参数(网络架构、探索、学习率),这给了我一些下降结果,但仍然没有达到应有的水平。每集的奖励在训练期间不断增加。 Q 值也在收敛(见图1)。然而,对于所有不同的超参数设置,Q-loss 不会收敛(见图2)。我认为,Q-loss 缺乏收敛性可能是获得更好结果的限制因素。

Q-value of one discrete action durnig training

Q-loss during training

我正在使用每 20k 时间步更新一次的目标网络。 Q-loss 计算为 MSE。

您知道 Q-loss 不收敛的原因吗? Q-Loss 是否必须收敛于 DQN 算法?我想知道,为什么大多数论文都没有讨论 Q-loss。

【问题讨论】:

    标签: tensorflow deep-learning reinforcement-learning q-learning


    【解决方案1】:

    我认为 Q 损失没有收敛是正常的,因为您的数据在您的政策更新时不断变化。它与监督学习不同,在监督学习中,您的数据永远不会改变,您可以对数据进行多次传递,以确保您的权重与该数据完全吻合。

    另一件事是我发现在每个时间步稍微更新目标网络(软更新)对我来说比在每个 X 时间步更新它(硬更新)效果更好。

    【讨论】:

    • 随着 DQN 探索从重放记忆中随机选择的转换,并且随着它“探索”动作空间,并且随着 epsilon 下降,随着 DQN 进入动作空间的“未学习”部分,损失阶段减少,因为它学习得更多,探索更多的动作空间和 epsilon->0。最终,随着动作空间被完全学习,所有损失都应该减少到 0。
    【解决方案2】:

    是的,损失必须覆盖,因为损失值是指预期Q值和当前Q值之间的差值。只有当loss值收敛时,电流才接近最优Q值。如果它发散,这意味着您的近似值越来越不准确。

    也许你可以尝试调整目标网络的更新频率或检查每次更新的梯度(添加梯度裁剪)。目标网络的加入增加了 Q-learning 的稳定性。

    在 Deepmind 2015 年的 Nature 论文中,它指出:

    在线 Q-learning 的第二个修改旨在进一步提高我们使用神经网络的方法的稳定性,是使用单独的网络在 Q-learning 更新中生成轨迹 yj。更准确地说,每次 C 更新我们都克隆网络 Q 以获得目标网络 Q' 并使用 Q' 生成 Q 学习目标 yj 以用于后续 C 对 Q 的更新。 与标准在线 Q 学习相比,这种修改使算法更加稳定,其中增加 Q(st,at) 的更新通常也会增加 Q(st+1, a) 对于所有 a,因此也增加了目标 yj,可能导致策略的振荡或发散。使用较旧的参数集生成目标会在对 Q 进行更新的时间与更新影响目标 yj 的时间之间增加延迟,从而使发散或振荡的可能性大大降低。

    Human-level control through deep reinforcement learning, Mnih et al., 2015

    我在 Cartpole 环境下给别人问过类似问题做了一个实验,更新频率 100 就解决了问题(最多达到 200 步)。

    当 C(更新频率)= 2 时,绘制平均损失:

    C = 10

    C = 100

    C = 1000

    C = 10000

    如果loss值的发散是由梯度爆炸引起的,可以裁剪梯度。在 Deepmind 的 2015 DQN 中,作者通过将值限制在 [-1, 1] 内来裁剪梯度。在另一种情况下,Prioritized Experience Replay 的作者通过将范数限制在 10 以内来剪辑渐变。以下是示例:

    DQN 渐变剪裁:

        optimizer.zero_grad()
        loss.backward()
        for param in model.parameters():
            param.grad.data.clamp_(-1, 1)
        optimizer.step()
    

    PER 渐变剪裁:

        optimizer.zero_grad()
        loss.backward()
        if self.grad_norm_clipping:
           torch.nn.utils.clip_grad.clip_grad_norm_(self.model.parameters(), 10)
       optimizer.step()
    

    【讨论】:

    • 这些图中的 x 和 y 是什么?是内存/重播缓冲区中所有体验的集数还是平均损失?
    • 是的,正如你所说。 x 是情节,y 是模型的平均损失。
    猜你喜欢
    • 2018-04-25
    • 2019-08-28
    • 2021-08-19
    • 1970-01-01
    • 2020-04-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多