在强化学习(十五) A3C中,咱们讨论了使用多线程的方法来解决Actor-Critic难收敛的问题,今天咱们不使用多线程,而是使用和DDQN相似的方法:即经验回放和双网络的方法来改进Actor-Critic难收敛的问题,这个算法就是是深度肯定性策略梯度(Deep Deterministic Policy Gradient,如下简称DDPG)。html
本篇主要参考了DDPG的论文和ICML 2016的deep RL tutorial。git
从DDPG这个名字看,它是由D(Deep)+D(Deterministic )+ PG(Policy Gradient)组成。PG(Policy Gradient)咱们在强化学习(十三) 策略梯度(Policy Gradient)里已经讨论过。那什么是肯定性策略梯度(Deterministic Policy Gradient,如下简称DPG)呢?github
肯定性策略是和随机策略相对而言的,对于某一些动做集合来讲,它多是连续值,或者很是高维的离散值,这样动做的空间维度极大。若是咱们使用随机策略,即像DQN同样研究它全部的可能动做的几率,并计算各个可能的动做的价值的话,那须要的样本量是很是大才可行的。因而有人就想出使用肯定性策略来简化这个问题。算法
做为随机策略,在相同的策略,在同一个状态处,采用的动做是基于一个几率分布的,便是不肯定的。而肯定性策略则决定简单点,虽然在同一个状态处,采用的动做几率不一样,可是最大几率只有一个,若是咱们只取最大几率的动做,去掉这个几率分布,那么就简单多了。即做为肯定性策略,相同的策略,在同一个状态处,动做是惟一肯定的,即策略变成$$\pi_{\theta}(s) = a$$网络
在看肯定性策略梯度DPG前,咱们看看基于Q值的随机性策略梯度的梯度计算公式:$$\nabla_{\theta}J(\pi_{\theta}) = E_{s\sim\rho^{\pi}, a\sim\pi_{\theta}}[\nabla_{\theta}log \pi_{\theta}(s,a)Q_{\pi}(s,a)]$$多线程
其中状态的采样空间为$\rho^{\pi}$, $\nabla_{\theta}log \pi_{\theta}(s,a)$是分值函数,可见随机性策略梯度须要在整个动做的空间$\pi_{\theta}$进行采样。'dom
而DPG基于Q值的肯定性策略梯度的梯度计算公式是:$$\nabla_{\theta}J(\pi_{\theta}) = E_{s\sim\rho^{\pi}}[\nabla_{\theta} \pi_{\theta}(s)\nabla_{a}Q_{\pi}(s,a)|_{a=\pi_{\theta}(s)}]$$函数
跟随机策略梯度的式子相比,少了对动做的积分,多了回报Q函数对动做的导数。post
而从DPG到DDPG的过程,彻底能够类比DQN到DDQN的过程。除了老生常谈的经验回放之外,咱们有了双网络,即当前网络和目标网络的概念。而因为如今咱们原本就有Actor网络和Critic两个网络,那么双网络后就变成了4个网络,分别是:Actor当前网络,Actor目标网络,Critic当前网络,Critic目标网络。2个Actor网络的结构相同,2个Critic网络的结构相同。那么这4个网络的功能各自是什么呢?学习
DDPG有4个网络,在了解这4个网络的功能以前,咱们先复习DDQN的两个网络:当前Q网络和目标Q网络的做用。能够复习强化学习(十)Double DQN (DDQN)。
DDQN的当前Q网络负责对当前状态$S$使用$\epsilon-$贪婪法选择动做$A$,执行动做$A$,得到新状态$S'$和奖励$R$,将样本放入经验回放池,对经验回放池中采样的下一状态$S’$使用贪婪法选择动做$A'$,供目标Q网络计算目标Q值,当目标Q网络计算出目标Q值后,当前Q网络会进行网络参数的更新,并按期把最新网络参数复制到目标Q网络。
DDQN的目标Q网络则负责基于经验回放池计算目标Q值,提供给当前Q网络用,目标Q网络会按期从当前Q网络复制最新网络参数。
如今咱们回到DDPG,做为DDPG,Critic当前网络,Critic目标网络和DDQN的当前Q网络,目标Q网络的功能定位基本相似,可是咱们有本身的Actor策略网络,所以不须要$\epsilon-$贪婪法这样的选择方法,这部分DDQN的功能到了DDPG能够在Actor当前网络完成。而对经验回放池中采样的下一状态$S'$使用贪婪法选择动做$A'$,这部分工做因为用来估计目标Q值,所以能够放到Actor目标网络完成。
基于经验回放池和目标Actor网络提供的$S',A'$计算目标Q值的一部分,这部分因为是评估,所以仍是放到Critic目标网络完成。而Critic目标网络计算出目标Q值一部分后,Critic当前网络会计算目标Q值,并进行网络参数的更新,并按期将网络参数复制到Critic目标网络。
此外,Actor当前网络也会基于Critic目标网络计算出的目标Q值,进行网络参数的更新,并按期将网络参数复制到Actor目标网络。
有了上面的思路,咱们总结下DDPG 4个网络的功能定位:
1. Actor当前网络:负责策略网络参数$\theta$的迭代更新,负责根据当前状态$S$选择当前动做$A$,用于和环境交互生成$S',R$。
2. Actor目标网络:负责根据经验回放池中采样的下一状态$S'$选择最优下一动做$A'$。网络参数$\theta '$按期从$\theta$复制。
3. Critic当前网络:负责价值网络参数$w$的迭代更新,负责计算负责计算当前Q值$Q(S,A,w)$。目标Q值$y_i = R+\gamma Q'(S',A',w')$
4. Critic目标网络:负责计算目标Q值中的$Q'(S',A',w')$部分。网络参数$w'$按期从$w$复制。
DDPG除了这4个网络结构,还用到了经验回放,这部分用于计算目标Q值,和DQN没有什么区别,这里就不展开了。
此外,DDPG从当前网络到目标网络的复制和咱们以前讲到了DQN不同。回想DQN,咱们是直接把将当前Q网络的参数复制到目标Q网络,即$w'=w$, DDPG这里没有使用这种硬更新,而是使用了软更新,即每次参数只更新一点点,即:$$w' \gets \tau w+ (1-\tau)w'$$$$\theta' \gets \tau \theta+ (1-\tau)\theta'$$
其中$\tau$是更新系数,通常取的比较小,好比0.1或者0.01这样的值。
同时,为了学习过程能够增长一些随机性,增长学习的覆盖,DDPG对选择出来的动做$A$会增长必定的噪声$\mathcal{N}$,即最终和环境交互的动做$A$的表达式是:$$A = \pi_{\theta}(S) + \mathcal{N}$$
最后,咱们来看看DDPG的损失函数。对于Critic当前网络,其损失函数和DQN是相似的,都是均方偏差,即:$$J(w) =\frac{1}{m}\sum\limits_{j=1}^m(y_j-Q(\phi(S_j),A_j,w))^2$$
而对于 Actor当前网络,其损失函数就和以前讲的PG,A3C不一样了,这里因为是肯定性策略,原论文定义的损失梯度是:$$\nabla_J(\theta) = \frac{1}{m}\sum\limits_{j=1}^m[\nabla_{a}Q_(s_i,a_i,w)|_{s=s_i,a=\pi_{\theta}(s)}\nabla_{\theta} \pi_{\theta(s)}|_{s=s_i}]$$
这个能够对应上咱们第二节的肯定性策略梯度,看起来比较麻烦,可是其实理解起来很简单。假如对同一个状态,咱们输出了两个不一样的动做$a_1$和$a_2$,从Critic当前网络获得了两个反馈的Q值,分别是$Q_1,Q_2$,假设$Q_1>Q_2$,即采起动做1能够获得更多的奖励,那么策略梯度的思想是什么呢,就是增长$a_1$的几率,下降$a_2$的几率,也就是说,Actor想要尽量的获得更大的Q值。因此咱们的Actor的损失能够简单的理解为获得的反馈Q值越大损失越小,获得的反馈Q值越小损失越大,所以只要对状态估计网络返回的Q值取个负号便可,即:$$J(\theta) = -\frac{1}{m}\sum\limits_{j=1}^m Q_(s_i,a_i,w)$$
这里咱们总结下DDPG的算法流程
输入:Actor当前网络,Actor目标网络,Critic当前网络,Critic目标网络,参数分别为$\theta, \theta',w,w'$,衰减因子$\gamma$, 软更新系数$\tau$,批量梯度降低的样本数$m$,目标Q网络参数更新频率$C$。最大迭代次数$T$。随机噪音函数\mathcal{N}
输出:最优Actor当前网络参数$ \theta$,Critic当前网络参数$w$
1. 随机初始化$\theta,w$, $w' = w$,$\theta' = \theta$。清空经验回放的集合$D$
2. for i from 1 to T,进行迭代。
a) 初始化$S$为当前状态序列的第一个状态, 拿到其特征向量$\phi(S)$
b) 在Actor当前网络基于状态$S$获得动做$A =\pi_{\theta}(\phi(S)) + \mathcal{N} $
c) 执行动做$A$,获得新状态$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),\pi_{ \theta'}(\phi(S'_j)),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$,经过神经网络的梯度反向传播来更新Critic当前网络的全部参数$w$
h) 使用$J(\theta) = -\frac{1}{m}\sum\limits_{j=1}^m Q_(s_i,a_i,w)$,,经过神经网络的梯度反向传播来更新Actor当前网络的全部参数$\theta$
i) 若是T%C=1,则更新Critic目标网络和Actor目标网络参数:$$w' \gets \tau w+ (1-\tau)w'$$$$\theta' \gets \tau \theta+ (1-\tau)\theta'$$
j) 若是$S'$是终止状态,当前轮迭代完毕,不然转到步骤b)
以上就是DDPG算法的主流程,要注意的是上面2.f中的$\pi_{ \theta'}(\phi(S'_j))$是经过Actor目标网络获得,而$Q'(\phi(S'_j),\pi_{ \theta'}(\phi(S'_j)),w')$则是经过Critic目标网络获得的。
这里咱们给出DDPG第一个算法实例,代码主要参考自莫烦的Github代码。增长了测试模型效果的部分,优化了少许参数。代码详见:https://github.com/ljpzzz/machinelearning/blob/master/reinforcement-learning/ddpg.py
这里咱们没有用以前的CartPole游戏,由于它不是连续动做。咱们使用了Pendulum-v0这个游戏。目的是用最小的力矩使棒子竖起来,这个游戏的详细介绍参见这里。输入状态是角度的sin,cos值,以及角速度。一共三个值。动做是一个连续的力矩值。
两个Actor网络和两个Critic网络的定义参见:
def _build_a(self, s, scope, trainable): with tf.variable_scope(scope): net = tf.layers.dense(s, 30, activation=tf.nn.relu, name='l1', trainable=trainable) a = tf.layers.dense(net, self.a_dim, activation=tf.nn.tanh, name='a', trainable=trainable) return tf.multiply(a, self.a_bound, name='scaled_a') def _build_c(self, s, a, scope, trainable): with tf.variable_scope(scope): n_l1 = 30 w1_s = tf.get_variable('w1_s', [self.s_dim, n_l1], trainable=trainable) w1_a = tf.get_variable('w1_a', [self.a_dim, n_l1], trainable=trainable) b1 = tf.get_variable('b1', [1, n_l1], trainable=trainable) net = tf.nn.relu(tf.matmul(s, w1_s) + tf.matmul(a, w1_a) + b1) return tf.layers.dense(net, 1, trainable=trainable) # Q(s,a)
Actor当前网络和Critic当前网络损失函数的定义参见:
td_error = tf.losses.mean_squared_error(labels=q_target, predictions=q) self.ctrain = tf.train.AdamOptimizer(LR_C).minimize(td_error, var_list=self.ce_params) a_loss = - tf.reduce_mean(q) # maximize the q self.atrain = tf.train.AdamOptimizer(LR_A).minimize(a_loss, var_list=self.ae_params)
Actor目标网络和Critic目标网络参数软更新,Actor当前网络和Critic当前网络反向传播更新部分的代码以下:
def learn(self): # soft target replacement self.sess.run(self.soft_replace) indices = np.random.choice(MEMORY_CAPACITY, size=BATCH_SIZE) bt = self.memory[indices, :] bs = bt[:, :self.s_dim] ba = bt[:, self.s_dim: self.s_dim + self.a_dim] br = bt[:, -self.s_dim - 1: -self.s_dim] bs_ = bt[:, -self.s_dim:] self.sess.run(self.atrain, {self.S: bs}) self.sess.run(self.ctrain, {self.S: bs, self.a: ba, self.R: br, self.S_: bs_})
其他的能够对照算法和代码一块儿学习,应该比较容易理解。
DDPG参考了DDQN的算法思想吗,经过双网络和经验回放,加一些其余的优化,比较好的解决了Actor-Critic难收敛的问题。所以在实际产品中尤为是自动化相关的产品中用的比较多,是一个比较成熟的Actor-Critic算法。
到此,咱们的Policy Based RL系列也讨论完了,而在更早咱们讨论了Value Based RL系列,至此,咱们还剩下Model Based RL没有讨论。后续咱们讨论Model Based RL的相关算法。
(欢迎转载,转载请注明出处。欢迎沟通交流: liujianping-ok@163.com)