强化学习(十)Double DQN (DDQN)

    在强化学习(九)Deep Q-Learning进阶之Nature DQN中,咱们讨论了Nature DQN的算法流程,它经过使用两个相同的神经网络,以解决数据样本和网络训练以前的相关性。可是仍是有其余值得优化的点,文本就关注于Nature DQN的一个改进版本: Double DQN算法(如下简称DDQN)。html

    本章内容主要参考了ICML 2016的deep RL tutorial和DDQN的论文<Deep Reinforcement Learning with Double Q-learning>。git

1. DQN的目标Q值计算问题

    在DDQN以前,基本上全部的目标Q值都是经过贪婪法直接获得的,不管是Q-Learning, DQN(NIPS 2013)仍是 Nature DQN,都是如此。好比对于Nature DQN,虽然用了两个Q网络并使用目标Q网络计算Q值,其第j个样本的目标Q值的计算仍是贪婪法获得的,计算入下式:$$y_j= \begin{cases} R_j& {is\_end_j\; is \;true}\\ R_j + \gamma\max_{a'}Q'(\phi(S'_j),A'_j,w') & {is\_end_j \;is\; false} \end{cases}$$github

    使用max虽然能够快速让Q值向可能的优化目标靠拢,可是很容易过犹不及,致使过分估计(Over Estimation),所谓过分估计就是最终咱们获得的算法模型有很大的误差(bias)。为了解决这个问题, DDQN经过解耦目标Q值动做的选择和目标Q值的计算这两步,来达到消除过分估计的问题。算法

2. DDQN的算法建模

    DDQN和Nature DQN同样,也有同样的两个Q网络结构。在Nature DQN的基础上,经过解耦目标Q值动做的选择和目标Q值的计算这两步,来消除过分估计的问题。网络

    在上一节里,Nature DQN对于非终止状态,其目标Q值的计算式子是:$$y_j= R_j + \gamma\max_{a'}Q'(\phi(S'_j),A'_j,w')$$app

    在DDQN这里,再也不是直接在目标Q网络里面找各个动做中最大Q值,而是先在当前Q网络中先找出最大Q值对应的动做,即$$a^{max}(S'_j, w) = \arg\max_{a'}Q(\phi(S'_j),a,w)$$函数

    而后利用这个选择出来的动做$a^{max}(S'_j, w) $在目标网络里面去计算目标Q值。即:$$y_j = R_j + \gamma Q'(\phi(S'_j),a^{max}(S'_j, w),w')$$post

    综合起来写就是:$$y_j = R_j + \gamma Q'(\phi(S'_j),\arg\max_{a'}Q(\phi(S'_j),a,w),w')$$学习

    除了目标Q值的计算方式之外,DDQN算法和Nature DQN的算法流程彻底相同。优化

 3. DDQN算法流程

    这里咱们总结下DDQN的算法流程,和Nature DQN的区别仅仅在步骤2.f中目标Q值的计算。

    算法输入:迭代轮数$T$,状态特征维度$n$, 动做集$A$, 步长$\alpha$,衰减因子$\gamma$, 探索率$\epsilon$, 当前Q网络$Q$,目标Q网络$Q'$, 批量梯度降低的样本数$m$,目标Q网络参数更新频率$C$。

    输出:Q网络参数

    1. 随机初始化全部的状态和动做对应的价值$Q$.  随机初始化当前Q网络的全部参数$w$,初始化目标Q网络$Q'$的参数$w' = w$。清空经验回放的集合$D$。

    2. for i from 1 to T,进行迭代。

      a) 初始化S为当前状态序列的第一个状态, 拿到其特征向量$\phi(S)$

      b) 在Q网络中使用$\phi(S)$做为输入,获得Q网络的全部动做对应的Q值输出。用$\epsilon-$贪婪法在当前Q值输出中选择对应的动做$A$

      c) 在状态$S$执行当前动做$A$,获得新状态$S'$对应的特征向量$\phi(S')和奖励$R$,是否终止状态is_end

      d) 将$\{\phi(S),A,R,\phi(S'),is\_end\}$这个五元组存入经验回放集合$D$

      e) $S=S'$

      f)  从经验回放集合$D$中采样$m$个样本$\{\phi(S_j),A_j,R_j,\phi(S'_j),is\_end_j\}, j=1,2.,,,m$,计算当前目标Q值$y_j$:$$y_j= \begin{cases} R_j& {is\_end_j\; is \;true}\\ R_j + \gamma Q'(\phi(S'_j),\arg\max_{a'}Q(\phi(S'_j),a,w),w')& {is\_end_j\; is \;false} \end{cases}$$

      g)  使用均方差损失函数$\frac{1}{m}\sum\limits_{j=1}^m(y_j-Q(\phi(S_j),A_j,w))^2$,经过神经网络的梯度反向传播来更新Q网络的全部参数$w$

      h) 若是T%C=1,则更新目标Q网络参数$w'=w$

      i) 若是$S'$是终止状态,当前轮迭代完毕,不然转到步骤b)

      注意,上述第二步的f步和g步的Q值计算也都须要经过Q网络计算获得。另外,实际应用中,为了算法较好的收敛,探索率$\epsilon$须要随着迭代的进行而变小。

4. DDQN算法实例 

    下面咱们用一个具体的例子来演示DQN的应用。仍然使用了OpenAI Gym中的CartPole-v0游戏来做为咱们算法应用。CartPole-v0游戏的介绍参见这里。它比较简单,基本要求就是控制下面的cart移动使链接在上面的pole保持垂直不倒。这个任务只有两个离散动做,要么向左用力,要么向右用力。而state状态就是这个cart的位置和速度, pole的角度和角速度,4维的特征。坚持到200分的奖励则为过关。

    完整的代码参见个人github: https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/ddqn.py

    这里咱们重点关注DDQN和上一节的Nature DQN的代码的不一样之处。代码只有一个地方不同,就是计算目标Q值的时候,以下:

    # Step 2: calculate y
    y_batch = []
    current_Q_batch = self.Q_value.eval(feed_dict={self.state_input: next_state_batch})
    max_action_next = np.argmax(current_Q_batch, axis=1)
    target_Q_batch = self.target_Q_value.eval(feed_dict={self.state_input: next_state_batch})

    for i in range(0,BATCH_SIZE):
      done = minibatch[i][4]
      if done:
        y_batch.append(reward_batch[i])
      else :
        target_Q_value = target_Q_batch[i, max_action_next[i]]
        y_batch.append(reward_batch[i] + GAMMA * target_Q_value)

    而以前的Nature  DQN这里的目标Q值计算是以下这样的:

 # Step 2: calculate y
    y_batch = []
    Q_value_batch = self.target_Q_value.eval(feed_dict={self.state_input:next_state_batch})
    for i in range(0,BATCH_SIZE):
      done = minibatch[i][4]
      if done:
        y_batch.append(reward_batch[i])
      else :
        y_batch.append(reward_batch[i] + GAMMA * np.max(Q_value_batch[i]))

    除了上面这部分的区别,两个算法的代码彻底相同。

5. DDQN小结

    DDQN算法出来之后,取得了比较好的效果,所以获得了比较普遍的应用。不过咱们的DQN仍然有其余能够优化的点,如上一篇最后讲到的: 随机采样的方法好吗?按道理经验回放里不一样样本的重要性是不同的,TD偏差大的样本重要程度应该高。针对这个问题,咱们在下一节的Prioritised Replay DQN中讨论。

 

(欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com)

相关文章
相关标签/搜索