本文为参考李宏毅老师的”Deep Reinforcement Learning, 2018”课程所作的个人笔记。
课程YouTube地址:Deep Reinforcement Learning, 2018。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.Basic Idea
强化学习的目标就是学习一个最优策略,可以使奖赏最大化。那么根据如何学到这个最优策略,可以将强化学习分为如下三类:
- value-based
- policy-based
- actor-critic
policy-based方法会直接学习并优化目标策略,例如我们之前提到的policy gradient、PPO、TRPO。
value-based方法通过状态值函数(后续简称V函数)或状态-动作值函数(后续简称Q函数),估计从某个状态或状态-动作对出发的累积回报;再依据值函数选择价值更高的动作,从而间接得到并优化策略。Q-learning就是典型的value-based方法。但由于理论的值函数通常是未知的,我们就需要一个critic(实际学习出来的评价器)来近似,这个critic可以是一张表、线性函数或者神经网络。
actor-critic则结合了value-based和policy-based的思想。actor决定依据当前策略哪个动作会被选择,critic则对动作进行评估。有些actor-critic方法是on-policy的,有些则是off-policy的。

Q-learning作为value-based方法,其要学的不是策略本身,而是critic。critic并不会直接决定动作,它只是评价动作的好坏。
学习critic的第一个方法是MC(Monte-Carlo)。试想一下,如果我们使用理论的V函数(Q函数同理),就要穷举所有可能的状态,并且针对每个状态,我们要知道所有其可能的后续轨迹,这样我们才能知道该状态所有可能得到的累积奖赏值,从而求出该状态的累积奖赏期望,即V函数,这在很多情况下是不可能实现的。因此,我们需要学习一个critic来对理论值函数进行近似。MC方法的核心就是通过多次采样求平均来近似期望。比如,针对某一状态,我们可以采样多条包含此状态的轨迹,计算从该状态出发到最后得到的累积奖赏值,求这些值的平均来近似该状态的累积奖赏期望(可以通过这种方式采集很多“状态-累积奖赏”对,作为critic的训练数据)。参照下图,针对V函数,假设critic是一个神经网络模型,其输入是一个状态,输出是从该状态出发,得到的累积奖赏的期望。这样即使是面对从没见过的状态,网络模型也能预测得到一个累积奖赏。

学习critic的第二个方法是TD(Temporal-Difference)。在MC方法中,针对某个状态,我们需要一直跟踪到轨迹结束,才能得到一个累积奖赏值,这会比较费时间。还是以V函数为例,参照下图,TD方法不需要等到轨迹结束,其只需考虑相邻两个状态即可,核心公式就是$V^{\pi}(s_t) = V^{\pi} (s_{t+1}) + r_t$。对于同一神经网络模型(即critic),输入为$s_t$时,输出为$V^{\pi}(s_t)$;输入为$s_{t+1}$时,输出为$V^{\pi}(s_{t+1})$,通过让$V^{\pi}(s_t) - V^{\pi} (s_{t+1})$逼近$r_t$来优化critic的参数。

对于MC方法,从某一状态出发,要一直追踪到轨迹结束才能获得累积奖赏,需要采样多条轨迹来求得累积奖赏的平均,在采样每条轨迹时,每个时间步都可能包含随机变量,所以随机性会不断累积,多条轨迹得到的累积奖赏值差异可能很大,所以说MC方法通常具有“高方差”,但由于每个累积奖赏都是实际轨迹计算得到的,所以MC方法还是“低偏差”。而对于TD方法,其只采样一步,拿到当前状态所产生的奖赏即可,随机性小了很多,所以TD方法是“低方差”,但由于$V^{\pi}(s_t)$和$V^{\pi}(s_{t+1})$都是由模型预测得到的,而不是真实产生的,所以TD方法还是“高偏差”。通常,TD方法更为常用一些。
接下来举个例子,假设采样了8条轨迹:
- $s_a,r=0,s_b,r=0,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=1,\text{END}$
- $s_b,r=0,\text{END}$
以第1条轨迹为例,从状态$s_a$出发,得到奖赏0,然后到达状态$s_b$,得到奖赏0,轨迹结束。综合8条轨迹,按照MC方法,我们可以得到:
\[V^{\pi} (s_b) = \frac{6}{8} = \frac{3}{4}, \quad V^{\pi} (s_a) = 0\]但如果按照TD方法:
\[V^{\pi} (s_a) = V^{\pi} (s_b) + r = \frac{3}{4} + 0 = \frac{3}{4}\]两种方法得到了不同的$V^{\pi} (s_a)$。
$Q^{\pi} (s,a)$表示在遇到状态$s$时,强制选择动作$a$,之后再按照策略$\pi$完成轨迹,最终得到累积奖赏期望。之前提到过,我们也需要一个critic来逼近Q函数,如下图所示,critic的构建有2种不同的方式,第一种方式,输入是状态$s$和动作$a$,输出就是累积奖赏期望;第二种方式,输入是状态$s$,输出是选择不同动作时对应的累积奖赏期望,但第二种方式只能针对离散动作变量(即动作数量是有限的)。

接下来我们就可以依据Q函数来对策略$\pi$进行优化,得到更好的策略$\pi ‘$:
\[\pi ' (s) = \underset{a}{\text{arg max}} Q^{\pi} (s,a) \tag{1}\]也就是说,对于策略$\pi ‘$,在遇到任意状态$s$时,会选择Q函数值最大的那个动作$a$。那该如何证明策略$\pi’$一定优于策略$\pi$呢?所谓的策略$\pi ‘$优于策略$\pi$,其实就是要证明对于任意状态$s$,都有$V^{\pi ‘}(s) \geqslant V^{\pi} (s)$。证明如下:
\[\begin{align*} V^{\pi} (s) &= Q^{\pi} (s, \pi (s)) \\& \leqslant \underset{a}{\max} Q^{\pi} (s,a) \\&= Q^{\pi} (s, \pi'(s)) \\&= E [ r_t + V^{\pi} (s_{t+1}) \mid s_t = s , a_t = \pi' (s_t) ] \\& \leqslant E [ r_t + Q^{\pi} (s_{t+1}, \pi' (s_{t+1})) \mid s_t = s , a_t = \pi'(s_t) ] \\&= E [ r_t + r_{t+1} + V^{\pi} (s_{t+2}) \mid \cdots ] \\& \leqslant E [ r_t + r_{t+1} + Q^{\pi} (s_{t+2}, \pi'(s_{t+2})) \mid \cdots ] \\& \cdots \\& \leqslant E [ r_t + r_{t+1} + r_{t+2} + \cdots ] \\&= V^{\pi'} (s) \end{align*} \tag{2}\]推导过程可以直观的表示为:
- 原始策略为:$\pi (s_1), \pi(s_2), \pi (s_3), …. , \pi(s_n)$。
- 推导第一步就是在状态$s_1$时,选择Q函数值最大的动作,此时的策略为:$\pi’ (s_1), \pi(s_2), \pi (s_3), …. , \pi(s_n)$,此时的新策略相比于原始策略是更优的。
- 第二步继续优化:$\pi’ (s_1), \pi’ (s_2), \pi (s_3), …. , \pi(s_n)$。
- 一直优化到最后:$\pi’ (s_1), \pi’ (s_2), \pi’ (s_3), …. , \pi’ (s_n)$,得到完整的新策略$\pi ‘$。
式(2)的推导也可参考此处:【机器学习基础】第七十五课:[强化学习]有模型学习。
下图是TD方法在Q函数上的应用:

假设用于近似Q函数的critic是一个神经网络模型,即图中的橙色矩形。$s_t,a_t,r_t,s_{t+1}$是采集的样本数据,用于训练critic。如图所示,我们需要两个网络模型,第一个模型的输入为$s_t,a_t$,输出为$Q^{\pi}(s_t,a_t)$;第二个模型的输入为$s_{t+1},\pi (s_{t+1})$,输出为$Q^{\pi} (s_{t+1},\pi (s_{t+1}))$。训练目标是让两个模型的输出的差值越接近$r_t$越好,即让$Q^{\pi}(s_t,a_t)$接近$Q^{\pi} (s_{t+1},\pi (s_{t+1})) + r_t$。如果在训练时,让两个模型保持一样,共享参数,同步更新,那相当于$Q^{\pi}(s_t,a_t)$和$Q^{\pi} (s_{t+1},\pi (s_{t+1})) + r_t$都在变化,这会导致训练很不稳定。因此,我们会将第二个模型固定,这样第一个模型的训练目标就是固定的了,此时在训练时,只更新第一个模型。在第一个模型更新多轮之后,第二个模型才会和第一个模型同步更新一下。
当前,我们基于有限的样本数量,对Q函数进行了近似,这也导致了$\underset{a}{\text{arg max}} Q (s,a)$选择的不一定是真正最好的动作。此外,环境和奖赏可能也是随机的,通过$\underset{a}{\text{arg max}} Q (s,a)$选择的动作在此后不一定是最优的。因此,我们需要在动作选择上增加一些随机性:
\[a = \begin{cases} \underset{a}{\text{arg max}} Q (s,a), & \quad \quad \text{with probability } 1-\epsilon \\ \text{random}, & \quad \quad \text{otherwise} \end{cases} \tag{3}\]此外,在训练早期,$Q(s,a)$的近似并不准确,此时应该多探索,所以可以让$\epsilon$较大。随着训练的进行,$Q(s,a)$的近似越来越准确,此时就没必要大量探索其他动作了,于是可以让$\epsilon$随着训练的进行逐渐变小。式(3)这个方法被称为epsilon greedy。
还有另外一个增加动作选择随机性的方法叫做boltzmann exploration,其按照每个动作的概率进行选择:
\[P(a \mid s) = \frac{\exp (Q(s,a))}{\sum_a \exp (Q(s,a))} \tag{4}\]我们先用策略$\pi$和环境互动多次,得到一些诸如$(s_t,a_t,r_t,s_{t+1})$的样本,这些样本被存放在buffer中,然后在训练时,会从buffer中取一个batch的数据用于训练,然后更新策略为$\pi’$,$\pi’$继续与环境互动多次进行数据采集,依旧存放在buffer中,当训练继续从buffer中取数据时,可能会取到不同策略采集的数据,这对训练过程非但没有坏处,反倒有利于训练。一方面,这节省了大量依据新策略重新采集数据的时间,另一方面,这也增加了一个batch内数据的多样性。
一个典型的Q-learning算法的步骤可总结如下:
- 初始化两个critic用于近似Q函数:$Q$和$\hat{Q}$,并且让$\hat{Q} = Q$。
- 对于每次迭代:
- 对于每个时间步$t$:
- 基于epsilon greedy,给定状态$s_t$,选择动作$a_t$。
- 得到奖赏$r_t$,到达新状态$s_{t+1}$。
- 将$(s_t,a_t,r_t,s_{t+1})$存入buffer。
- 从buffer中取出数据$(s_i,a_i,r_i,s_{i+1})$(通常是取一个batch的数据)。
- 运行第二个模型,求$y = r_i + \underset{a}{\max} \hat{Q} (s_{i+1}, a)$。
- 更新第一个模型$Q$的参数,使$Q(s_i,a_i)$接近$y$。
- 每经过$C$步,就将第二个模型$\hat{Q}$更新为第一个模型$Q$,即执行$\hat{Q} = Q$。
- 对于每个时间步$t$:
对于Q-learning,如果critic是深度神经网络,那么我们将其称为Deep Q-Network,简称DQN。
2.Advanced Tips
2.1.Double DQN

在上图中,4个子图分别表示4个不同的任务。横轴为训练步数,纵轴为评估的奖赏值。橙色曲线表示,在每个训练阶段(策略也是随着训练的进行而在不断的优化),采样多个状态,分别送入DQN,输出预测的奖赏值,将这些奖赏值求平均,绘制为橙色曲线。蓝色曲线是类似的绘制方法,只不过是将DQN替换为Double DQN。橙色直线表示的是,采用DQN方法最终优化好的策略,让其在真实环境中执行成百上千次,将这些不同状态的奖赏值求平均,绘制在图中,作为真实值的近似。蓝色直线类似,只不过是使用Double DQN最终优化好的策略去与环境互动。
从上图可以看出,DQN总是会高估Q值。而Double DQN估计的Q值就比较接近真实值。此外,蓝色直线代表的Q值要比橙色直线好,表示Double DQN学得的策略更优。
为什么DQN会高估Q值呢?关键原因就是$\underset{a}{\max} \hat{Q} (s_{i+1}, a)$这一步(DQN的步骤见第1部分末尾)。举个例子,假设状态$s’$有三个动作,它们真实价值全部都是$Q^*(s’,a_1) = Q^*(s’,a_2) = Q^*(s’,a_3) = 10$,但是神经网络不可能完全准确,某一次预测可能是:$\hat{Q}(s’, a_1) = 9, \hat{Q}(s’,a_2) = 11, \hat{Q}(s’, a_3) = 10$,整体看平均值依旧是10,但DQN会选奖赏最大的动作$a_2$,其预测奖赏值为11,而真实值却是10,所以就存在高估的问题。
在原始的DQN算法中,第一个模型学习的目标价值的计算为$r_i + \underset{a}{\max} \hat{Q} (s_{i+1}, a)$,可以发现,动作$a$的选取以及目标价值的计算都依赖$\hat{Q}$模型。而在Double DQN中,为了避免Q值被高估,动作$a$的选取以及目标价值的计算依赖两个不同的神经网络模型。Double DQN的目标价值的计算为$r_i + \hat{Q} (s_{i+1}, \underset{a}{\text{arg max}} Q’ (s_{i+1},a))$。之所以Double DQN可以避免Q值被高估,原因在于,如果$Q’$高估了动作$a$的价值,$\hat{Q}$可以将其修正到一个合理的值;如果$\hat{Q}$高估了某个动作的价值,这个动作可能并不会被$Q’$所选取。需要注意的是,在实际实现时,第一个模型$Q$和$Q’$使用同一个模型,参数实时更新,而$\hat{Q}$和DQN中一样,会被冻结一段时间后才会更新一次。
Double DQN相较于DQN,改动非常小。
2.2.Dueling DQN
Dueling DQN和普通DQN的唯一区别就是网络结构不同,但网络的输入和输出类型还都是一样的:

上面的子图表示普通DQN,下面的子图表示Dueling DQN。在Dueling DQN的网络结构中,$V(s)$的作用类似V函数,用于评价状态$s$本身整体有多好;$A(s,a)$的作用类似这里式(10)中的A,用于表示选择的动作$a$,相比其他动作,相对来说好了多少。
接下来解释下这样改的好处在哪里。如下图所示,这里我们假设状态和动作都是离散变量。

假设在一次训练中,网络的训练目标$Q(s,a)$发生了如下变化:

那么网络就需要更新参数来逼近新的训练目标$Q(s,a)$,假设网络只需要更新$V(s)$的值如下:

此时,我们会发现未被采样到的同一状态下的其他动作的Q值也会随之更新:

这就是Dueling DQN的优势所在。那现在一个新的问题就是,如何让网络倾向于更新$V(s)$,而不是$A(s,a)$呢?一个比较直觉的想法就是让$A(s,a)$的更新变得麻烦一些,网络就会倾向于去更新更容易被更新的$V(s)$。一个简单的做法就是,限制每个状态下,其所有的$A(s,a_1),A(s,a_2),A(s,a_3),…$的平均值为0。

2.3.Prioritized Reply
在之前训练中,TD error更大的数据更容易被后续训练采样到:

2.4.Multi-step
结合MC和TD两种方法的思想,采样间隔拉长到$N$步:

2.5.Noisy Net
之前介绍过,式(3)通过在选择动作时增加随机性,来避免DQN总是选择当前估计的最优动作,从而错过其他可能更好的动作。我们可以通过给网络参数施加高斯噪声来达到同样的目的。假设原始的网络记为$Q(s,a)$,给参数施加高斯噪声后的模型记为$\tilde{Q}(s,a)$,在选择动作时,可以直接$a = \underset{a}{\text{arg max}} \tilde{Q} (s,a)$。
2.6.Distributional Q-function
DQN预测的$Q^{\pi} (s,a)$是一个期望值,相当于是一个概率分布的期望,但有一个问题就是,同一个期望值,可以对应不同的概率分布,如下图所示:

假设只有3个动作,下图左为普通的DQN,下图右为Distributional Q-function:

上图右输出的是3个概率分布,绿色部分的概率分布对应$Q^{\pi} (s,a_1)$,黄色部分的概率分布对应$Q^{\pi} (s,a_2)$,蓝色部分的概率分布对应$Q^{\pi} (s,a_3)$。
3.Continuous Action
在之前的Q-learning介绍中,我们都是假设动作是离散的,即可选择动作的数量是有限的,那如果动作是连续的,比如动作是控制车轮转动的角度,此时可选择的动作数量就是无限的,Q-learning解决连续型动作并不容易,因为Q-learning的一个核心就是计算$a = \underset{a}{\text{arg max}} Q(s,a)$,如果$a$的取值是无限的,这个式子的计算就会比较难。
第一个解决办法就是采样大量的动作$a$,分别计算$Q(s,a)$,最终选取Q值最大的那个动作。
第二个解决办法是将$a$看作是Q网络的一个参数,只调整参数$a$,通过梯度下降法来寻找最优动作。
第三个解决办法是特别设计一个Q网络,如下:
