3. 动态规划(Planning by Dynamic Programming)

3. 动态规划(Planning by Dynamic Programming)

本系列文章来自David Silver 的网络公开课。若有问题,欢迎交流~
link: Teaching
原创内容,转载请联系作者。

概述

基础知识回顾:动态规划的要素

  • 最优子结构(Optimal substructure):
    • 最优子结构意味着,我们的问题可以拆分成一个个的小问题,通过解决这个小问题,最后,我们能够通过组合小问题的答案,得到大问题的答案
  • 重叠子问题(Overlapping subproblems)Expectation
    • 子问题出现多次,并且子问题的解决方案能够被重复使用
  • Markov decision processes 满足这两者的条件
    • Bellman equation提供了递归的拆分问题的方法
    • value function存储的数据可以被重复使用

动态规划在求解MDP的应用

  • 动态规划应用于MDP的规划问题(planning)而不是学习问题(learning),我们必须对环境是完全已知的(Model-Based),才能做动态规划,直观的说,就是要知道状态转移概率和对应的reward才行
  • 动态规划能够完成预测问题和控制问题的求解(定义请看第一章)
    • 预测问题:
      • Input: MDP <S; A; P; R; \gamma> and policy \pi 或者 MRP<S; P^π; R^π; \gamma>
      • Output: value function v_{\pi}
      • 也就是说,预测问题是根据当前的MDP过程,来衡量每一个状态的value
    • 控制问题:
      • Input: MDP <S; A; P; R; \gamma> without policy
      • Output:optimal value function v_{*} ,进而输出optimal policy \pi_{*}

Policy Iteration

Policy Iteration 被分为两个部分,首先,我们需要给定一个policy \pi

  • Policy evaluation :评估 \pi 的value function, v_{\pi} (当前策略下每一个状态的价值)
  • Policy improvement :根据得到的 v_{\pi} ,利用贪心算法获得优化的policy \pi'
  • 根据得到的 \pi' 以及我们的状态转移概率,进行新的一轮Policy evaluation
  • 这个过程一直持续到新旧两轮迭代的相同

我们用图片来直观表现这个过程:

接下来,我们分成Policy Evaluation 和 Policy Improvement来展开。

Policy Evaluation

知识回顾:

我们将使用Bellman Expectation Equation来解决Policy 的估计的问题,先回忆一下上章我们推出的Bellman Expectation Equation

  • state-action-state:

\begin{align*} v_\pi(s)&=\sum_{a \in A}\pi(a|s)p_{\pi}(s,a)\\ &=\sum_{a \in A}\pi(a|s)(R^a_s+\gamma \sum_{s^{'} \in S} P^a_{ss^{'}}v_{\pi}(s^{'})) \end{align*}

价值评估的解决方案

  • 我们的目标是给定任意一个policy,我们来通过迭代找到一个最优的policy,我们的做法就是迭代使用Bellman Expectation Equation。
  • 首先,我们会初始化一个value function的值,比如全部置为1,同时初始化一个policy。这个初始化不会影响迭代结果,并且,它不会影响收敛速率。
  • 接着使用Bellman Expectation Equation,利用已经得到的value function来计算新一轮迭代得到的value function。我们的Bellman Expectation Equation就变成了:

v_{k+1}=\sum_{a \in A}\pi(a|s)(R^a_s+\gamma \sum_{s^{'} \in S} P^a_{ss^{'}}v_{k}(s^{'}))

  • 重复这个过程,一直到恒定不变为止(即收敛),我们会在之后说明,这个迭代过程的结果一定会使得收敛。
  • 稳定后的就是我们本轮迭代得到的value function,他是对当前的policy的评估。

Example

在我们的例子中,是一个根据网格最快达到灰色点的学习过程。

  • action初始化为随机的等概率四个方向进行
  • 所有的reward都是-1,除了进入灰色格子的reward
  • 我们的 \gamma =1 ,也就是说,对于未来的状态的评估v ,我们是不带折扣的加入的
  • 我们的目标是最快达到灰色格子的状态

我们的迭代过程如下,左边一列就是迭代的每一轮的value function,读者可以尝试自己计算一下:

  • 这里的小数点后面的数据没有显示出来
  • 我们求k=3的时候,表达式右边的v用的是k=2的v

Policy improvement

算法流程

  • 首先,我们根据得到的value function ,使用贪心算法(greedy policy)来更新我们policy,以Deterministic Policy为例:

\begin{equation} \pi^{'}(a|s)= \begin{cases} 1 & a= arg \max_{a \in A} q_{\pi}(s,a) \\ 0 & otherrwise \\ \end{cases} \end{equation}

  • 对于任意的状态s,他的更新前后的policy是否相等,也就是判断policy是否已经收敛,此时,如果相等,则退出循环。如果不相等,使用新的 \pi' 进行policy evaluation,得到新的 v_{\pi'}(s)
  • 将greedy policy进行展开,可以得到:

更新过程:

直观的理解,假设我们现在用的是Deterministic Policy:如果我们在原来的policy的基础上,改变其中的一个所采用的action a',如果他所得到的q,比原来我们对该状态的评估的value更高,用公式表示就是:

q_{\pi_2}(s,a') > v_{\pi_2}(s)=\max _{a \in A}q_{\pi_1}(s,a)

那么,我们可以认为,以后如果再进入这个状态,我们使用新的action a' ,我们将一定能得到更好的结果。所以,我们可以代替原来的policy,即 \pi'(s)=a' 。如果我们这个过程中,一直选择当前状态 s 所能达到的最好的q的来进行更新(也就是看看哪个a导致q最大),这个过程就是policy improvement的过程,进一步拓展:

我们前面基于单个的state进行更新,我们完全可以基于同样的思路,将这个更新过程拓展到所有的state,也就是说,每一轮迭代,我们以原来的policy \pi 为基础,对每一个state进行更新,这就有了我们的更新公式,我们对于任意的 s \in S 做下面的操作:

\begin{align} \pi'(s)&=arg \max_a q_{\pi}(s,a)\\ &=arg \max_a (R_s^a+ \gamma \sum_{s' \in S} P_{ss'} v_\pi(s')) \end{align}

补充一点:对于Stochastic policy,也就是说,每一个 \pi'(s) 对应的不是一个唯一的action,而是每一个action发生的概率组成的向量,此时:

q_\pi(s,\pi'(s))= \sum_a \pi'(s,a) q_\pi(s,a)

这样一来,求最好的的过程,就可能不是简单的选择某一个action这么简单,而是做action最大化的一个概率组合。但是这不影响我们的这个更新的过程的正确性

Value function 一定越来越好的证明

前面我们说,我们可以认为,以后如果再进入这个状态s,我们使用新的action a' ,我们将一定能得到更好的结果。

那么,对于整体的策略而言,已知旧的policy中部分使用更好的policy而得到新的policy,当我们用新的policy来重新评估的时候,我们将一定能得到更好的value function嘛?也就是说,在这个过程中, v_{\pi'} >v_{\pi} ,是不是对于所有的s恒成立?下面我们以deterministic policy 进行证明:

首先考虑对于任意的s, q_{\pi}(s,\pi'(s)) v_\pi(s) 之间的关系

  • 明确 q_{\pi}(s,\pi'(s))\pi\pi' 的含义:他表示我们当前q的选取依然依赖原本的policy \pi,因为q的计算表达式右侧中,需要用到v或者q来迭代计算,他的含义是,右侧的v或者q是来自上次迭代,或者说来自对 \pi 这个策略下的评估的结果。我们做的只是,在原来的策略的评估的基础上,看看有没有新的更好的动作,这个动作就是 \pi'(s) ,用公式表达:

q_\pi (s,\pi^{'}(s))=\max_{a \in A} q_\pi (s,a)

  • 表达式中的 q_\pi(s,a) 则一定是 v_\pi(s) 其中的一项,此项为  q_\pi(s,\pi(s)) ,所以有:

\max_{a \in A} q_\pi (s,a) \ge q_\pi(s,\pi(s))=v_{\pi}(s)

  • 补充强调一下:  q_\pi(s,\pi(s))=v_{\pi}(s) 是恒成立的,代表着在当前policy评估的q函数中,我们在当前状态选择policy认为的最优的action,他便是当前policy对于当前s的value的评估,即 v_{\pi}(s)
  • 综上,我们能够得出结论:

q_{\pi}(s,\pi'(s))\ge v_{\pi}(s)

接着,说明 v_{\pi^{'}}(s) \ge v_{\pi}(s) ,对于所有的s恒成立:

  • 首先,已知 v_{\pi}(s) \le q_\pi (s,\pi^{'}(s))
  • 接着,我们展开 q_\pi (s,\pi^{'}(s)) , 得到的应该是在状态下执行policy \pi' 的期望,可以得到:

\begin{align} &\max_{a \in A} [R_{t+1} + \gamma v_{\pi}(S_{t+1})]\\ \le&\max_{a \in A} [R_{t+1} + \gamma q_{\pi}(s_{t+1},\pi'(s_{t+1}))]\\ \le&\max_{a \in A} [R_{t+1} + \gamma R_{t+2} +\gamma^2 R_{t+3}...]\\ \le& v_{\pi'}(s) \end{align}

  • 对于非确定性的policy,我们也可以得到:

\begin{align*} &E_{\pi^{'}}[R_{t+1}+\gamma v_{\pi}(S_{t+1})|S_t=s]\\ \le&E_{\pi^{'}}[R_{t+1}+\gamma q_\pi (S_{t+1},\pi^{'}(S_{t+1}))|S_t=s]\\ \le&E_{\pi^{'}}[R_{t+1}+\gamma R_{t+2}+\gamma^2 q_\pi (S_{t+2},\pi^{'}(S_{t+2}))|S_t=s]\\ \le&E_{\pi^{'}}[R_{t+1}+\gamma R_{t+2}+\gamma^2 R_{t+3}+ ... | S_t=s]\\ =&v_{\pi^{'}}(s) \end{align*}

综上 v_{\pi^{'}}(s) \ge v_{\pi}(s) 恒成立

v的收敛

当policy imporvement 停止的时候,我们知道,对于任意的 s \in S ,都有

q_\pi(s,\pi'(s)) = v_\pi(s)


成立。这意味着,对于任意的 s \in S ,有:

q_\pi(s,\pi'(s))=\max_a(R_s^a + \gamma \sum_{s' \in S} P_{ss'} v_\pi(s'))=q_\pi(s,\pi(s))=v(s)

此时也意味着bellman optimal Equation 被满足,即:

v_\pi(s)=\max_{a \in A} q_{\pi}(s,a)


注意:这里要强调的是,从上述过程我们可以看出,我们虽然使用贪婪的思想,但是这并不意味着我们只在意当前的这个步骤;我们利用bellman方程,通过我们上次的到的value,把全局的情况考虑进去了,并把结果存储,给下次的bellman的贪婪提供依据。

Example

下面这个例子,则是一个停车场的例子:

假设我们现在有两个停车场,这个停车场的车子有一定概率被租用,有一定概率被还回,每次租用就有收益。我们作为停车场的主人,希望通过两个车场的车子的租用,以达到最大的收益,这可以作为一个MDP过程,具体设置如下:

  • State: 两个位置的车子数,每个地方最多有20辆车 <a,b>
  • Action:车辆调度,一次最多调度5辆车
  • Reward:每次租车有10的收益
  • environment:两个车场每天到来的车服从泊松分布:
    • 1: request \lambda=3 ,return \lambda=3
    • 2: request \lambda=4 ,return \lambda=2

下面是迭代的结果:

其中,的横纵坐标分别是两个停车场的车的个数,而曲线是决策的分割线,比如中间的0,表示,在这个区间我们今晚调度0辆车。

V这是一个value function 所展示的曲线,他展示了第四次迭代后每一个状态的收益.

伪代码描述

NOTE: 这段伪代码摘抄自《Reinforcement Learning:An Introduction》,不过作者对Reward的定义与本文所讲的有所不一样,图中框红色的部分应该被挪到 V(s') 项前面。

修正迭代:Modified Policy Iteration

读者看一下我们前面的方格例子,可以发现对于我们的policy而言,虽然此时还没有满足Bellman Optimal Equation的条件,但是最优的policy已经出来了,或者说每一个state的action都已经被唯一确定,所以,在这之后我们做的一次次迭代实际上是无用功,Modified Policy Iteration希望解决的就是砍掉这些无用的迭代的过程,我们有以下解决方案:

  • 引入变量 \epsilon 作为停止条件,在精度允许范围内即可结束
  • 设定一个固定的迭代次数k,当超过k之后,即可停止迭代(当k=1时,等价于value iteration)

Value Iteration

优化原则

我们从另一个角度思考问题,动态规划的方法将优化问题分成两个部分:

  • 我第一步执行的是最优的action
  • 我之后后继结点每一步都按照最优的policy去做,那么我最后的结果就是最优的

Principle of Optimality Theorem

一个policy \pi(s|a) 在状态 s 出达到了最优解,也就是 v_{\pi}(s)=v_{*}(s) 成立,当且仅当:

对于任何能够直接到达 ss' ,都已经达到了最优解,也就是,对于所有的 s'v_{\pi}(s’)=v_{*}(s') 恒成立.

Deterministic Value Iteration

Value Iteration 使用的是Bellman Optimal Equation 来进行优化决策,他就像是在Policy Iteration中每次的迭代都直接更新Policy

复习Bellman Optimal Equation

在之前的介绍中,我们最终得到的state-to-state的方程为:

v_*(s)=\max_a(R^a_s+\gamma \sum_{s^{'} \in S}P^a_{ss^{'}}v_*(s^{'}))

流程

  • 随机初始化value function v_1
  • 同样,使用已经存在的 v_k 来得到新的 v_{k+1} ,这个过程,我们使用的是Bellman Optimal Equation,具体如下图所示:

v_{k+1}(s)=\max_a(R^a_s+\gamma \sum_{s^{'} \in S}P^a_{ss^{'}}v_k(s^{'}))

  • 可以看出,我们通过上一次迭代得到的value,来确定本轮迭代每一个state的optimal value function。
  • 我们在前面说的“每次都修改policy”,就蕴含在这里,实际上我们没有直接修改policy,但是我们通过对于的预估的公式表达的修改,已经展示出了:我们使用的policy就是对于所有的s,都使用上一轮中表现最突出的action(虽然过程是这样,但是迭代若还没有结束,这个policy实际上是没有意义的)
  • 不断的重复迭代这个过程,直到v收敛
  • 最后使用贪心算法求policy,就可以得到对应的policy便是最优的policy: \pi(s) = arg \max_{a\in A} [R_s^a + \sum_{s' \in S} P_{ss'}^a v^*(s)]

伪代码

NOTE: 这段伪代码摘抄自《Reinforcement Learning:An Introduction》,不过作者对Reward的定义与本文所讲的有所不一样,图中框红色的部分应该被挪到 V(s') 项前面。

特点

  • 我们只是在解决一个planning的问题,而不是强化学习的问题,因为我们知道环境如何变化
  • value function做的工作类似于value的反向传播,每次迭代做一步传播,所以中间过程的policy和value function 是没有意义的。不像是policy iteration,他每一次迭代的结果都是有意义的,都是一个完整的policy。我们用这个例子来说明:
  • 这里我们设定了一个终点,也就是灰色的点(实际上这个终点是在迭代过程中不必要的,只是为了更好的演示)。value iteration的迭代过程像是一个从某一个state(这里是我们的目标goal)反向传播其他各个状态的过程。因为每次迭代只能影响到与之直接相关的状态。
  • 让我们回忆一下前面所说的Principle of Optimality Theorem:当你这次迭代求解的某个状态s的value function v_{k+1}(s) 是最优解,他的前提必然是能够到达该状态的所有状态s'此时都已经得到了最优解;如果不是的话,他做的事情只是一个类似传递value function的过程。
  • 我们还是以图中为例说明,实际上,对于每一个状态,我们都可以看成一个终点。迭代由每一个终点开始,每次都根据bellman optimal equation重新计算value,如果他的相邻节点value发生变化,变得更好,那么她也会变得更好,一直到相邻节点都不变了。因此,在我们迭代到 v_7 之前,也就是还没将每个终点的最优的value传递给其他的所有状态之前,中间的几个value function只是一种暂存的不完整的数据,他不能代表每一个state的value function,所以生成的policy 是一个没有意义的policy

拓展

异步的动态规划:Asynchronous Dynamic Programming

在我们之前的算法中,我们每一次的迭代都会完全更新所有的,这样对于程序资源需求特别大。这样的做法叫做同步备份(synchronous backups)。异步备份的思想就是通过某种方式,使得每一次得带不需要更新所有的,因为事实上,很多的也不需要被更新。异步备份有以下几种方案

1. 就地动态规划:In-Place Dynamic Programming

In-place 动态规划所做的改进,是直接去掉了原来的副本 v_k ,只保留最新的副本(也就是说,在一次更新过程中,存在着有些用的是 v_{k} ,有些用的是 v_{k+1} )。具体而言,我们可以这样表示:对于所有的状态s:

v(s) \leftarrow \max_{a \in A} (R_s^a+\gamma \sum_{s' \in S} P^a_{ss'}v(s'))

2. 加权扫描动态规划:Prioritized Sweeping Dynamic Programming

Prioritized Sweeping 的思想是,根据某种方式,来确定每一个状态现在是否重要,对于重要的状态进行更多的更新,对于不重要的状态更新的次数就比较少。

  • 更新顺序:可以使用priority queue 来有效的确定更新次序(按照优先权排队,每次把优先权最高的拿出来更新)
  • 权重设计规则:可以使用Bellman error 来确定优先权,这个公式是通过两次的value的差异来作为state的评估标准,如果某个状态上次的value和这次的value相差不大,我们有理由认为他即将达到稳定,则更新他的价值就比较小,反之则比较大。具体公式如下:

|\max_{a \in A} (R_s^a+\gamma \sum_{s' \in S} P^a_{ss'}v(s') - v(s)|

所以说,这个方法需要我们进行反向规划,因为我们需要知道当前状态之前的value是多少

3. 实时动态规划:Real-Time Dynamic Programming

实时动态规划的思想是只有代理现在关注的状态会被更新。与当前无关的状态暂时不被更新。

就比如我们在时间步t进入状态 S_t ,进行动作 A_t ,结果是得到反馈 R_{t+1} ,那么我们要做的就是,仅仅更新 S_t 的value function,公式如下:

v(S_t) \leftarrow \max_{a \in A} (R_{S_t}^a+\gamma \sum_{s' \in S}P^a_{S_ts'}v(s'))

Full-Width Backups and Sample Backups

本节的内容将会在 整合学习与规划一节中具体表述

Full-Width 和 Sample Backups的区别在于更新状态时考虑的后继状态的个数的区别,他和同步DP,异步DP思考的是两个维度的优化方向。

  • Full-Width Backups 介绍的是:当我们在考虑更新某一个state 的value function的时候,我们需要遍历这个state的所有可能的action,和每一个action所可能达到的后继state,这个遍历的开销非常大,对于每一次迭代,如果有m个action和n个state,则时间复杂度为 O(mn^2) ,也就是说,遍历次数会随着n而指数增长,这在大型的DP问题中,代价是无法接受的,所以我们提出了sample backups。
  • sample backups 的思路是将state-to-state的过程进行采样,也就是说,我们以整个MDP <S,A,R,S'> 为单位,得到很多的样本,也就是说,对于一个样本,一个state对应一个action,通过采样多个MDP过程,来估计当前的策略的优劣,而不是每个节点直接遍历所有的可能性,我们可以用下图表示:

这样做有如下的优点:

  • Model-free:一个非常重要的好处就是,由于我们不再需要计算所有的action可到达的状态,就意味着我们不需要使用状态转换概率矩阵,也就是说,我们不再需要提前完全搞明白环境的变化模型,这便是一个model-free的算法!
  • 假设我们采样的个数为a,那么我们一次迭代的时间复杂度就是 O(amn) ,随着state的增加,我们的时间复杂度仅仅是常数增长。一定程度避免了维度灾难

Approximate Dynamic Programming

函数逼近的动态规划,是我们做优化的另外一个维度,他的思想是利用一个逼近器(比如一个神经网络算法),来代替目前精确的计算每一个s的具体的value是多少,我们会在之后的章节具体介绍

编辑于 2018-01-28

文章被以下专栏收录