美文网首页
Dueling DQN—一种简单有效提高DQN效果的方法

Dueling DQN—一种简单有效提高DQN效果的方法

作者: CristianoC | 来源:发表于2019-07-24 15:11 被阅读0次

    1.前言

    关于DQN我们还会讲最后一种升级办法,我们只需要稍微改动DQN中的神经网络的结构,就能大幅提升学习效果,加速收敛,这种新方法叫做Dueling DQN。用一句话概括Dueling DQN就是:它将每一个动作的Q拆分成了state的Value加上每个动作的Advantage。

    2.算法

    2.1Dueling 算法

    我们看一下Dueling DQN的神经网络架构和普通DQN有什么不同:


    image

    我们可以很明显地看出,上面普通的DQN只有一个输出,就是每一个动作的Q值;而Dueling DQN则拆成了state的Value和每个动作的Advantage。

    我们再来看一下公式:


    image

    它分成了这个state的值,加上每个动作在这个state上的advantage。因为有时候在某种state,无论做什么动作,对下一个state都没有多大的影响,比如论文当中的上面这个图:


    image
    这是开车的游戏,左边是state value,发红的部分证明了state value和前面的路线有关,右边是advantage,发红的部分说明了advantage很在乎旁边要靠近的车子,这时的动作会受advantage的影响。发红的地方左右了自己车子的移动原则。

    2.2 更新方法

    image
    class DuelingDQN:
        def __init__(..., dueling=True, sess=None)
            ...
            self.dueling = dueling  # 会建立两个 DQN, 其中一个是 Dueling DQN
            ...
            if sess is None:    # 针对建立两个 DQN 的模式修改了 tf.Session() 的建立方式
                self.sess = tf.Session()
                self.sess.run(tf.global_variables_initializer())
            else:
                self.sess = sess
            ...
    
        def _build_net(self):
            def build_layers(s, c_names, n_l1, w_initializer, b_initializer):
                with tf.variable_scope('l1'):   # 第一层, 两种 DQN 都一样
                    w1 = tf.get_variable('w1', [self.n_features, n_l1], initializer=w_initializer, collections=c_names)
                    b1 = tf.get_variable('b1', [1, n_l1], initializer=b_initializer, collections=c_names)
                    l1 = tf.nn.relu(tf.matmul(s, w1) + b1)
    
                if self.dueling:
                    # Dueling DQN
                    with tf.variable_scope('Value'):    # 专门分析 state 的 Value
                        w2 = tf.get_variable('w2', [n_l1, 1], initializer=w_initializer, collections=c_names)
                        b2 = tf.get_variable('b2', [1, 1], initializer=b_initializer, collections=c_names)
                        self.V = tf.matmul(l1, w2) + b2
    
                    with tf.variable_scope('Advantage'):    # 专门分析每种动作的 Advantage
                        w2 = tf.get_variable('w2', [n_l1, self.n_actions], initializer=w_initializer, collections=c_names)
                        b2 = tf.get_variable('b2', [1, self.n_actions], initializer=b_initializer, collections=c_names)
                        self.A = tf.matmul(l1, w2) + b2
    
                    with tf.variable_scope('Q'):    # 合并 V 和 A, 为了不让 A 直接学成了 Q, 我们减掉了 A 的均值
                        out = self.V + (self.A - tf.reduce_mean(self.A, axis=1, keep_dims=True))     # Q = V(s) + A(s,a)
                else:
                    with tf.variable_scope('Q'):    # 普通的 DQN 第二层
                        w2 = tf.get_variable('w2', [n_l1, self.n_actions], initializer=w_initializer, collections=c_names)
                        b2 = tf.get_variable('b2', [1, self.n_actions], initializer=b_initializer, collections=c_names)
                        out = tf.matmul(l1, w2) + b2
    
                return out
            ...
    

    3.对比结果

    这次我们看看累计奖励reward,杆子立起来的时候奖励=0,其他时候都是负值,所以当累积奖励没有在降低的时候,说明杆子已经被成功立起来很久了。

    image
    我们可以发现当可用工作越高,学习难度就越大,不过Dueling DQN还是会比Natural DQN学习得更快,收敛效果更好。
    完整代码:https://github.com/cristianoc20/RL_learning/tree/master/Dueling_DQN
    参考:https://github.com/MorvanZhou

    相关文章

      网友评论

          本文标题:Dueling DQN—一种简单有效提高DQN效果的方法

          本文链接:https://www.haomeiwen.com/subject/uavxrctx.html