在强化学习(十一) Prioritized Replay DQN中,咱们讨论了对DQN的经验回放池按权重采样来优化DQN算法的方法,本文讨论另外一种优化方法,Dueling DQN。本章内容主要参考了ICML 2016的deep RL tutorial和Dueling DQN的论文<Dueling Network Architectures for Deep Reinforcement Learning>(ICML 2016)。html
在前面讲到的DDQN中,咱们经过优化目标Q值的计算来优化算法,在Prioritized Replay DQN中,咱们经过优化经验回放池按权重采样来优化算法。而在Dueling DQN中,咱们尝试经过优化神经网络的结构来优化算法。git
具体如何优化网络结构呢?Dueling DQN考虑将Q网络分红两部分,第一部分是仅仅与状态$S$有关,与具体要采用的动做$A$无关,这部分咱们叫作价值函数部分,记作$V(S,w,\alpha)$,第二部分同时与状态状态$S$和动做$A$有关,这部分叫作优点函数(Advantage Function)部分,记为$A(S,A,w,\beta)$,那么最终咱们的价值函数能够从新表示为:$$Q(S,A, w, \alpha, \beta) = V(S,w,\alpha) + A(S,A,w,\beta)$$github
其中,$w$是公共部分的网络参数,而$\alpha$是价值函数独有部分的网络参数,而$\beta$是优点函数独有部分的网络参数。算法
因为Q网络的价值函数被分为两部分,所以Dueling DQN的网络结构也和以前的DQN不一样。为了简化算法描述,这里不使用原论文的CNN网络结构,而是使用前面文中用到的最简单的三层神经网络来描述。是否使用CNN对Dueling DQN算法自己无影响。网络
在前面讲到的DDQN等DQN算法中,我使用了一个简单的三层神经网络:一个输入层,一个隐藏层和一个输出层。以下左图所示:ide
而在Dueling DQN中,咱们在后面加了两个子网络结构,分别对应上面上到价格函数网络部分和优点函数网络部分。对应上面右图所示。最终Q网络的输出由价格函数网络的输出和优点函数网络的输出线性组合获得。函数
咱们能够直接使用上一节的价值函数的组合公式获得咱们的动做价值,可是这个式子没法辨识最终输出里面$V(S,w,\alpha)$和$A(S,A,w,\beta)$各自的做用,为了能够体现这种可辨识性(identifiability),实际使用的组合公式以下:$$Q(S,A, w, \alpha, \beta) = V(S,w,\alpha) + (A(S,A,w,\beta) - \frac{1}{\mathcal{A}}\sum\limits_{a' \in \mathcal{A}}A(S,a', w,\beta))$$post
其实就是对优点函数部分作了中心化的处理。以上就是Duel DQN的主要算法思路。因为它仅仅涉及神经网络的中间结构的改进,现有的DQN算法能够在使用Duel DQN网络结构的基础上继续使用现有的算法。因为算法主流程和其余算法没有差别,这里就不单独讲Duel DQN的算法流程了。学习
下面咱们用一个具体的例子来演示Dueling DQN的应用。仍然使用了OpenAI Gym中的CartPole-v0游戏来做为咱们算法应用。CartPole-v0游戏的介绍参见这里。它比较简单,基本要求就是控制下面的cart移动使链接在上面的pole保持垂直不倒。这个任务只有两个离散动做,要么向左用力,要么向右用力。而state状态就是这个cart的位置和速度, pole的角度和角速度,4维的特征。坚持到200分的奖励则为过关。优化
这个实例代基于Nature DQN,并将网络结构改成上图中右边的Dueling DQN网络结构,完整的代码参见个人github: https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/duel_dqn.py
这里咱们重点关注Dueling DQN和Nature DQN的代码的不一样之处。也就是网络结构定义部分,主要的代码以下,一共有两个相同结构的Q网络,每一个Q网络都有状态函数和优点函数的定义,以及组合后的Q网络输出,如代码红色部分:
def create_Q_network(self): # input layer self.state_input = tf.placeholder("float", [None, self.state_dim]) # network weights with tf.variable_scope('current_net'): W1 = self.weight_variable([self.state_dim,20]) b1 = self.bias_variable([20]) # hidden layer 1 h_layer_1 = tf.nn.relu(tf.matmul(self.state_input,W1) + b1) # hidden layer for state value with tf.variable_scope('Value'): W21= self.weight_variable([20,1]) b21 = self.bias_variable([1]) self.V = tf.matmul(h_layer_1, W21) + b21 # hidden layer for action value with tf.variable_scope('Advantage'): W22 = self.weight_variable([20,self.action_dim]) b22 = self.bias_variable([self.action_dim]) self.A = tf.matmul(h_layer_1, W22) + b22 # Q Value layer self.Q_value = self.V + (self.A - tf.reduce_mean(self.A, axis=1, keep_dims=True)) with tf.variable_scope('target_net'): W1t = self.weight_variable([self.state_dim,20]) b1t = self.bias_variable([20]) # hidden layer 1 h_layer_1t = tf.nn.relu(tf.matmul(self.state_input,W1t) + b1t) # hidden layer for state value with tf.variable_scope('Value'): W2v = self.weight_variable([20,1]) b2v = self.bias_variable([1]) self.VT = tf.matmul(h_layer_1t, W2v) + b2v # hidden layer for action value with tf.variable_scope('Advantage'): W2a = self.weight_variable([20,self.action_dim]) b2a = self.bias_variable([self.action_dim]) self.AT = tf.matmul(h_layer_1t, W2a) + b2a # Q Value layer self.target_Q_value = self.VT + (self.AT - tf.reduce_mean(self.AT, axis=1, keep_dims=True))
其他部分代码和Nature DQN基本相同。固然,咱们能够也在前面DDQN,Prioritized Replay DQN代码的基础上,把网络结构改为上面的定义,这样Dueling DQN也能够起做用。
DQN系列我花了5篇来说解,一共5个先后有关联的算法:DQN(NIPS2013), Nature DQN, DDQN, Prioritized Replay DQN和Dueling DQN。目前使用的比较主流的是后面三种算法思路,这三种算法思路也是能够混着一块儿使用的,相互并不排斥。
固然DQN家族的算法远远不止这些,还有一些其余的DQN算法我没有详细介绍,好比使用一些较复杂的CNN和RNN网络来提升DQN的表达能力,又好比改进探索状态空间的方法等,主要是在DQN的基础上持续优化。
DQN算是深度强化学习的中的主流流派,表明了Value-Based这一大类深度强化学习算法。可是它也有本身的一些问题,就是绝大多数DQN只能处理离散的动做集合,不能处理连续的动做集合。虽然NAF DQN能够解决这个问题,可是方法过于复杂了。而深度强化学习的另外一个主流流派Policy-Based而能够较好的解决这个问题,从下一篇咱们开始讨论Policy-Based深度强化学习。
(欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com)