数据酷客 | 强化学习科普第3期:动态规划
Posted 数据酷客
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据酷客 | 强化学习科普第3期:动态规划相关的知识,希望对你有一定的参考价值。
在介绍了MDP与强化学习的总体情况之后,我们便开始来考虑如何求解具体MDP的最佳策略方法。我们首先介绍最优控制的内容。在最优控制中,MDP的环境是已知的,这也就是说,在给定的s下采取给定的a,进入下一个s的概率分布我们是有已知的。
由于我们已经有了环境,所以我们求解MDP就不需要一个“学习”的过程。在最优控制中,主要由两类求解最佳策略的方法。第一类是动态规划与HJB方程的方法,第二类则是变分法与庞特里亚金原理。这两类方法主要应用动态规划与微分方程来求解最佳策略,并不具有“学习”的性质。不过,动态规划与HJB方程的思想很大程度上被移植到了强化学习中,所以我们会花两篇的时间着重介绍一下动态规划与HJB方程。
首先,我们先考虑最简单的MDP。最简单的MDP是什么样的呢?显而易见,最简单的MDP时间t是离散的,并且状态s与动作a都是有限的,另外还是time-invariant的。例如,一个游戏中一共有10种状态s,3种动作a,我们求解最佳策略,就相当于是找出一个s与a之间的映射。即对于每一个当前状态s,应该采取哪一种相对应的动作a。这可以表示成一个10×1的表格(用one-hot变量表示就是10×3的表格)。
井字过三关
让我们来考虑一种比较简单的棋类游戏,比如“井字过三关”,相信大家小时候都玩过这个游戏。棋盘只有3×3的大小。两个玩家一个画“○”,一个画“×”,只要在同一行或者同一列或者对角线上连上三个,即可获得胜利。
我们定义一个这样的MDP:将目前棋盘中的局势定义为s,将我们下一步的走法定义为a。假设我们是先走的那一方,画“○”。我们走之后轮到对方AI走。我们对手的AI设计得比较平庸——当AI看到我们已经在某一直线上连了两个“○”,且直线剩下的一个位置是空的(我们将这种情况称为“叫杀”),AI会选择在该直线的第三个位置画上“×”,以阻止我们取得胜利;如果AI发现我们暂时没有马上要取得胜利的局面,就会均匀地等概率随机挑选一个空的位置走。设我们取得胜利可以获得r=1,打成平局则r=0,如果不幸输给对手则r=-1。这是一个我们已知环境的MDP(即我们知道每一个s下采取每一个a,进入下一个s的概率分布),现在考虑求解最佳的策略,即最大概率击败AI的方法。
游戏的开局显然是同一个基础的s,即棋盘上一个棋子也没有的情况。我们要选择第一步的a。一般最自然的想法是“走中间”,因为其他位置只是处在两条或者是三条直线上,而中间的位置则是处在四条直线上,所以看起来中间的位置是一个“兵家必争之地”。
现在考虑第一步“走中间”。这时由于AI没有感觉到威胁,所以它会在剩下八个位置中随机挑选一个位置走,每一个s的概率是八分之一。如果我们认为旋转、对称可以得到的棋盘都是同一种,我们事实上可以认为只有两种不同的情况——即AI走到边上或是走到角上。每一种走法各有二分之一的概率,示意图如下所示:
我们发现,如果是落入了下面那种情况(即AI走了“边上”),事实上我们已经赢了。因为我们下一步选择走到角上“叫杀”,AI就只能招架我们的进攻。而再下一步的时候,我们就形成了绝杀。也就是说,我们必然可以获得r=1,如下图所示:
但是如果落入了上面的那一种情况,我们该怎么走呢?我们有7种不同的a可以选择。考虑旋转对称的等价性,则只有4种。这四种a中,有三种a走完对对AI构成“叫杀”。但是AI可以通过落子来化解我们的“叫杀”,并且可能会反过来对我们构成“叫杀”。这时候我们又只能应对它的叫杀,最后往往只能走出平局。如下所示:
对于剩下一种走法(即将“○”下在“×”的斜对角),对AI不构成“叫杀”。这种情况下AI会随机地走入剩下的六个格子中。依照旋转对称等价的原则,我们依旧可以认为只有三种情况,各三分之一的概率发生。这三种情况中,第一种情况对我们构成了“叫杀”。我们忙于应付,最后会打成一场平局;第二种情况中,AI没有对我们构成威胁,我们再走一步便成功绝杀;第三种情况下,AI则给我们气势汹汹地来了个“叫杀”,我们必须应付。可是没想到我们一应付,就反过来将AI给绝杀了,这AI真可谓“扛起石头砸自己的脚”。如下图所示:
上面这番分析意味着,如果AI走了角的话,我们选择下一步“叫杀”其实是没有好处的,因为这样无法获得胜利,肯定只有r=0;我们最佳的走法应该是走到它的对角,让它随机走一步。这样,我们仍旧有三分之二的概率可以获得胜利,拿到r=1。
总结地说,如果我们第一步走了中间,则我们面临两种情况:AI走“边上”以及AI走“角落”,两种情况各一半的概率。如果AI选择了“走边上”,则我们必然可以取得胜利,获得r=1;而如果AI选择走“角落”,则我们最佳的走法应该是走到它的对角,这样也有三分之二的概率取胜。在面对初始s,采取“先走中间”的a的情况下,我们取得的r的期望是 。
既然面对初始s“先走中间”获得的r期望有六分之五之高。那么它是不是最佳的策略呢?答案可能令人意外——这并不是最佳的策略。
考虑我们第一步走“角落”。由于没有对AI产生威胁,故而它会随机从剩下八个位置中选择一个落子。根据旋转对称等价的原则,事实上有5种情况(其中前两种情况没有与之对称的,故而只有12.5%,后面三种情况都有对称的情况,所以各算25%):
我们想说的是,第一种情况,即AI选择了“走中间”的策略后,我们不能保证取胜。而在其他四种情况下,只要我们走法正确,我们一定能够取得胜利。我们这里只给出第二种情况下必胜走法的解答,其他三种情况留给读者自行思考:
如果我们“走角落”之后,AI选择了“走中间”,我们是不是一定没办法获胜呢?也不是的,我们可以选择走到“对角”。这时候,类似于上面的分析,AI有三分之一的概率会选择走角落,这时候我们就能获胜。如下所示:
这也就是说,在面对初始s,采取“走角落”的a之后,有八分之七的概率AI没有选择“走中间”。而这些情况下,只要我们后面走法正确,我们是必胜的。如果AI选择了“走中间”,则我们如果走法正确,仍然有三分之一概率取胜。这意味着,第一步采取“走角落”的a,我们获得的r的期望是 。
经过对比,我们发现十二分之一比六分之五要大,所以我们最佳的策略下,面对初始的s选择的a应该是“走角落”!
上面涉及到的思想
在上面,我们解决了一个简单的MDP。现在,我们来看看它主要用到了哪些思想。
首先,我们会发现有一个概念在我们的求解过程中十分关键,那就是存在某些状态s,这个状态本身没有分出胜负。但是只要AI走到了这个状态,如果我们下一步走的正确的话就一定能够取得胜利。我们可以直接将这样的局面s与r=1划上等号,并且以这个为前提,再去分析怎样才能最大可能地进入这些“必胜局面”——比如第一步“走角落”的话会有八分之七的概率进入“必胜局面”,所以我们有理由相信第一步“走角落”是好的。
要注意的是,这种“必胜局面”的前提是“如果我的走法正确”。如果AI走到了我们想要的“必胜局面”,而我们却不知道应该怎么走,那么我们是不能保证自己能获得胜利的。同样道理,在我们上一节中讲到了一些“一定会打平”的局面,如果我们在这种局面下的走法不正确,甚至是有可能会输给AI的。所以,我们上面说的所有“必胜”或者“一定打平”都是建立在“我们的走法是正确”的基础上的。
对于“必胜局面”,我们知道“如果走法正确”,就一定能够获得r=1。而对于“必平局面”,我们知道“如果走法正确”,一定会以r=0收场(我们作为先走的一方,如果“走法正确”是绝对不可能输掉的)。我们可以想象,“必胜局面”对于我们的“价值”就是1,而“必平局面”对我们的“价值”就是0。对于二者之外的“中间局面”,例如最开始的局面,我们却不能马上看出会发生什么。这时候,我们可以看看我们的走法将以多大概率将其导向“必胜局面”与“必平局面”,来分析出这些“中间局面”的价值。
例如“先走角落”的策略,会以百分之七概率进入“必胜局面”,八分之一的局面进入另外一个“中间局面”;而对于“先走中间”的策略,则会以二分之一进入“必胜局面”,以二分之一进入另外一个“中间局面”。这些“中间局面”的“价值”是多少,需要我们用上面同样的手法作进一步的分析。
分析得出,在后续采用“最佳走法”的情况下,“走中间”的期望收益是0.833,而“走角落”的期望收益是0.916,所以“走角落”的收益更大。这时,我们可以判断出“第一步走角落”是最佳的策略。按照上面对于“价值”的定义,最初的局面(即场上一个棋子也没有的初始状态)的“价值”就是其采用“最佳策略”所带来价值,也就是“走角落”对应的0.916,而不是“走中间”对应的0.833。我们可以得出如下的“最佳策略”与“价值”的表格(每一种局势都有对应的“最佳策略”与“价值”,我们只列出一小部分):
上面说的这些正是动态规划的基本思想——将大的问题拆分称为比较小的问题,分别求解这些小问题,再用这些小问题的结果来解决大问题。能将小的问题与大的问题相连接在一起的,正是我们说的“价值”——我们这里对这个“价值”做出定义:它是关于st的价值函数V(st),代表“在最佳策略下”从t时刻的s出发之后,可以获得的总期望价值E(Σi=tγiri)。当MDP为时齐的时候,一般不需要t作为角标,就好像在下棋时候,你光看棋局判断哪方占优,而不必知道现在是第几回合。另外,要理解的是这里说的“价值”和MDP本身定义的奖励r是有区别的。你在s下能获得V(s)的前提是你走出了“最佳策略”,否则就不能得到这么多“价值”。
上面“井字过三关”只是一个特殊的例子,它比较简单。有一些局势s,我们一眼就能看出它是“必胜局面”,便可以直接把V(s)标记为1,并得到它的“最佳策略”。然后,我们又可以用这些标记了0或1的V(s)求别的V(s)。但是对于更复杂的MDP,例如中国象棋,我们就难以做到这一点。比如在某一个刚开局的s处,我们可以选择立即吃掉对方一个子,获得立即的r,也可以选择放弃吃子而去抢占一个位置,帮助我们在以后获得更多r。这个s才刚刚开局,远没有能分出胜负,我们压根看不出这一步的“最佳策略”到底是什么,也自然求不出V(s)是什么。这种情况又该怎么办呢?
说到底,矛盾的地方在于我们对价值函数V(s)的定义——它表示“在最佳策略下”获得的价值。但我们一开始并没有“最佳策略”(如果有了最佳策略,我们问题都解完了,何必要求V(s)呢?)。s是一个静态的局面,它本身是没有价值的。如果是一个不会下棋的人,再好的棋局s也能给下输。s的价值V(s)大小是一种“策略”赋予的,而“策略”如何制定,又需要参考V(s)的大小。我们一开始既没有V(s),也没有“最佳策略”,我们怎么能够“无中生有”地同时求出V(s)与“最佳策略”呢?
动态规划算法就是为了解决这样的矛盾设计的,我们下面来介绍其框架:
动态规划算法框架
我们考虑的仍然是a与s都有限的MDP。不妨设s有10种,a有3种。
首先我们定义“策略”,即policy,它一般用希腊字母π表示,其含义是s与a的对应关系,什么s应该采取什么a。由于s与a都是有限的,所以我们可以用一个10×1的表格记录policy,每一格记录一种s对应的a。
然后我们再定义一个“策略价值函数”Vπ(s)。这里的“价值函数”和上面说的有些不同,它指的不是s在“最佳策略”下的价值,而是在当前策略π下能获得的期望。这也就是说,我们从s出发,按照π来选择a,进入下一个s,然后又在下一个s用π来选择a,一直这样玩下去,最终总的期望奖励Σiγiri就是我们的Vπ(s)。显然,任何一个策略π都可以对应一个“策略价值函数”Vπ(s),而不同的π对应的Vπ(s)自然也是不一样的。
当我们建立了这个10×1的“策略表”与10×1的“策略价值表”之后,就可以开始进行的迭代以求解“最佳策略”了。下面的算法被称为“策略迭代”,是动态规划求解MDP中最经典的一种算法,其步骤如下:
1、首先,初始化“策略表”π。我们希望初始策略不要太差,不要和“最佳策略”偏离得太远,这样才便于迭代步骤之后能收敛到“最佳策略”,所以我们要争取生成一个不算太差的初始策略。例如,在“井字过三关”的游戏中,很多s下我们都够一眼看出有必胜策略a,所以可以将这些a填在s对应的位置。这个步骤帮助我们大大减少了动态规划的复杂度。但是对于复杂的MDP,我们可能只能随机产生初始策略。
2、初始化“策略价值函数”Vπ(s)。同理,我们应该努力让初始化的“策略价值函数”与真正“价值函数”(“最佳策略”下的“策略价值函数”)更加接近。例如在“井字过三关”中,我们把很多“必胜局面”的Vπ(s)直接就初始化为1了。但是如果没有特定的专业知识,我们只能将其全部初始化为0。
3、在策略π下求出“策略价值函数”Vπ(s)的值。按照定义,按照策略表π上给的规则,以及已知的环境,模拟出从s出发按照π操作会发生什么,以算出s的价值。由于这个步骤是在给定策略下求“价值”,故将其称作“策略评估”,即policy evaluation。
4、进行了“策略评估”后我们得到了Vπ(s)。但是,我们追求的是“最佳策略”,所以我们还要修改当前的策略。这个步骤被称为“策略提升”,即policy improvement。如果说上面“策略评估”是用策略表π来求出当前策略下的价值Vpi(s),那么“策略提升”则恰恰相反,是用当前的价值Vπ(s)来求最佳的策略π。其过程是很朴素的:对于每一个状态s,我们查看3个a(记为a1,a2,a3)带来的后果Σs′Pais,s′Vπ(s′)+rais,i=1,2,3选择其中最好的ai作为s对应的策略就行了。
动态规划的主要过程就是先进行1、2,即对“策略表”π与“价值函数”V进行初始化,然后迭代地重复3与4,即迭代地“策略分析”与“策略提升”,直到收敛,即“策略提升”步骤不对π产生任何改动,即停止算法。其伪代码如下所示:
策略迭代与值迭代
在上面的算法中,“策略评估”这个步骤是复杂的。在“井字过三关”的游戏中,由于整一局游戏的步数十分有限,所以我们事实上是先枚举从s出发的所有情况,然后将其加和,继而求出s的价值是多少。但是对于复杂一些的游戏(哪怕s与a都很少,可是游戏的回合数很长),想通过先枚举后求和的方法以计算V(s)是极其复杂的。我们得另谋良方。
按照“策略价值函数”的定义,我们有得到如下公式:
Vπ(s)=Σs′Pas,s′Vπ(s′)+ras
公式中,a是s处根据π选择出来的。上面我们曾提到过“中间状态的价值可以用别的中间状态计算出来”,这个公式所表达的正是这个意思。有了这个公式之后,我们就不必通过枚举、加和的方式来“策略评估”。由于Pas,s′与ras都是已知的,这就是一个10元的线性方程组。我们可以直接通过求解方程的方式来解决它。
对于10元的方程组,我们自然可以直接解出这个方程。直接求解一个线性方程组需要的计算量是O(n3)(例如采用高斯消去法)。对于复杂一些的MDP,s的数量n可能会有很大,这会导致计算量很大。如果有学习过数值线性代数这门课程,就会了解解线性方程组有两大类的方法,一类是直接解法,另一类是迭代解法(包括雅克比迭代与高斯赛德迭代)。我们考虑采用雅克比迭代法来解这个方程:
设方程为x=Ax+bx,首先要随机生成一个x0,然后对于i=1,2,…,n令xi+1=Axi+b,直到xi与xi+1之间的距离很小。其框图如下:
雅克比迭代法的收敛性与矩阵I−A的“严格对角优势”有关。而我们这里的A比较特殊,它的行之和为1(这是因为概率Pas,s′对s′求和显然为1),满足“严格对角优势”的定义,所以采取雅克比迭代解方程是能够收敛到方程的真解的,或者说,在迭代过程中xi一定是距离方程的解越来越近的。
不难看出,雅克比迭代法的每一个迭代步要耗费O(n2)的计算量。由于迭代具有距离真解越来越近的性质,所以我们可以选择只用雅克比迭代法迭代k≤n步,求解出一个距离真解不太远的解。这个过程只需要花费O(n2k)的计算量。这也就是说,我们在“策略评估”这一步花费了更少的计算量,求出了精确度更低的“策略价值函数”。
这种减少计算量的方法是否会给我们带来帮助?答案是肯定的。因为我们归根结底的目的不是求“价值”,而是“最佳策略”。在整个动态规划算法的框架中,“策略评估”求解出Vπi(s)其实只是为了“策略提升”来求解πi+1。当我们用Vπi(s)求出了πi+1之后,我们又要重新对πi+1进行“策略评估”,求出新的Vπi+1(s)。在“策略提升”中,我们要令πi+1(s)=argmaxaΣs′Pas,s′Vπi(s′)+ras。这个表达式中,如果Vπi(s)只有较小的误差,很大程度上是不会影响求argmaxa的。所以说,“策略评估”中,“价值”不必要算得太精确,它只要能够体现出大致哪个s比较好,让我们能够在“策略提升”中选对a就行了。
此外,雅克比迭代法每次要随机生成一个初始解x0,然后再通过慢慢地迭代让它接近真解。随机生成的初始解可能是距离真解很远,所以要迭代很多步才能靠近真解。但是在这里,我们可以不必每次都随机猜出初始解,我们可以利用上一步“策略评估”的V(s)作为这一次“策略评估”的初始解。由于在迭代进行到后面,“策略提升”中发生改动可能不大,所以以πi“策略评估”得到的V(s)可能距离以πi+1(s) “策略评估”的V(s)的距离本身就不远,迭代较少的步数也能取得不错的精度。
以下是的方法就是建立在这个思想上,这个方法被称作“策略迭代”(policy iteration)。它在上面讲的一般的“动态规划”框架上采用了雅克比迭代法来进行“策略评估”。由于上述的两点原因,它比一般的“动态算法”更加高效:
我们可以想象一种比较极端的“策略迭代”,那就是每一次“策略评估”的时候仅仅迭代一步。这样可能每一步求出的值函数都有一定误差,但是由于每一步计算量更小,所以可以迭代更多步。并且,由于每一步都在复用前一步的V(s),所以随着迭代它的误差会越来越小。总的来说,这也是一种性能不错的算法,我们将其称为“值迭代”(value iteration)。
要注意的是,在“值迭代”算法中,事实上是不用单独列出“策略表”的。因为迭代进行到每一步,s对应的a都是能够极大化Σs′Pas,s′V(s′)+ras的a,所以“策略表”其实已经隐藏在“价值表”中了,没必要再单列出来。“值迭代”的算法如下所示:我们可以想象在每一时刻,V(s)都有一个与之对应的“隐藏”的π。当V(s)计算完成,我们也可以自动输出这个π
在“策略迭代”与“值迭代”两种算法之间,还有一些折中的方案。我们可以想象,在算法刚开始(循环计数i还比较小)的时候,“策略评估”需要迭代比较多的步数才能获得误差较小的“价值函数”,而在算法进行了很多步之后,“策略评估”则只需要迭代较少的步数就能求出较精确的“价值函数”。所以我们也可以先将k设的比较大,然后再慢慢减小,直到减为1。这就相当于先进行“策略迭代”然后进行“值迭代”,综合了两种算法的特点。
算法的收敛性
前面我们介绍了好几种算法,包括最一般的“动态规划”的框架,以及“值迭代”与“策略迭代”两种算法。下面,我们考虑当算法收敛的时候究竟意味着什么。
在“动态规划”的算法中,各个量的定义是很清晰的。我们用当前的“策略”π求出当前的“策略价值函数”Vπ(s),而又用Vpi(s)提升当前的“策略”。“策略评估”与“策略提升”交替进行,并且它们的定义都很清晰;而在“策略迭代”或“值迭代”中,有些量的定义则不太清晰。因为我们不是用精确解法去“策略评估”的,所以任何一个时刻的V(s)都不是真的“价值”,而只是对当前“策略价值函数”的一个近似。另一方面,当前的策略又是在被不断修改的,所以V(s)的确给人一种“不清晰”、“不可靠”的感觉。
我们希望算法收敛时候达到什么效果呢?我们自然希望此时策略π正是“最佳策略”,而此时的“策略价值函数”Vπ(s)也正是“最佳策略”对应的价值,也就是这个状态“真正的价值”。我们很容易想到,无论是采用“动态规划”、“策略迭代”还是“值迭代”,如果当算法运行到某一个时刻,π恰好是“最佳策略”,而V(s)也恰好是“真正的价值”时,算法一定会收敛。因为此时无论是“策略迭代”还是“策略提升”,都不再能改变π与V(s)的取值。这也就是说,达到最优解是算法收敛的充分条件。
但是反之,如果算法收敛了,就一定是π收敛到“最佳策略”而Vπ(s)收敛到“最佳策略”下的“价值”吗?答案是否定的。我们可以想象一种情况,存在一些π,是“不错的策略”,但不是“最佳策略”,我们将其称作“次优策略”。当某个时刻π是一个“次优策略”,而Vpi(s)则是在这个“次优策略”下的各个s的价值。这时候,很可能在“策略提升”的步骤中我们没有办法改进:
例如在上面“井字过三关”的游戏中,我们说过第一步“走角落”之后有五种情况,其中四种情况都是“必胜局面”。我们给出了其中一种的“必胜走法”,让读者思考其余三种。如果有粗心的读者A没有发现这三种情况是“必胜局面”,认为它们都是“必平局面”,那么就会判断第一步“走角落”的价值只有
,比起“走中间要低不少。所以,A就会认为第一步的最佳策略是“走中间”,并且认为初始局面的价值是0.833。这样,A就会得出一个“次优策略”——第一步走中间,并且得出这个“次优策略”下所有s的“状态价值函数”。这个“次优策略”与“状态价值函数”之间自然是能够“自圆其说”的,也就是说“策略评估”与“策略提升”都无法改变π与V(s),算法已经收敛了。
这种情况下,A就沉迷于这个“次优策略”中,每一局第一步都“走中间”,获得83.3%的胜率。他深信最佳的策略就是“第一步走中间”,并且对83.3%的胜率沾沾自喜,从来就没有想到过还有更好的方法。这种情况,我们就称作“局部收敛”,即在没有求出“最佳策略”的情况下算法已经无法更新。
事实上,这里涉及到“价值”的方法,无论是现在讲的动态规划,还是后面要讲到的DQN,都难免会遇到“局部收敛”的情况。我们后面讲到DQN的时候,会讲一系列“off-policy”或是探索-利用(explore-exploit)取舍的trick。它们被设计出来的重要目的之一就是为了防止“局部收敛”的。在我们现在所讲的动态规划问题中,由于环境是已知的(即我们知道ras),所以我们可以将估计出现偏差的V(s)用ras给“扭转”过来(根据棋局规则的定义很容易判断出有些局面是“必胜局面”),所以是不容易“局部收敛”的;但是在没有模型的问题中,尤其是那些r特别稀疏的MDP中,“局部收敛”的风险是很大的。因为当我们对于V(s)的估计出现了整体的偏差时,相对很难遇到r去“扭转”我们判断的偏差。所以在DQN中,采用“探索”的trick是很重要的。这一点我们后面会慢慢讲。
总的来说,我们今天介绍了最简单的MDP——s与a均有限,且环境已知的MDP的解法,并且引出了“价值”、“策略”等的定义与含义。在下一节中,我们将考虑s与a是连续变量的情况,并进一步加深大家对于“价值”与“策略”的理解,并引出最优控制与强化学习中很重要的Bellman方程。
数据酷客专题区有更丰富、更全面、更完整的文章分享,欢迎阅览。
http://cookdata.cn/topic/
以上是关于数据酷客 | 强化学习科普第3期:动态规划的主要内容,如果未能解决你的问题,请参考以下文章