【问题标题】:How does DQN work in an environment where reward is always -1DQN 如何在奖励始终为 -1 的环境中工作
【发布时间】:2019-06-19 15:24:55
【问题描述】:

鉴于 OpenAI Gym 环境 MountainCar-v0 总是返回 -1.0 作为奖励(即使达到目标),我不明白 DQN 与体验回放如何收敛,但我知道它确实如此,因为我有 @ 987654322@ 证明了这一点。通过工作,我的意思是当我训练代理时,代理很快(在 300-500 集内)学会了如何解决山地车问题。下面是我训练有素的代理人的一个例子。

据我了解,最终需要找到一个“稀疏奖励”。然而据我从 openAI Gym code 看到的,除了-1 之外,没有任何奖励。感觉更像是一个“没有奖励”的环境。

几乎回答了我的问题,但实际上并没有:当任务快速完成时,这一集的回报(奖励总和)更大。因此,如果汽车永远找不到标志,则返回 -1000。如果汽车快速找到标志,则返回可能是 -200。这不能回答我的问题的原因是因为使用 DQN 和体验重放,这些返回(-1000,-200)永远不会出现在体验重放记忆中。所有的记忆都是(状态、动作、奖励、下一个状态)形式的元组,当然要记住,元组是随机从记忆中提取的,而不是逐集的。

这个特殊的 OpenAI Gym 环境的另一个元素是完成状态在两种情况下返回:击中标志 (yay) 或在一些步数后超时 (boo)。但是,代理对两者一视同仁,接受 -1 的奖励。因此,就内存中的元组而言,从奖励的角度来看,这两个事件看起来是相同的。

所以,我在记忆中没有看到任何表明这一集表现良好的东西。

因此,我不知道为什么此 DQN 代码适用于 MountainCar。

【问题讨论】:

  • 我不明白为什么这个问题被否决了。这是一个完全有效的问题。我也需要一个答案。

标签: machine-learning keras reinforcement-learning openai-gym q-learning


【解决方案1】:

之所以可行,是因为在 Q-learning 中,您的模型试图估计每个可能操作的所有未来奖励的 SUM(技术上是时间衰减的总和)。在 MountainCar 中,您每走一步都会获得 -1 的奖励,直到您获胜,所以如果您成功获胜,您最终获得的负面奖励会比平时少。例如,您获胜后的总分可能是 -160 而不是 -200,因此您的模型将开始预测历史上曾导致赢得比赛的动作的 Q 值更高。

【讨论】:

    【解决方案2】:

    你是对的。记忆(经验重播)与模型在情节奖励中的表现之间没有直接关联。 DQN 中的 Q 值用于预测每个动作在每一步中的预期奖励。衡量模型好坏的性能指标是真实奖励和预期奖励(TD-error)之间的差异。

    为非目标步骤部署 -1 是帮助 RL 模型选择可以更快完成情节的动作的技巧。因为Q-value是一个action-value。在每一步,模型预测每一个可能的动作的奖励,并且策略(通常是贪婪或 epsilon-greedy)选择具有最重要价值的动作。您可以想象,在某一时刻返回将需要 200 步才能完成这一集,但向前只需要 100 步。 Q 值将分别为 -200(无折扣)和 -100。您可能想知道模型如何知道每个动作的价值,这是因为在重复的情节和连续的试错中。该模型经过训练以最小化实际奖励和预期奖励之间的差异,即 TD 误差。

    在随机采样的体验回放中,所有体验都被统一采样和删除。但是,在优先体验重放中,您可以重用那些估计误差较大的体验。通常,优先级与预期 Q 值和当前模型的预测 Q 值的 TD 误差(real_reward - expected_reward)成正比。优先级越大,意味着体验有多令人惊讶,并且有助于加快训练速度。

    你可以在Priority Experience Replay, Schaul et al., 2016查看想法

    【讨论】:

      【解决方案3】:

      查看简化的问题可能会有所帮助。考虑:

      States:
      ───┬───┬───┬───┬───┐
      ...│L2 │L1 │ S │ R1│
      ───┴───┴───┴───┴───┘
      
      Actions:
      left or right
      
      r = -1 for all states
      episode terminates upon reaching R1 or after 2 steps
      

      内存:

      1. (S, left, -1, L1)非终端
      2. (S, right, -1, R1)终端
      3. (L1, left, -1, L2)终端
      4. (L1, right, -1, S)终端

      需要注意的明显但重要的一点是,虽然奖励都是相同的,但状态和动作却不同。该信息使我们能够推断给定当前状态的下一个状态。 让我们看看我们正在更新的目标(没有折扣):

      1. Q(S, left ) --> -1 + max{a}Q(L1, a)
      2. Q(S, right) --> -1
      3. Q(L1, left ) --> -1
      4. Q(L1, right) --> -1

      在这个人为的示例中,只有转换 1 呈现了额外的不稳定性来源。但是随着时间的推移L1 上的操作值会从对转换 3 和 4 的足够多的采样中收敛,因此转换 1 上的目标也应该如此。 那时,当我们再次遇到转换 1 时,我们会有更好的估计 Q(S, left) --> -1 + -1

      当我们询问 DQN 如何从其记忆中学习时,仅查看奖励是不够的,因为它还使用 下一次观察 来确定其当前对动作值的最佳估计下一步 (relevant code),将所有内容有效地连接在一起并慢慢计算奖励。尽管它以一种与传统 Q-learning 不同的更不稳定的方式这样做。


      作为练习,考虑进一步扩展它并将终端状态设置为R2。 然后我们可以很容易地看到现在max{a}Q(S, a) = -2;到达R2 和简单地超时需要相同的时间,所以我们做什么都没关系(除非我们开始更接近R2)。但是,增加超时步骤的数量,它应该再次朝向R2。 IE。山地车也可以工作,因为超时设置为大于达到目标所需的时间步长。这条路径最终应该将其(负但更好的)值传播回我们的初始状态。

      尽管这适用于任何其他环境,但只要他们的努力得到回报,他们至少仍然可以学会在超时之前让更接近目标。考虑到山地车环境中的奖励设计,情况并非如此。

      【讨论】:

        【解决方案4】:

        在 DQN 中,您学习 Q 函数,它基本上近似于您的回报。在内存中,您使用 (s,a,s',r) 存储元组并在这些元组上重新训练您的 Q 函数。如果对于给定的元组,你表现良好(你很快达到了标志),那么你将通过重新使用元组进行训练来重新体验它,因为该元组的 Q 函数更高。

        无论如何,体验回放通常更能解决任何问题,而不仅仅是山地车。

        【讨论】:

        • 感谢您的回答,但我认为这不能解决问题。
        • 您问为什么即使奖励始终相同,记忆也会起作用。问题是你不只看奖励,而是看 Q 值,重放 Q 值会有所帮助。至少根据我的理解。
        • 这没有回答问题。
        • @simon,他们想要的是一个易于理解的外行术语。你的答案是 100% 正确的。
        • 我认为这不能回答问题的原因是因为在工作解决方案代码(上面链接)中没有累积回报(如,我们没有在内存中获取所有观察奖励并添加它们,等等..)。所以我看不出快速或缓慢地解决环境问题有多重要。谢谢!!
        【解决方案5】:

        你说:

        那些返回值(-1000,-200)永远不会出现在体验回放记忆中。

        回放内存中存在的是一个 SARdS 元组,它带有一个 done 标志,告诉您该剧集已经结束。见openai健身房deepq例子:

        # Store transition in the replay buffer.
        replay_buffer.add(obs, action, rew, new_obs, float(done))
        

        在最终更新中,如果 float(done) == 1 则忽略未来的 Q 值。因此,在剧集结束时,Q 值为 0。如果这发生在第 200 步,那么剧集的总回报将为 -200。如果它发生在第 1000 步,那么总回报将是 -1000。

        换一种说法——如果完全是随机的,情节在步骤 200 结束,一个表现得与随机策略一样糟糕的代理的 Q 值(预期未来回报)为 -800。如果情节随后结束,TD 误差将是 +799,表示仅失去另一个 -1 的积极惊喜。

        我注意到您链接到的code 似乎没有在重播缓冲区中使用完成标志。相反,它依赖于s_ == None 的最终状态来表示剧集的结束。去掉那个代码,代理就不会学习了。

           if s_ is None:
                t[a] = r
            else:
                t[a] = r + GAMMA * numpy.amax(p_[i])
        

        【讨论】:

          猜你喜欢
          • 2020-11-23
          • 1970-01-01
          • 2019-01-28
          • 2017-10-03
          • 2018-12-16
          • 1970-01-01
          • 2022-10-19
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多