强化学习的理论框架——马科夫决策过程(MDP)
强化学习,本质上是让计算机学会自主决策的方法论。而马可夫决策过程(Markov decision process, MDP)则是强化学习中,对现实问题进行建模的数学模型,它把所有的现实问题都抽象为:
智能体与环境的互动过程; 在互动过程中的每个时间步,智能体都收到环境的状态(环境向智能体呈现一种情况),智能体必须选择相应的响应动作,然后在下一个时间步,智能体获得一个奖励(环境表示智能体是否对该状态做出了正确的响应)和新的状态; 所有智能体的目标都是最大化预期累积奖励,或在所有时间步获得的预期奖励之和。
MDP有以下内涵:
所有的问题都可以看作是任务。并且可以分为阶段性任务与连续性任务:
连续性任务是一直持续下去、没有结束点的任务。 阶段性任务是起始点和结束点明确的任务。 在这种情况下,我们将一个完整的互动系列(从开始到结束)称为一个阶段。 每当智能体抵达最终状态,阶段性任务都会结束。 所有的问题都是基于奖励假设,并且以最大化(预期)累积奖励为目标:
奖励是智能体作出最优决策的驱动因素。 奖励是在互动过程中的每个时间步,由环境反馈并由智能体所获取。 智能体在任意时间点都以最大化(预期)累积奖励作为目标函数进行决策。 在时间步t累积奖励 G_t = R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \gamma^3 R_{t+4} +… ,其中 \gamma 是远期回报的折扣率: - 必须满足 0 \leq \gamma \leq 1 - 如果 \gamma=0 ,智能体只关心最即时的奖励。 - 如果 \gamma=1,回报没有折扣。 - \gamma 的值越大,智能体越关心遥远的未来; \gamma 的值越小,折扣程度越大,在最极端的情况下,智能体只关心最即时的奖励。 - 一般情况下, \gamma 应该设置为更接近1。 MDP模型由以下属性组成:
- 一组(有限的)状态 \mathcal{S} (对于阶段性任务,则是 \mathcal{S}^+ )
- 一组(有限的)动作 \mathcal{A} , \mathcal{A}(s) 是在状态 s \in \mathcal{S} 的潜在行动集合
- 一组奖励 R 或者奖励函数 R_a(s,s')
- 环境的一步动态特性(状态转移概率函数) p(s', r | s, a) = P(S_{t+1}=s', R_{t+1}=r | S_t=s, A_t=a)
- 折扣率 \gamma \in [0,1]
MDP的解题思路
由上述分析可知,智能体要实现自主决策,必然会存在一个策略函数 \pi ,使得对于任意的 s \in S 都存在一个动作(对确定性策略而言)或者一个动作分布(对随机性策略而言)映射 \pi(s) 。再具体一点说:
确定性策略是从 \pi: \mathcal{S}\rightarrow\mathcal{A} 的映射。对于每个状态 s\in\mathcal{S} ,它都生成智能体在状态 s 时将选择的动作 a\in\mathcal{A} 。 随机性策略是从 \pi: \mathcal{S}\times\mathcal{A}\to [0,1] 的映射。对于每个状态 s\in\mathcal{S} 和动作 a\in\mathcal{A} ,它都生成智能体在状态 s 时选择动作 a 的概率。 既然智能体必然会存在一个策略(哪怕这时是个很不靠谱的策略),那么我们就可以得到一个基于这个策略 \pi 的一个状态值函数 v_{\pi} ,这个状态值函数 v_{\pi} 对于每个状态 s \in \mathcal{S} 都能找到一个相应的映射值 v_π(s)≐E_π[G_t ∣S_t =s] :
由于在某个状态 s 根据策略函数 \pi 去选择动作时,环境的状态转移函数是一个概率分布,因此这里所对应的 v_{\pi}(s) 是这个概率分布的数学期望值 E_{\pi} 。 由MDP的定义可知 G_t = R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + \gamma^3 R_{t+4} +… ,因此可以写成Bellman递推公式 G_t = R_{t+1} + \gamma v_{\pi}(S_{t+1}) 因此,把状态值函数用Bellman递推公式表示则有 v_π(s)≐E_π[R_{t+1} + \gamma v_{\pi}(S_{t+1}) ∣S_t =s] 。
对于不同的策略 \pi ,都会对应不同的状态值函数 v_{\pi} 。那么假如有一个策略 \pi' 使得每一个状态 s \in \mathcal{S} 都有 v_{\pi'}(s) \geq v_{\pi}(s) ,那么策略 \pi' 就优于或等同于策略 \pi 。因此,必然存在至少一个最优策略 \pi_* 优于或等同于其他策略 \pi (最优策略必定存在,但可以不唯一)。
那么基于任意一个最优策略 \pi_* 都具有相同的状态值函数 v_* ,称为最优状态值函数。
状态值函数 v_{\pi} 是一个静态的概念,它仅仅反应了当智能体处于某个状态 s 时,依据策略 \pi 去行动的话,它理论上可以得到的累计奖励是多少;而策略 \pi 是一个抽象概念。究竟当智能体处于状态 s 时,它应该采取哪种行动 a \in \mathcal{A} ?因此,需要引入一个动作值函数 q_{\pi} 。动作值函数对于智能体而言,就好比人类的价值评判,它能根据智能体所处的状态 s 以及做相应动作 a 可以得到一个“行为价值评分”,使智能体依据“行为价值评分”的大小去选择实际采取的行动。因此,动作值函数 q_{\pi} ≐ E_{\pi}[G_t | S_t = s, A_t = a] 。
与状态值函数同理,动作值函数用Bellman递推公式表示则有 q_{\pi} ≐ E_{\pi}[R_{t+1} + \gamma q_{\pi}(S_{t+1}, A_{t+1}) | S_t = s, A_t = a]。
策略 \pi 在以上的描述中略显抽象,其实本质上也是一个函数。对于某个策略 \pi , \pi(s) \in \mathcal{A} (其中s \in \mathcal{S}) 。假设我们已经得知最优的动作值函数 q_* ,那么我们很容易就可以得出最优策略 \pi_* ,因为所谓的最优策略,就是在任意时间步 s 所对应的策略,就是在该状态下行动价值评分最高的行动。
因此,最优策略函数 \pi_(s) = argmax_{a \in \mathcal{A}} q_(s, a) 。
但现在的问题是:我们如何获得最优动作值函数 q_* ?
这个问题在不同的情况下会有不同的答案!
情况一(理想状态):智能体了解环境的一切
当智能体了解环境的一切时,这已经不算强化学习的范畴了。这是(运筹学)动态规划的范畴。就是指智能体了解在不同的状态 s \in \mathcal{S} 下采取行动 a \in \mathcal{A} 可以得到多少奖励,而无须通过与环境互动来获取此信息。
正因为智能体了解环境的一切,因此可以通过迭代策略评估的方法很容易就得到在某个策略 \pi下(一般以随机策略作为初始化设置)的状态值函数 v_{\pi} 。
在得知 v_{\pi} 的情况下,便可以用状态值来衡量动作值,即 q_{\pi}(s,a) = \sum_{s' \in \mathcal{S} \ r \in \mathcal{R}} p(s',r | s, a)(r + \gamma v_{\pi}(s')) 。如是遍历所有的状态 s \in \mathcal{S} ,使 \pi'(s) \leftarrow argmax_{a \in \mathcal{A}}q_{\pi}(s, a) 进行策略改进。
最后,重复以上过程进行策略迭代,当 \pi = \pi' 时,意味着得到最优策略 \pi_* 。
以上是情况一的算法思路概况。以下是算法具体的伪代码:
迭代策略评估,目标是求出状态值函数
估算动作值函数,利用状态值函数求动作值函数
策略改进,利用动作值函数改进策略
策略迭代,重复以上步骤直到策略不再改变,从而得到最优策略 经过以上步骤,最终就得到了最优策略 \pi_* 。然而,上述算法的时间复杂度非常高,因为每次计算状态值函数都要进行多次遍历所有状态。而实际上,状态值函数只是为了更新动作值函数,从而得到一个较好的行动策略,因此即使状态值函数不精确,也不影响各个动作值的相对关系。于是,有了以下的算法优化方案:
用少次数的迭代求得不精确的状态值函数V
沿用之前的策略改进函数,使用截断策略评估函数代替原来的策略评估函数,当状态值函数的更新小于阀值则代表此时的π就是最优策略 用少次数(多于一次)的迭代策略评估所得到的算法优化方案,称为截断策略迭代。
这里值得一提的是,在策略迭代中,循环的终止条件是 \pi = \pi' ,即策略不再变化;而在截断策略迭代中,循环的终止条件是 max_{s \in \mathcal{S}}|V(s)-V_{old}(s)| < \theta ,即状态值函数已经收敛。为何会有不同?
原因是在策略迭代中的算法逻辑是“先求出收敛的 v_{\pi} ,再求 q_{\pi} ,最后得 \pi' \leftarrow maxarg_{a \in \mathcal(A)} q_{\pi}(s,a) ,直到没一个 \pi' 优于之前的 \pi ,那么便得到了最优策略 \pi_* ”。
而在截断策略迭代中,算法逻辑是“用一个不精确的状态值函数 V 来求一个不精确的动作值函数 Q ,然后得到一个策略更新 \pi' \leftarrow maxarg_{a \in \mathcal(A)} Q(s,a) ,只要状态值函数 V 收敛,就能得到一个最优策略 \pi_* “。
而仅循环一次的迭代策略评估所得到的算法优化方案,称为值迭代。
仅循环一次的截断策略迭代函数重构后的伪代码,称为值迭代 值迭代的优化逻辑是,用零矩阵作为状态值函数 V 的初始矩阵,然后以当时状态 s 下的最优行动 a 来更新状态值,并遍历每个状态,直到更新值小于阀值。这时得到的状态值函数便是基于最优策略所得到的状态值函数 v_* 。根据 v_* 则容易求得 q_* ,有了 q_* 便有了 \pi_* 。
值迭代与最开始的策略迭代,在逻辑上最大的区别是,在估算状态值函数 V 时:
策略迭代算法中, V(s) = \sum_{a \in \mathcal{A}} \pi(a | s) \sum_{\ s' \in \mathcal{S} \ r \in \mathcal{R}} p(s', r | s, a)(r + \gamma V(s')) ,即在更新 V 函数时考虑全部的行动可能。 值迭代算法中, V(s) = max_{a \in \mathcal{A(s)}} \sum_{s' \in \mathcal{S} \ r \in \mathcal{R}} p(s', r | s, a)(r + \gamma V(s')) ,即在更新 V 函数时,仅考虑动作值最高的行动。
情况二:智能体需要与环境互动来得到反馈
我们知道强化学习的目标是让智能体学会最优策略 \pi_* ,而学会最优策略的逻辑是:用不精确的状态值函数 V\rightarrow 求得不精确的动作值函数 Q\rightarrow 得出不准确的较优策略 \pi' ,然后迭代这个过程最终使状态值函数收敛,从而得到最优策略 \pi_* 。
当智能体了解环境的全部时,无需通过与环境的互动来得到反馈。可问题是,在绝大多数情况下,智能体都无法得知环境的奖励信息 R 以及状态转移概率函数 Pr ,因此只能通过让智能体与环境进行互动,来获取这些奖励反馈。
根据MDP的定义,我们知道在智能体与环境互动的过程,可以分为阶段性任务与持续性任务。它们之间的根本区别在于,前者有明确的终止状态 S_T 而后者没有。因此智能体与环境互动的经验元组如下:
阶段性任务: < S_0,A_0,R_1,S_1,A_1,R_2,...,S_n,A_n,R_{n+1},S_T> 持续性任务: < S_0,A_0,R_1,S_1,A_1,R_2,...,S_n,A_n,R_{n+1},S_{n+1},......> 那么,智能体要如何利用这些经验元组去估算当前策略 \pi 的状态值函数 v_{\pi} 及 q_{\pi} ,从而可以不断进行策略改进找到更好的策略 \pi' ,最终找到最优策略 \pi_* ?
解题思路有两种:蒙特卡罗方法(Monte Carlo method,简称MC法)、时间差分方法(temporal difference,简称TD法)。
MC法:
在讨论蒙特卡罗方法之前,应该先认识一下什么是蒙特卡罗方法。
Monte Carlo methods (or Monte Carlo experiments) are a broad class of computational algorithms that rely on repeated random sampling to obtain numerical results. —— Monte Carlo method, from Wikipedia 首先蒙特卡罗方法是一种算法,通过重复地生成随机样本去近似地计算目标函数,其算法的核心思想就是大数定律。
—— Monte Carlo method, from Wikipedia 沿用wiki上的例子:用蒙特卡罗方法求四分之一圆的面积。
在 x \in [0,1], y \in [0,1] 范围内以均匀分布生成随机点 (x, y),然后把 \sqrt{x^2+y^2} \le 1 的点标记为红色,其余的标记为蓝色。再计算 \frac{\sum 红点个数}{\sum 所有点个数} ,得到的比例约等于 \frac{\pi}{4} (当所有随机点总数达30000个时,误差仅为0.07%)。
那么,MC方法如何应用在强化学习的问题中呢?
强化学习的核心思想是通过状态值函数 V 或者动作值函数 Q 去改进策略 \pi 从而得到更好的策略 \pi' 。因此,可以概括地描述为两个步骤: 评估\Leftrightarrow 改进 。
评估,指的是对状态值函数 V 或者动作值函数 Q 进行估算; 改进,指的是根据 Q 去更新执行策略; 然后不停要重复以上两个步骤,直到策略收敛。 好了,我们如何评估状态值函数与动作值函数呢?
刚才提到,智能体无法得知环境的奖励信息 R 以及状态转移概率函数 Pr 。这时就可以用蒙特卡罗方法,根据策略 \pi 去生成经验元组然后通过计算经验元组的期望值去估算真实状态值函数 v_{\pi} 及真实动作值函数 q_{\pi} ,即:
V(s) = E[G_t | S_t = s] ,求出所有状态 s \in \mathcal{S} 下收益的期望值,便可以得到一个近似的状态值函数 V\approx v_{\pi} ; 同理, Q(s,a) = E[G_t | S_t = s, A_t = a] ,求出所有状态&行动组 <s,a> 下收益的期望值,便可以得到一个近似的动作值函数 Q \approx q_{\pi} 。 这里有几个要点需要注意的:
对于同一个阶段的经验元组,当同一个状态或者同一对状态&动作组,如果出现两次及以上,处理的手法有两种:1. 仅考虑首次出现;2. 每次出现都考虑。仅考虑首次的处理方式不会出现偏差,具体原理可参考此论文。两种的处理手法只要访问的次数足够多,最终都会共同收敛为相同的值。 由于智能体并不知道环境的状态转移概率函数 Pr ,因此并不能用状态值函数 V 去表达动作值函数 Q ,因此 V 函数可以忽略,直接用经验元组去估算 Q 函数。 具体的伪代码如下:
仅考虑首访的Q函数代码 代码说明:
子函数 N(s,a) 用于记录 <s,a> 在每个回合(由 S_0 到 S_T )出现的次数; 子函数 returns_sum(s,a) 用于记录 <s,a> 的累计奖励 最终 Q(s,a) 就是 <s,a> 的平均奖励 求得 Q 函数的真值后,就可以根据 Q 来改进策略。然而,以上求 Q 函数的过程需要大量的的随机样本才能使函数接近真值,而每次更新策略后,又要重新计算 Q ,这样的算法时间复杂度太高,因此需要对算法进行优化。
优化的切入点有两个:
评估环节:使用动态更新算法,使得 Q 函数的计算移入循环内,这样首先是减少了原本在计算 Q 函数时对 s 及 a 的遍历; 改进环节:原本是先求出 Q 函数,再进行策略改进;优化后,把策略改进移入循环内,达到边改进边求 Q 函数的效果;另外,引入 \epsilon 系数,使得智能体能既能保证贪心策略又能兼用随机策略,从而保障 Q 函数的完整性提高可信度。贪心策略令智能体能“学以致用”,而随机策略令智能体有机会探索“未知的可能性”。 优化后的伪代码如下:
代码写到这里,还有一个问题:
之前提过子函数 N(s,a) 用于记录 <s,a> 出现的次数,因此随着次数的增加,导致 Q(s,a) 的更新会越来越小。而实际生活中,世界总是不断变化的,最近的经验所占的权重应当大于多年以前的经验。因此,经验更新系数 \frac{1}{N(s,a)} 更改为一个常量 \alpha 。于是有了以下伪代码:
需要说明的是,该算法中,当迭代的次数足够大的时候,策略会最终收敛为最优策略 \pi_* 。而“多大才算足够大?”的问题则没有明确的答案,需要根据状态空间 \mathcal{S} 与动作空间 \mathcal{A} 、以及具体的环境反馈而定。
TD学习:
从刚才的MC方法,我们知道 Q(s,a) = E[G_t | S_t = s, A_t = a] ,而 其中的G_t = R_{t+1} 。但我们在MDP的解题思路中提到 G_t = R_{t+1} + \gamma Q(S_{t+1}, A_{t+1}) ,如果我们把公式写成 Q(s,a) = E[R_{t+1} + \gamma Q(S_{t+1}, A_{t+1})| S_t = s, A_t = a] 可不可以呢?答案是当然可以,但写成这种递推方程的形式后,算法就不再叫蒙特卡罗方法了,叫时间差分学习(Temporal-Difference Learning)。因为这里定义的蒙特卡罗方法,就是用单纯的随机数的统计量关系去表达近似的函数值。
Monte Carlo methods are ways of solving the reinforcement learning problem based on averaging sample returns. To ensure that well-defined returns are available, here we define Monte Carlo methods only for episodic tasks. That is, we assume experience is divided into episodes, and that all episodes eventually terminate no matter what actions are selected. Only on the completion of an episode are value estimates and policies changed. Monte Carlo methods can thus be incremental in an episode-by-episode sense, but not in a step-by-step (online) sense. The term “Monte Carlo”is often used more broadly for any estimation method whose operation involves a significant random component. Here we use it specifically for methods based on averaging complete returns (as opposed to methods that learn from partial returns, considered in the next chapter). --[2]《Reinforcement Learning: An Introduction》, Chapter 5 Monte Carlo Methods 蒙特卡罗方法最大的局限在于它仅仅适用于阶段性任务(它自己就是这么定义的)。而日常生活当中的常见问题往往都需要以持续性任务的模型去演绎。好比让智能体学习驾驶,如果视驾驶为阶段性任务,那么智能体只能等到出了车祸才能视为一个回合;而若视为持续性任务,那么智能体可以在每时每刻都可以在学习。因此,这里需要用到TD学习。
代码说明:
该算法称为Sarsa,名称源于算法是基于 (S_t , A_t , R_{t+1} , S_{t+1} , A_{t+1}) 作为计算依据; 该算法的最终结果是一个最优动作值函数 q_{} ; 有了 q_ 就很容易得到最优策略函数 \pi_(s) = argmax_{a \in \mathcal{A}}q_(s,a) ; 该算法能通用于阶段性任务及持续性任务; 该算法与MC方法类似,用了一个衰减的 \epsilon 系数来控制探索与利用的概率,使 Q 函数更接近真值,同时每次更新 Q 函数前会使用 \epsilon -greedy 函数改进策略。 在Sarsa算法中,收益函数 G_t = R_{t+1} + \gamma Q(S_{t+1}, A_{t+1}) 中的 A_{t+1} 用的是 \epsilon -greedy 函数计得,即有一定的概率使收益函数不是最大值。若要使收益函数保证取最大值,那么收益函数需要修改为 G_t = R_{t+1} + \gamma max_{a}Q(S_{t+1}, a) ,具体的伪代码如下:
该修改后的算法称为Sarsamax,或者又叫Q-learning 除了Q-learning与Sarsa外,还有一种算法是基于行动概率的期望值,即收益函数为 G_t = R_{t+1} + \gamma \sum_{a} \pi(a|S_{t+1})Q(S_{t+1}, a) ,具体的伪代码如下:
该算法称为期望Sarsa TD学习的三种算法的特点总结如下(具体可参阅该教科书(尤其是第 6.4-6.6 部分)的第 6 章节):
在以下情况下,所有 TD 控制算法(Sarsa、Sarsamax、期望 Sarsa)都会收敛于最优动作值函数 q_* (并生成最优策略 \pi_* ):(1)ϵ 的值根据 GLIE 条件逐渐降低,以及 (2) 步长参数 α 足够小。 Sarsa 和期望 Sarsa 都是同步策略(on-policy) TD 控制算法。在这种情况下,我们会根据要评估和改进的相同(ϵ 贪婪策略)策略选择动作。 Sarsamax 是异步策略(off-policy)方法,我们会评估和改进(ϵ 贪婪)策略,并根据另一个策略选择动作。 同步策略 TD 控制方法(例如期望 Sarsa 和 Sarsa)的在线效果比异步策略 TD 控制方法(例如 Sarsamax)的要好。 期望 Sarsa 通常效果比 Sarsa 的要好。