正文
「虚拟表格」是什么意思?想像一下,对于输入空间的每个可能的动作,你都可以为每个可能采取的动作赋予一个分数。如果这可行,那么你可以很容易地「打败」环境:只需选择具有最高分数的动作!但是需要注意 2 点:首先,这个分数通常被称为「Q-分数」,此算法也由此命名。第二,与任何其它得分一样,这些 Q-分数在其模拟的情境外没有任何意义。也就是说,它们没有确定的意义,但这没关系,因为我们只需要做比较。
为什么对于每个输入我们都需要一个虚拟表格?难道没有统一的表格吗?原因是这样做不和逻辑:这与在谷底谈采取什么动作是最好的,及在向左倾斜时的最高点讨论采取什么动作是最好的是一样的道理。
现在,我们的主要问题(为每个输入建立虚拟表格)是不可能的:我们有一个连续的(无限)输入空间!我们可以通过离散化输入空间来解决这个问题,但是对于本问题来说,这似乎是一个非常棘手的解决方案,并且在将来我们会一再遇到。那么,我们如何解决呢?那就是通过将神经网络应用于这种情况:这就是 DQN 中 D 的来历!
DQN agent
现在,我们现在已经将问题聚焦到:找到一种在给定当前状态下为不同动作赋值 Q-分数的方法。这是使用任何神经网络时遇到的非常自然的第一个问题的答案:我们模型的输入和输出是什么?本模型中你需要了解的数学方程是以下等式(不用担心,我们会在下面讲解):
如上所述,Q 代表了给定当前状态(s)和采取的动作(a)时我们模型估计的价值。然而,目标是确定一个状态价值的总和。那是什么意思?即从该位置获得的即时奖励和将来会获得的预期奖励之和。也就是说,我们要考虑一个事实,即一个状态的价值往往不仅反映了它的直接收益,而且还反映了它的未来收益。在任何情况下,我们会将未来的奖励折现,因为对于同样是收到$100 的两种情况(一种为将来,一种为现在),我会永远选择现在的交易,因为未来是会变化的。γ因子反映了此状态预期未来收益的贬值。
这就是我们需要的所有数学!下面是实际代码的演示!
DQN agent 实现
深度 Q 网络为持续学习(continuous learning),这意味着不是简单地累积一批实验/训练数据并将其传入模型。相反,我们通过之前运行的实验创建训练数据,并且直接将运行后创建的数据馈送如模型。如果现在感到好像有些模糊,别担心,该看看代码了。代码主要在定义一个 DQN 类,其中将实现所有的算法逻辑,并且我们将定义一组简单的函数来进行实际的训练。
DQN 超参数
首先,我们将讨论一些与 DQN 相关的参数。它们大多数是实现主流神经网络的标准参数:
class DQN:
def __init__(self, env):
self.env = env
self.memory = deque(maxlen=2000)
self.gamma = 0.95
self.epsilon = 1.0
self.epsilon_min = 0.01
self.epsilon_decay = 0.995
self.learning_rate = 0.01
让我们来一步一步地讲解这些超参数。第一个是环境(env),这仅仅是为了在建立模型时便于引用矩阵的形状。「记忆(memory)」是 DQN 的关键组成部分:如前所述,我们不断通过实验训练模型。然而与直接训练实验的数据不同,我们将它们先添加到内存中并随机抽样。为什么这样做呢,难道仅仅将最后 x 个实验数据作为样本进行训练不好吗?原因有点微妙。设想我们只使用最近的实验数据进行训练:在这种情况下,我们的结果只会学习其最近的动作,这可能与未来的预测没有直接的关系。特别地,在本环境下,如果我们在斜坡右侧向下移动,使用最近的实验数据进行训练将需要在斜坡右侧向上移动的数据上进行训练。但是,这与在斜坡左侧的情景需决定采取的动作无关。所以,通过抽取随机样本,将保证不会偏离训练集,而是理想地学习我们将遇到的所有环境。
我们现在来讨论模型的超参数:gamma、epsilon 以及 epsilon 衰减和学习速率。第一个是前面方程中讨论的未来奖励的折现因子(<1),最后一个是标准学习速率参数,我们不在这里讨论。第二个是 RL 的一个有趣方面,值得一谈。在任何一种学习经验中,我们总是在探索与利用之间做出选择。这不仅限于计算机科学或学术界:我们每天都在做这件事!
考虑你家附近的饭店。你最后一次尝试新饭店是什么时候?可能很久以前。这对应于你从探索到利用的转变:与尝试找到新的更好的机会不同,你根据自己以往的经验找到最好的解决方案,从而最大化效用。对比当你刚搬家时:当时你不知道什么饭店是好的,所以被诱惑去探索新选择。换句话说,这时存在明确的学习趋势:当你不了解它们时,探索所有的选择,一旦你对其中的一些建立了意见,就逐渐转向利用。以同样的方式,我们希望我们的模型能够捕捉这种自然的学习模型,而 epsilon 扮演着这个角色。