深度强化学习实践(原书第2版)
上QQ阅读APP看书,第一时间看更新

6.2 表格Q-learning

首先,真的需要遍历状态空间中的每个状态吗?我们有一个环境,该环境可以用作真实状态样本的来源。如果状态空间中的一些状态没有展示出来,我们为什么要关心这些状态的价值呢?我们可以用从环境中获得的状态来更新状态价值,这可以节省很多工作。

如前所述,这种价值迭代的更新方法称为Q-learning,对于有明确的状态价值映射的情况,它具有以下步骤:

1)从空表开始,将状态映射到动作价值。

2)通过与环境交互,获得元组(s, a, r, s')(状态、动作、奖励和新状态)。在此步骤中,要确定所需采取的动作,并且没有单一的正确方法来做出此决定。在第1章中,我们探讨了探索与利用的问题。本章将进行详细讨论。

3)使用Bellman近似更新Qs, a)值:

114-01

4)从步骤2开始重复。

与价值迭代一样,终止条件可能是更新的某个阈值,或者也可以执行测试片段以估计策略的预期奖励。

这里要注意的另一件事是如何更新Q值。当从环境中取样时,将新值直接赋给现有的值通常是一个坏主意,因为训练可能会变得不稳定。

在实践中,通常使用“混合”技术用近似值更新Q(s, a),该技术使用值为0~1的学习率α将新旧Q值平均:

114-02

即使环境包含噪声,也可以使Q值平滑收敛。该算法的最终版本如下:

1)从一个Q(s, a)的空表开始。

2)从环境中获取(s, a, r, s')。

3)进行Bellman更新:114-03

4)检查收敛条件。如果不符合,则从步骤2开始重复。

如前所述,这种方法称为表格Q-learning,因为我们维护了一个带有其Q值的状态表。我们在FrozenLake环境中尝试一下。完整示例代码在Chapter06/01_frozenlake_q_learning.py中。

114-04

首先,导入包并定义常量。这里的新内容是α值,α将用作价值更新中的学习率。现在,Agent类的初始化更加简单,因为不需要跟踪奖励和转移计数器的历史记录,只需跟踪价值表即可。这将使内存占用空间更小,这对于FrozenLake而言不是一个大问题,但对于较大的环境可能至关重要。

115-01

前面的方法可用来从环境中获取下一个状态转移。在动作空间中随机选取动作,并返回由旧状态、所采取动作、所获得奖励和新状态组成的元组。该元组将在后续的训练循环中使用。

115-02

下一个方法接收环境中的状态,并通过表格查找在当前状态下可以获得最大价值的动作。如果没有与动作和状态对关联的价值,就将其设为零。该方法将被使用两次:第一次在测试方法中,使用当前价值表运行一个片段(用来评估策略的质量);第二次使用是在执行价值更新时,用于获取下一个状态的价值。

115-03

在此,我们在环境中前进一步来更新价值表。为此,通过将立即奖励与下一个状态的折扣价值相加来计算状态s和动作a的Bellman近似。然后,获得状态和动作对以前的价值,并使用学习率将这些值混合平均。其结果就是存储在表中的针对状态s和动作a的价值的新近似值。

115-04

Agent类中的最后一个方法使用提供的测试环境运行一整个片段。每一步的动作都是根据当前Q值表决定的。该方法用于评估当前的策略,以检查学习进度。请注意,此方法不会更改价值表,只是用它查找要采取的最佳动作。

该示例的其余部分是训练循环,它与第5章中的示例非常相似:创建测试环境、智能体和SummaryWriter。然后在循环中,在环境中执行一步,并使用获取的数据执行价值更新。接下来,通过运行几个测试片段来测试当前的策略。如果获得了足够好的奖励,就停止训练。

116-01

该示例的运行结果如下:

116-02

你可能已经注意到,与上一章的价值迭代方法相比,此版本使用了更多的迭代来解决问题,原因是不再使用测试中获得的经验数据。(在示例Chapter05/02_frozenlake_q_iteration.py中,定期测试导致Q表统计信息的更新。而此处,测试过程中不触及Q值,这导致在解决环境问题之前会有更多的迭代。)总体而言,从环境中获取的样本总数几乎相同。TensorBoard中的奖励图也展示了训练动态,这与价值迭代方法非常相似(见图6.1)。

117-01

图6.1 FrozenLake的奖励动态