4. 免模型预测(Model-Free Prediction)

4. 免模型预测(Model-Free Prediction)

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

Introduction

  1. 免模型指的是,未知环境的情况下,也就是此时你不知道环境的内在响应机制,你不知道你的动作将会对环境产生什么样的影响和反馈。你只能直接得到结果。
  2. 预测,区别于control,本章只是计算一个已知的policy的每一个状态的价值(value function)应该是多少,Control在下一张,他解决的是policy优化的问题

Monte-Carlo Learning

Monte-Carlo Evaluation 的流程

目标

我们将整个强化学习的过程变成一个个的片段(episodes),每一个片段都是一个状态/决策/反馈的序列,这些片段都是在同一个策略 \pi 的指导下完成的,也就是说对于每一个片段: S_1,A_1,R_1,...,S_k\sim \pi

我们的目标是:根据得到的一个个的片段,去评估在当前侧露下,每一个状态的价值: v_{\pi}

步骤

  • 对于每一个片段,我们能够计算他的折扣奖励(discounted reward),作为return: G_t =R_{t+1} + \gamma R_{t+2} + ... + \gamma^{T-1}R_T

注意的是,这个 G_t 需要保留状态信息的。也就是说,你需要指导在t时刻,你现在处于哪一个状态;

  • 通过计算t时刻在某个状态s时的return的平均值(excepted return),把他当作t时刻该状态的价值评估: v_\pi=E_\pi[G_t|S_t=s]

回顾一下,在之前的动态规划中,我们由于知道整个环境的运作方式,所以将这个公式转化成了:

\begin{align*} v(s)&=E[G_t|S_t=s]\\ &=E[R_{t+1}+\gamma G_{t+1} | S_t=s]\\ &=E[R_{t+1}+\gamma v(S_{t+1})|S_t=s]\\ \end{align*}

但是在环境未知的情况下,我们只能通过蒙特卡洛采样的方式,通过求经验的return的均值,来将他近似为 v_\pi

具体两种计算value function 的期望的方式

两种方式的不同之处:

  • Fist-Visit Monte-Carlo Policy Evaluation: 在同一个片段中,第一次访问到状态s的时候进行操作
  • Every-Visit Monte-Carlo Policy:在同一个片段中,每次访问到状态s都进行操作

操作指的是:

  • 增加计数器: N(s) \rightarrow N(s) +1
  • 增加累积的return: S(s) \rightarrow +G_t
  • 当我们进行足够多的操作时,通过 V(s)=S(s)/N(s) 可以求出估计的平均值,根据大数定理,此时V(s) 趋近于 v_{\pi}

增量更新value function

  • 平均值可以被增量更新,证明如下:

假设有平均值 \mu_1,\mu_2,.. ,和序列 x_1,x_2,.. ,均值可以用下面的方法增量计算:

\begin{align} \mu_k&=\frac{1}{k}\sum_{j=1}^{k}x_j\\ &=\frac{1}{k}(x_k+\sum_{j=1}^{k-1}x_j)\\ &=\frac{1}{k}(x_k+(k-1)\mu_{k-1})\\ &=\mu_{k-1}+\frac{1}{k}(x_k-\mu_{k-1}) \end{align}


  • 增量更新 V(s) :

同样的道理,我们可以在每一轮episode S_1,A_1,R_2,...,S_T

对于每一个状态 S_t (在同一个episode中,t不一样,s可能一样的),我们都有对应本轮episode的return G_t ,注意,这里 G_t ,不是每一个策略执行后的立即奖励reward,而是从t到片段结束的return,所以有:

N(S_t)=N(S_t)+1 \\ V(S_t)=V(S_t)+\frac{1}{N(S_t)}(G_t-V(S_t))

非稳定(non-stationary)环境下,我们不需要做完全的平均,因为环境随时在改变,实际上,我们更希望遗忘历史,更重视现在,因此,这个公式有了改进方案: V(S_t) = V(S_t)+ \alpha(G_t-V(S_t))

  • 增量更新的权重选择

在理论上说,我们使用了 \alpha 来改变每一次更新的权重,所以就必须满足一个条件:这些权重的累加必须为1(如果累加不为1,我们最后得到的V可能越来越大,也可能越来越小),那么,为了满足权重累加为1,有如下的理论:

首先,我们定义第k次的更新时,对于action a 的权重 \alpha_k(a) 。举个例子,在我们前面的平均加权的时候, \alpha_k(a)=\frac{1}{k} 恒成立,那么,她需要满足以下两个条件(根据:stochastic approximation theory):

\sum_{t=1}^{\infty}\alpha_t(a)=\infty\\ \sum_{t=1}^{\infty}\alpha_t(a) ^2 < \infty

让我们来直观理解这两个条件:

  • 第一项:所有的权重累加起来是无穷大的,这就要求每一个step都要有一定的权重,不能在某一个step之后的权重都为0,这个条件用来克服initial conditions 和 random fluctuations 带来的影响。
  • 第二项:用于保证最后的的时间步的权重足够小,来保证他的收敛性。

NOTE: \alpha_k(a)=\frac{1}{k} 满足条件,但是,在我们的最近更新有限的权重更新方案中 \alpha_k(a)=\alpha ,他不满足第二个式子,当我们在不稳定环境(non-stationary)中,这样的做法是有效的,并且,在实践中他比使用完全平均的方法被证明有更高的效率


时序差分算法(Temporal-Difference Learning)

TD(0) 算法描述

时序差分法是在蒙特卡洛算法的基础上做了一点调整:他和蒙特卡洛算法最大的区别在于,他不需要直接求得整个片段(episode)的 G_t ,才进行V(S)的更新,而是使用带折扣的预测的方式的方式来根据当前状态估计整个 G_t 应该是多少也就是说,他能做到,每走一步,就能进行V的更新,而不是等到整个episode结束后才进行更新。具体而言: V(S_t)=V(S_t)+\alpha(R_{t+1}+\gamma V(S_{t+1})-V(S_t))

这个算法和之前的bellman 方程有点像,唯一不同的是,我们现在是得到了 V(S_{t+1}) 的数据之后,再来更新 V(S_{t}) ,那么如何得到呢?一个常见的做法是 V(S_{t+1}) 可以来自上一论value function估计的结果。

另外,强调几个TD中常用的item:

  • R_{t+1}+\gamma V(S_{t+1}) 称作TD算法的target
  • \delta_t=R_{t+1}+\gamma V(S_{t+1})-V(S_t) 被称作 TD的error

两者的区别的比较

性能比较:

我们可以从这张图看出两者的区别,左边是使用MC算法,我们执行完所有动作之后,得到一个 G_t ,也就是这里的 actual outcome,用这个数据来更新每一个点。

而TD算法,他是在走到下一个状态之后,用下一个状态的预估值加折扣,来更新自己

两者的优缺点比较

  • off line learning or online learning:
    • MC 是off line learning:必须按照episode来学习,只有走完了整个episode的序列(sequences),知道了正确的return才能进行value的更新。我们把这种更新不需要经过任何的预估的过程叫做: no Bootstrapping
    • TD 是 online learning:可以每步都更新。因此,即使整个序列不完整(还没走到终点),我们也可以开始更新。我们把这种更新需要经过任何的预估的过程叫做: Bootstrapping
  • no biased or not biased:
    • MC算法对于的V评估是没有偏差(biased)的,因为每次都是基于正确的 G_t ,来自当前episode 的每一个真实的reward 折扣相加,所以没有偏差
    • TD算法中,若 V(S_{t+1})=v_\pi(S_{t+1}) ,(即V函数就是准确的价值函数)那么评估也是没有偏差的,否则,评估是有偏差的,因为我们用当前的价值函数来“当作” 真正的价值函数,而实际上,当前的价值函数和实际的价值函数是有一点差距的
  • variance:
    • 由于每次MC算法用来更新的return ,涉及到多次的rewards的相加,所以得到的方差(variance)比较大(方差比较大的含义:对于同一个状态(s),采样得到的值的差距比较大),也就是 G_t 每次可能得到的值差别较大,这导致他的收敛速度更慢
    • TD算法只有一次的选择,剩下的reward都来自 V(S_{t+1}) 的预估,所以方差比较小
  • 总结:
    • 由于MC的高方差,无偏差的特性,有以下几个特点:
  1. 他有更好的收敛性质。他总能够很好的拟合函数(他能够更容易接近真实的价值函数);
  2. 对初始化数据不敏感(因为他的标注是真实的,所以最后总会调整到正确的轨道上);
  3. 收敛速度比较慢
  • 由于TD算法的有偏差,低方差的特性,他有以下几个特点:
  1. 他通常速度比较快(因为数据的方差比较小,而我们一般认为收敛的准则是:当数据的波动比较小,则认为他收敛了);
  2. 但是对初始化数据比较敏感(如果有一个不好的初始化值,那么他虽然可以很快收敛,但不是收敛到正确的解);

比较两者的收敛过程

我们通过分析MC和TD的迭代公式,可以看到这两者的区别,同样通过迭代取得收敛的效果,但是他们收敛的对象是不一样的:

  • 对于MC算法,我们收敛的是return的最小均方差,也就是: \min \sum_{k=1}^K \sum_{t=1}^{T_k}(G_t^k - V(s_t^k))^2
  • 所以实际上,他没有利用MDP的任何信息,把他当成一个随意的状态序列来处理。相反的,对于非Markov的环境下的迭代,他的效果更好
  • 对于TD算法,我们做的则是,让他和MDP模型最大程度的相似,就像我们看到他的公式的形式,实际上就是让他不断的逼近贝尔曼方程的模型。所以他利用了Markov的性质,这使得他的迭代更为的有效率。

补充:方差和偏差

  • 偏差:描述的是预测值(估计值)的期望与真实值之间的差距。偏差越大,越偏离真实数据,如下图第二行所示。
  • 方差:描述的是预测值的变化范围,离散程度,也就是离其期望值的距离。方差越大,数据的分布越分散,如下图右列所示。
图来自网络,侵删

TD( \lambda )

算法分析:

  • TD( \lambda ) 的算法是TD(0)和MC的折衷,他本身是一种类似MC的算法,我们在原来完全基于真实return的 G_t ,基础上,加上前瞻预测值V(S),来组成我们需要的 G_t^{(n)} ,再由 G_t^{(n)} 组成 G_t^\lambda ,首先, G_t^{(n)} 定义如下: G_t^{(n)}=R_{t+1}+\gamma R_{t+2}+...+\gamma^{n-1}R_{t+n} +\gamma^{n}R_{t+n+1}+\gamma^{n+1}V(S_{t+1+n})
  • 如果考虑n-step的预测,我们的temporal-difference learning 算法,就可以改写成: V(S_t)=V(S_t)+\alpha(G_t^{(n)}-V(S_t))
  • 我们接下来的问题是,这个n到底是什么时候最好呢?
其中,这是RMS error 的定义:The performance measure shown is the root mean-squared (RMS) error between the true values of states and the values found by the learning methods。

这张图是一个random walk 的实验,他有21个状态,我们可以看到,3-step和5-step的预测错误率是最低的,但是如果我们的状态发生改变,这个n就不一定等于3或者5,所以定死一个n,是不合理的,有没有办法动态的调整这个n的大小呢?

我们的解决思路就是取这n个步骤的组合起来,这样,就能组合每一个步骤的信息,提高算法的准确率了,我们使用正则化因子 \lambda 来进行加权,这就是TD( \lambda )算法:

G_t^{\lambda}=(1-\lambda)\sum_{n=1}^{\infty}\lambda^{n-1}G_t^{(n)}

  • 这个过程中,如果n接近无穷大的时候,根据等差数列的求极限公式,可以得到,整个权值之和是1,现在,我们以此来更新value:

V(S_t)=V(S_t)+\alpha(G_t^{\lambda}-V(S_t))

  • 但是实际上,一个episodes的长度是有限的,为了保证权重之和为1,我们将剩下的权重赋值给最后一个step得到的final return,如下图所示:
  • 假设一个片段一共有T个step,则在t时刻算起,agent所要经历的steps为:T-t个。
  • 当agent走到episodes结束时,最后一项 为G_t^{(T-t)}=R_t ,因为此时没有任何预估值(也就是没有 V(S_{T}) )。我们将这项拆开,将从 \lambda^{T-t-1}\lambda^{\infty} 过程中的权重累加,赋给 R_t 。同样利用等比数列求极限,可以将上式改写成:

G_t^{\lambda}=(1-\lambda)\sum_{n=1}^{T-t-1}\lambda^{n-1}G_t^{(n)} + \lambda^{T-t-1}R_t

该算法与MC和TD(0)的关系

  • \lambda=0 ,则变成了原来的TD算法,只看未来的一个步长的反馈
  • \lambda=1 ,则变成了MC算法,即只看事实

特点:

  • 考虑了未知的对未来的预测情况,用于计算 G_t^\lambda ,最终用于更新value
  • 就像是MC算法,他只能在一个episodes结束之后才能开始进行计算

Backward-View TD( \lambda )

资格迹 Eligibility Traces

Eligibility Traces 用来描述某一个状态对当前的reward的影响的深远程度,她需要考虑两方面的因素:

  • 频率启发Frequency heuristic :在这个片段中,出现次数最多的state,他对当前的reward的影响应该越大
  • 最近启发 Recency heuristic :与当前的的出现越近的state,我们认为他对当前的reward的影响应该越大。

基于这两者的考虑,我们提出了Eligibility Traces,我们先看他的公式表达:

\begin{align} E_t(s)&=\gamma \lambda E_{t-1}(s)+1(S_t=s) \end{align}

他的含义很直观,每次经过一个step,我们通过 \gamma \lambda 来进行折扣,减小这个状态的影响力;另外一方面,当step处在的状态就是s时,我们通过+1( S_t=s )来增加 该状态的影响力,我们可以用下面这张图,直观的表述这个过程:

更新过程

  • 我们对每一个状态,都维护一个Eligibility Traces
  • 每经过一个step,便更新Eligibility Traces
  • 利用 E_t(s) ,我们可以更新value:
  • \begin{align} &\delta_t = R_{t+1} +\gamma V(S_{t+1})-V(S_t)\\ &V(S_t) = V(S_t) + \alpha \delta_tE_t(S_t) \end{align}

\lambda 为0和1时的比较

  • \lambda=0 ,此时 E_t(s) = 1(S_t=s) ,也就是说: V(S_t)=V(S_t)+\alpha \delta_t 这便是前面的TD(0)算法
  • \lambda=1 ,在Online Update条件下讨论:我们假设在一个episode中,每一个state会在time-step = k的时候被访问到,在到当前的step t的过程中,会经过次衰减t-k,我们因此可以把E的公式简化为:

\begin{equation} E_t(S_k)= \begin{cases} 0 & k < t \\ \gamma ^{t-k} & k \ge t \\ \end{cases} \end{equation}

  • 因此,对于第个step的 V(S_t) 更新的公式,可以变成: V(S_k)=\alpha \delta_t \gamma ^{t-k}
  • 我们考虑对整个episode进行在线更新,则累计的结果是:

\begin{align} \sum_{t=1}^{T-1} \nabla V(S_k)=\sum_{t=1}^{T-1} \alpha \delta_tE_t(S_k)=\alpha (\sum_{t=1}^{k-1}\delta \times 0 +\sum_{t=k}^{T-1} \delta_t \gamma^{t-k}) = \alpha \sum_{t=k}^{T-1} \delta_t \gamma^{t-k} \end{align}

  • 我们把其中 \sum_{t=k}^{T-1} \delta_t \gamma^{t-k} 展开: \delta_t + \gamma \delta_t + \gamma ^2 \delta_t + ... + \gamma^{T-1-k}\delta_{T-1}
  • 带入 \delta_t = R_{t+1} + \gamma V(S_{t+1}) - V(S_t) 得到:

\begin{align} \sum_{t=k}^{T-1} \delta_t \gamma^{t-k}=R_{t+1} + &\gamma V(S_{t+1}) - V(S_t)\\ + \gamma R_{t+2}+ \gamma^2 V(S_{t+2})-&\gamma V(S_{t+1})\\ + \gamma^2 R_{t+2} + \gamma ^3 V(S_{t+3}) - \gamma^2 V(S_{t+2})\\ ... \end{align}

  • 可以看到,中间项会被消除,最后留下: R_{t+1} + \gamma R_{t+2} + \gamma^2 R_{t+3} + ... \gamma^{T-1}R_{T} - V(S_t) = G_t -V(S_t)
  • 可以看到,这个结果是和MC算法一样的,但是,我们之前做了一个假设,就是每一个state在一个episode只被访问一次,可以想想,在online update的条件下,如果state能够被访问多次,他的结果和every-visit MC算法是大致上相等的。

Offline Update 的条件下,MC算法和TD( \lambda )算法是完全等价:

  • 首先,要明确,offline update 和online update的变化项都是在片段进行过程中累积的,但区别主要在:前者要到片段结束后才能更新,后者可以直接进行更新。所以我们要证明两者等价,只要证明一个周期结束后两者的更新项相同即可
  • 推导分为几个部分,首先是Backward-ViewTD( \lambda ):
    • 我们将Eligibility traces 用求和符号表述 : \begin{align} E_t(s)&=\gamma \lambda E_{t-1}(s)+1(S_t=s)\\ &=\sum_{k=1}^{t}(\gamma\lambda)^{t-k}1(S_t=s) \end{align}
    • 这个公式怎么得到的呢,我们可以用下面这张图来解释一下:
    • 当某一个 状态出现了 S_t=s 的时候,我们应该如何计算他的Eligibility trace?根据迭代的公式,当某个状态在第k个step出现之后,他每经过一次step,就会以权重 \gamma \lambda 的速度进行衰减,一共衰减多少次呢?衰减到我们当前的时间步t,所以说,衰减次数是: (\gamma \lambda )^{t-k}
    • 因为backward-view算法是逐步更新的,所以一个片段下来,对于某一个状态s,我们的更新项为: \begin{align} \sum_{t=1}^{T}\alpha \delta_tE_t(s)&=\sum_{t=1}^{T}\alpha \delta_t \sum_{k=1}^{t}(\gamma\lambda)^{t-k}1(S_k=s)\\ &=\sum_{t=1}^{T}\alpha 1(S_t=s) \sum_{k=t}^{T}(\gamma\lambda)^{k-t} \delta_k \end{align}
    • PS:这里用了一个求和符号转换,我们将这些项逐个展开成一个二维矩阵的形式,可以发现,原本我们做的是先横向求和,再纵向求和;我们现在改成先纵向求和,再横向求和(横纵只是相对的,取决于我们怎么展开)
  • 接着是Forward-view的推导:
    • Forward-view算法的更新项就比较简单,就是:

\begin{align} (G_t^{\lambda}-V_t(s_t))= -V_t(s_t) &+ (1-\lambda)\lambda^0[r_{t+1}+\gamma V_t(s_{t+1})]\\ &+(1-\lambda)\lambda^1[r_{t+1}+\gamma r_{t+2}+\gamma^2 V_t(s_{t+2})]\\ &+ …… \end{align}

    • 就像我们之前说的,由等比数列求和公式,我们将 r_{t+1} 抽出来,就能得到一个完整的等比数列求和,结果为 r_{t+1} ,
    • 后面每一层的 \lambda , 部分级次的数据不够,比如 r_{t+2} ,他是从 \lambda^1 开始的,所以要扣除相应个数的系数,结果如下:

\begin{align} (G_t^{\lambda}-V_t(s_t))= -V_t(s_t) &+(\gamma \lambda)^0[r_{t+1}+\gamma(1-\lambda) V_t(s_{t+1})]\\ &+(\gamma \lambda)^1[r_{t+2}+\gamma(1-\lambda) V_t(s_{t+2})]\\ &+ ……\\ \end{align}

    • 进行形式变换:

\begin{align} (G_t^{\lambda}-V_t(s_t))&=(\gamma \lambda)^0[r_{t+1}+\gamma V_t(s_{t+1}) -V_t(s_{t})]\\ &+(\gamma \lambda)^1[r_{t+2}+\gamma V_t(s_{t+2}) -V_t(s_{t+1})]\\ &+ ……\\ \end{align}

  • 使用求和公式,就可以累计上式得到: \sum_{k=t}^{T}(\gamma \lambda)^{k-t} \delta_k
  • 同样的,一个片段,我们会有多个step,每一个step都可能走到该状态,当走到该状态的时候,我们要进行上述更新,所以,在整个step结束之后,我们的累计更新值为:

\sum_{t=1}^{T} 1(S_t=s) \alpha (G_t^{\lambda}-V_t(s_t))=\sum_{t=1}^T 1(S_t=s) \alpha \sum_{k=t}^{T}(\gamma \lambda)^{k-t} \delta_k

  • 可以看到,两者相等。

backward-view 的伪代码:

几种 view在 offline 和 online 条件下的比较:

编辑于 2019-01-12

文章被以下专栏收录