白话强化学习与PyTorch
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第2章 强化学习的脉络

虽说本书讲的是以PyTorch作为落地工具的深度强化学习的应用,但是,要想比较清晰地了解这个强化学习和深度学习相结合的交叉学科领域,还是要分别把这两个部分弄清楚。请各位读者暂时忘掉深度学习和PyTorch,让我们一起仔细了解一下强化学习考虑问题的方式。

从本章开始,我们就要正式接触强化学习所涉及的各种模型、复合概念与算法了。与其说第1章介绍了强化学习建模时研究的对象,不如说是不得不做的对客观世界的观察手段的片段性陈述。现在,就让我们看看接下来要怎么研究、会碰到什么问题吧。

2.1 什么是策略

在第1章中,除了Agent、Environment、Observation、State、Action、Reward这些词,我还提到了一个词——策略(Policy)。我们应该如何理解机器人行为范畴内的策略呢?一般用这样一个表达式来描述:

a=π(s).

这里的a指的是动作,s指的是状态,函数π(跟圆周率没有半点关系)就是用来描述策略的。从形式上看,策略就像一个函数,只要输入一个状态s,就输出一个动作a

如果你在其他资料中看到

a=π(s|θ),

也不用紧张,这个θ仅仅为了说明在策略函数π中有参数θ。当然,这个θ取什么值合适,在强化学习中是通过训练得到的。θ的表达式通常不会太简单,不是用一两个实数就能描述清楚的。在强化学习中,可以用两种方式去理解这个函数:可以感性地理解为一些矩阵,在状态s以向量或者矩阵的形式输入后,与s进行各种矩阵计算;也可以更感性地理解为一些由if…else…及for循环组成的复杂的语句,用来对输入的s进行判断与处理。你觉得怎么理解更容易,就先怎么理解。

还有一种描述方式,经常写作

π(a|s)=P[At=a|St=s].

看上去和前面的策略写法有点像,但是略微复杂一些。这个公式表示的是输入状态s后,策略输出的a不是一个确定的值,而是一个概率分布的描述。而概率的描述,就在后面这个部分,就是P[At=a|St=s]。也就是说,当输入一个状态St=s的时候,应该输出的动作At=a的概率为多少。当然,就算我们不细究0和1的开闭区间的细节,这个概率也一定是一个0和1之间的数字。如果你觉得这个形式看上去不直观,让我们换一个方式来表述,如表2-1所示。

表2-1 π(a|s)=P[At=a|St=s]的含义

表2-1相当于将π(a|s)=P[At=a|St=s] 展开,A1AN表示整个动作空间所有可能的动作取值。中不同的动作的个数,S1SN表示所有可能的状态值。注意,这里的1、2、3……N不是时间片的次序,只用于描述状态的不同取值。现在,我们通过查表就可以得到策略的完整描述了。假如某一时刻机器人得到了S5状态的输入,那么它应该输出一个动作,这个动作a应该有10%的概率输出A1、有2%的概率输出A2、有9%的概率输出A3……有2%的概率输出AN。大致就是这样。

我估计,可能已经有读者有疑问了。

· 问题一:策略的描述我知道了,但是策略是怎么得到的呢?或者说,怎么评价一个策略好或者不好呢?

· 问题二:既然输入状态是确定的,那么在同一个状态下,不是应该只有一个动作是最优或者最好的吗?能不能把这个最优或者最好的动作求出来,直接做这个动作,而不用每次都通过“丢一个不均匀的骰子”来决定做哪个动作呢?

这些问题都非常好。

2.2 什么样的策略是好的策略

其实,研究机器人和研究人是类似的,研究机器人的行为和研究人的行为也是类似的。在人类的世界中,评价一个事物好或者不好,通常都是基于评价者自身价值观的。不同的人对相同事物的同一属性,也会有不同的看法或者截然相反的评价。

举个非常简单的例子,如表2-2所示,对一顿便餐,“在家做饭”还是“外出吃饭”,不同的人会有完全不同的看法,进而导向两种完全不同的原则(或者说策略)。当然,不管怎么说,这两种方案各有利弊。

表2-2 对“在家做饭”和“外出吃饭”的比较

我们可以尝试列出表格,在简单比较后进行判断。要知道,即便是住在同一个小区的人,做饭水平一样或者选择的是同一家餐厅(看似一切预设状态都极为相似),得出的结论也可能是不同的。例如,一个人打算吃点东西就去上班,另一个人在家闲来无事想尝尝新菜式,他们就会有不同的动作输出——一个在家做饭,另一个外出吃饭。

其实,还有很多没有列出的因素。例如,餐厅的环境、餐具的选择、服务员的态度等。这些因素不仅会影响就餐气氛,也会影响当事人对做饭成本(时间成本和材料成本)的判断。再如,有没有人一起就餐?对一起就餐的人,是吃路边摊就可以,还是需要准备一顿丰盛的家宴?这些都是不同的因素。

人类研究的策略其实是非常复杂的,不是一本书就能说明白的。不过,别慌,在机器学习的范畴里,如果想解决一个问题,通常要简单得多。不是因为机器学习本身的理论很“牛”,恰恰相反,是因为它太“弱”了——不能像人一样进行复杂的逻辑推理与判断,进行“理性+感性”的复杂分析,只能比较一个“数”的大小。什么“数”?就是我们常说的评价函数(Evaluation Function)。

评价函数的概念是什么?其实就相当于我们在上学的时候每门考试的成绩。如何评价一个人学习成绩的好坏?就看他的考试成绩如何。在同一个班里的两个同学,“明明”数学考了59分,“偏偏”数学考了100分——“偏偏”最后考上了大学,成了一名程序员。对于学生,评价函数可以作为遴选标准——谁的评价函数的值大,就选择谁。至于策略,评价函数就是“考试”,而且没有其他更好的方法。

不同的策略参加“考试”,谁的得分高,就认为谁是好策略。公平吧?得分面前人人平等。这个“考试”就是Environment(也可以说是考题)。让不同的策略在Environment里面摸爬滚打,最后计算一下谁的得分高——这个思路很自然,也很顺畅。

当然,有人会问:一次考试就能说明问题吗?一次考试的得分就能客观、公正地评价一个考生的能力或实力吗?这里有没有随机的成分,有没有不公平的现象存在?这些问题也是有道理的。所以,在给持有不同策略的机器人考生出题时,我们也希望它们能有长期稳定的发挥。例如,通过多次使用策略取平均值,用统计学的方法,消除单次考试中由于题目过于简单或者过于困难而产生的对策略的评价不准确的问题。

这个话题和代码本身没有什么关系,这是一个原则,或者说一种思维方式,希望能跟大家达成共识。

至于“在同一个状态下,不是应该只有一个动作是最优或者最好的吗”这个问题,我们暂且按下不表,后面自会解答。

2.3 什么是模型

模型(Model)这个词,在不同的研究领域有着不同的释义。在强化学习领域,模型是用于预测环境中将发生什么的一套描述信息。该怎么理解呢?

对一个机器人所处的环境来说,如果这个环境是自然形成的,而不是由某个人创造的,那么,这个环境将以什么样的规律变化,通常是没办法直接表示出来的。如果要描述一个模型,可以使用如下表达式:

P是概率;竖线后面的部分是St=sAt=a,表示当某个时间片t的状态为s时,做了一个动作a;竖线前面的部分是St+1=s′,表示下一个时间片的状态为s′。用于表示概率的P,实际上是一个矩阵。

的含义,如表2-3所示。

表2-3的含义

表格外层的横坐标是状态St,纵坐标是At。表格里层左列表示的是在其时间后方的St+1状态的取值,右列表示各状态取值的概率。也就是说,在外层表格中,可以通过查表得到在St状态下做一个动作At后转移到各个状态的概率。每个里层表格的形式都是这样的。想想看,在一个复杂的环境中,这个表格的“体积”应该是巨大的。

除此之外,有一个R的表达式,如表2-4所示。

表2-4的含义

比较这两个表达式。方括号内竖线后面的部分一模一样,就不多解释了,在表格中直接对应于横坐标和纵坐标。前面的Rt+1,指的是获得的奖励值,可以通过查表得到在St状态下做一个动作At会得到的奖励值。如果你在一些资料中看到这个地方写的是Rt,也不用觉得奇怪,因为毕竟这是在t时间片内,在St状态下做了一个动作At所得到的奖励值——用Rt来表示也不能算错。所以,我们只要知道这个表达式的含义是什么就可以了,至于下标具体写哪个,我个人觉得不重要。

一旦我们掌握了这两个表达式和表格中的信息,就相当于掌握了机器人视角下的客观世界的“推背图”《推背图》是唐太宗李世民为推算大唐国运,下令两位著名道士李淳风和袁天罡所著的一本书。这本书融合了易学、天文、诗词、谜语、图画。。这样,在环境中机器人怎么做才是最好的,研究起来就比较容易了。

想想看,这样一个模型,我们要怎么做才能得到?

一种情况是,如果这个环境是由我们自己创造的,那么我们至少能看到它的源代码。这样,所有的转移概率就可以很容易地得到了,甚至可以由我们自由设定。

另一种情况是,如果这个环境是由别人创造的,我们在看不到任何源代码的情况下,其实没有什么好办法,只能一次次试探,在试探中通过统计来得到转移概率。根据大数定律概率论中讨论随机变量序列的算术平均值向随机变量各数学期望的算术平均值收敛的定律。在随机事件的大量重复出现中,往往呈现几乎必然的规律,这个规律就是大数定律。通俗地说,在实验不变时,多次重复进行实验,随机事件的出现频率将趋近于它的概率——偶然中包含着某种必然。,只要试探的次数足够多,这个转移概率矩阵就会“稳定”下来,转移概率的值会趋近于某个数字。只不过,在这种情况下,需要的试探次数非常多,说“数以万计”一点都不夸张,尤其对那些仅状态数就上万的环境来说,试探次数简直是一个天文数字,恐怕机器人在其“一生”中都要不断地做这种试探了。

不过,话说回来,这也像人类自己一样。人类的认知范围是非常有限的——即便无数次尝试扩展观测范围,大到太阳系、银河系,小到细胞、分子、原子,人类也仍然不敢说自己穷尽了观测的范围。既然如此,在任何一个场景中,我们敢说自己观测到了所有的状态、将转移概率的统计收敛做到位了吗?我们很可能连状态的设置都做得不够充分,又怎么能得到一个理想的、完美的模型呢?

但是,我仍然觉得不必悲观。机器人的进化过程和人类的进化过程是一样的,都是在进化中不断调整和进步的——从不准确到准确,从不精确到精确。在强化学习的范畴中,你也会看到这样一个过程:只要每次的调整能够被验证为有进步,尤其是与之前的建模方式相比有进步,那么,它就可以被采纳并保留下来。虽然这种进化不是由机器人自己触发的,而是纯人工的进化,但它也是一种重要的进化。

2.4 如何得到一个好的策略

在本章前面的三节中,我们讨论了策略的含义。那么,如何判定一个策略是好的策略?什么是模型?在这一节中,我们就来给强化学习定一个基调,讨论一下得到一个好策略的原则。

当然,从“好的策略”的定义来看,比较不同的策略,就是在同样的环境中比较它们的得分,更准确地说,是比较它们得分的数学期望值(算数平均值)。哪个策略能在环境中长期稳定地得到高分(得到更多的奖励值),就是好的策略;反之,就是不好的策略。这里所说的得分,意味着以一定的前提条件来“打分”,也就是说,有既定的评分原则。

既然如此,思路就比较清晰了,通常有直接法和间接法两种思路来求解一个好的策略。

2.4.1 直接法

直接法的思路并不难理解。在策略函数a=π(s|θ) 中,在输入状态s确定的情况下,输出的动作a其实只和后面的参数θ有关。这个θ就是我们在训练智能机器人的时候想要得到的最终的模型参数。

而在环境中,得分(奖励值)是什么呢?

r=R(a|s).

虽然我们可能说不清这个函数中的其他系数是什么,不过在一个确定的环境中,通常在一个确定的状态s下输入一个确定的动作a,就会有得分产生。这两个函数能够结合吗?其实是可以的。

如果进行代换,可以写成这样的形式:

r=R(π(s|θ)|s).

在策略π确定的情况下,只要取一个参数θ的值,然后输入一个状态s,就会得到一个得分大小的描述。

一个策略究竟能得多少分?似乎可以通过这样的形式来计算:

也就是把各种状态下的得分加起来,然后除以状态的数量。是这样吗?不是。虽然思路的方向没有问题,但其中的细节很重要——别忘了,状态有N个,可这不代表它们出现的概率是均等的。

我们用一个最简单的例子作为反例。我们训练一个机器人,让它判断出门时要不要打伞,如表2-5所示。我们的目的是,让机器人学会雨天出门就要打伞、晴天出门不用打伞。

横坐标是状态(天气),纵坐标是动作,得分信息就是0分或者1分。假如目前机器人采用的策略是:晴天状态,有20% 的概率打伞,有80% 的概率不打伞;雨天状态,有90% 的概率打伞,有10% 的概率不打伞。这个策略好不好呢?我们分别计算一下。

· 晴天状态得分:0×20%+1×80%=0.8。

· 雨天状态得分:1×90%+0×10%=0.9。

最终,整个策略的评分是多少呢?是0.85吗?还真不一定。如果是0.85,就相当于把晴天和雨天的概率都设置成50%,即0.8×50%+0.9×50%=0.85。在这个题设的环境中,没有提到一定会这样。在两种极端情况下,即晴天的概率为100% 或者雨天的概率为100%,策略的评分分别是0.8和0.9。

这个例子只是为了说明上面那种写法是不对的。什么样的写法才是对的?当然是求数学期望值(即加权平均值)了。可以写成

或者写成更直观的

对每个状态值si,用它们各自的概率P(si),乘以策略输出的动作a的概率P(a|si),再乘以在R(a|si)状态下做这个动作的评分值,最后计算它们的算术平均值,就能得到对一个策略的相对客观、公正的评分了。

然后呢?既然评分函数有了,就要想办法通过让θ取某个值,让整个函数取得最大值。哪怕用最“土”的方法,通过100个或者1000个不同的θ取值,得到100个或者1000个对应的策略,也必然会得到100个或者1000个对应的得分的数学期望值——大不了挨个儿比大小,选一个得分最高的出来。

从程序员的角度看,这个方法似乎是可行的,但仔细想想,这个方法的思路不够严谨。即使将θ设定为某个矩阵中的值或者一系列if…else… 语句,也不能保证覆盖所有的策略所能取的值。既然不能保证覆盖,就不能保证这种通过比大小的方法得到的结果是最优解(这和1.2节中那个导航的例子完全不一样)。所以,在这种情况下,我们通常会借助一些高科技的手段,通过最优化(Optimization)方法求出θ取值的矩阵,或者得出构造什么样子的if...else… 语句才能保证输出最大的奖励值的数学期望值。结论暂时放在这里,求解的细节后面我们会仔细讨论。总之,直接法通过优化策略函数a=π(s|θ) 的待定系数的方法来获得好的回报值的数学期望值,这个大方向不能错。

2.4.2 间接法

策略通常用待定系数来描述。如果不方便用待定系数来直接描述一个策略,有没有其他的办法呢?也是有的,就是本节要介绍的间接法。

在某种程度上,间接法似乎比直接法更容易理解——a=π(s|θ) 本身就是一种策略,这种策略实际上在做什么呢?

应该说,在做如图2-1所示的动作搜索与转移。也就是说,当机器人所处的状态为某个状态的时候,选择输出一个动作a,然后迁移到下一个状态s。那么问题来了:哪个动作a更好?有一个非常自然的思路:哪个状态更好,哪个动作a就更好。在刚刚叙述的条件下,我们可以把θ描述成很多if…else… 语句的组合,判断的目标就是比较哪个状态s更好,从而选择其对应的动作a。这个思路就是一个广度优先遍历树的思路,只要能够把这棵树建立起来,就可以在每一层寻找那个得分最高的分支,然后做相应的动作。可是,开启“上帝视角”的情况比较特殊,在大部分场景中是没有办法做到的,因此,对陌生的场景来说,只有当前状态st、动作a、下一个状态st+1、获得的奖励值r这些可以瞬时观察到的值。能不能将瞬时奖励值r(也就是三个分支分别对应的r1r2r3)作为比较对象,哪个动作a所对应的奖励值r大,就选择哪个动作呢?

好像还是有一点问题:这个瞬时奖励值的大小,其实不能真实地反映这个动作及其所对应转移到的状态的价值。因为在这个状态的后面,可能隐藏着时间更为久远、尺度更为巨大的奖励或惩罚,而这些是无法通过当时的奖励值看出来的。

说到这里,我想起了一个小故事。相传在南宋时期(1140年),金国曾在金皇室完颜宗弼完颜宗弼(? —1148年11月19日),本名斡啜,又作兀术,女真族,完颜阿骨打第四子,金朝名将、开国功臣。有胆略,善射。(在评书里俗称“金兀术”)的带领下南下攻宋。名将刘锜刘锜(1098年—1162年2月),德顺军(今甘肃静宁)人,南宋抗金名将。镇守顺昌城顺昌城,今天安徽阜阳一代。,除了进行必要的战前动员、准备好相应的物资,他还精心设计了一系列方法来对付完颜宗弼的最强“武器”——铁浮屠和拐子马。铁浮屠和拐子马是两种重甲骑兵,对于兵种多为步兵的宋军来说,是非常难对付的。针对铁浮屠,刘锜用长枪和大斧手来对付骑手。针对拐子马,刘锜使用的方法更是令人叫绝。他命令士兵身背竹筒,冲到阵前,就在金军纳闷宋军为什么使用这种非制式装备的时候,士兵们直接打开了竹筒……煮熟的豆子从竹筒中倾倒出来,撒了一地。金军的战马酣斗多时,饥饿难忍,一看满地香喷喷的豆子,都立刻低下头吃了起来。这下子,金军的进攻节奏被破坏了,阵型也乱了。宋军趁势进攻,下砍马足,上斩敌首。金军人仰马翻,互相踩踏,折兵五千余人,战马也有大量死亡和伤残。

我觉得,通过这个故事,人和动物在智力上的差距还是高下立见的。对宋军来说,这完全不能叫“埋伏”,而是明摆着“坑人”来了——更“坑马”。然而,马就是这么天真、善良。为什么?嗯,因为它们没看过这本书,没学过强化学习。在这里讲这个故事只是为了让大家放松一下,顺便对这种瞬时奖励值的严重后果有一个认识——当前的美餐一顿,可能导致下一刻掉进万劫不复的深渊。

因此,我们通常会借助另一个函数——值函数(Value Function)来描述并期望尽可能精确地描述这个状态的价值。值函数的表达式可以这样写:

vπ(s)=Eπ[Rt+1+γRt+22Rt+3+...|St=s].

v就是价值(Value)的意思。这个表达式的含义也比较清楚:vπ(s)表示,在策略π确定的情况下,状态s的值为多少(价值为多少的概率;价值越高,状态就越好);在等号的右边是计算方法,Eπ[Rt+1+γRt+22Rt+3+...|St=s]指的是将下个时间片的奖励值、下下个时间片的奖励值、下下下个时间片的奖励值……相加,然后得出一个用于评估这个状态的价值的数学期望值。这个价值本身也与策略有关。例如,马看见豆子就会直接低头去吃,因此,可以想象,Rt+1的值是1,从Rt+2开始的值都是 -100(这是一个将直接导致死亡或者终身残疾的策略)。如果马无视豆子,拼死战斗,那么Rt+1Rt+2Rt+3等值就可能变成10、20、-3等,这会导向另一个结果,进而改变对当前状态的估值判断。

我们还是通过一个例子来具象地了解这个方法的思路。高考对中国人来说有多重要呢?高考结束后,是上大学、打工,还是“啃老”?这样的话题在社会上热议多年。然而,如何评价参加高考和上大学,如何评价参加高考和上大学的价值?还是应该通过客观、公正、科学的方法得出结论。也就是说,既不要以自己的好恶来武断地评价,也不要仅根据一些个案来评价,而要进行大范围的统计,并在此基础上进行评价。在这里,为了评价方便,我们只用年收入这一个指标作为评分标准,如图2-2所示。

表2-5 机器人打伞得分表

例如,一位普通的高中生,在高考前夕心里有了一些波动,犹豫高考之后是上大学好、打工好,还是回家“啃老”好。显而易见,打工是很快就能赚到一些钱的,哪怕是做一名普通的工人,也能有一些收入。假设一名普通工人的年收入为1.5万元,上大学和“啃老”在当时看来都是没有直接收入的,甚至上大学还要交学费(为了计算和讨论方便,没有把打工时产生的生活成本算在里面,只使用收入作为评分标准),而“啃老”尽管没有收入,但貌似也没有成本。在上大学和“啃老”这两项上面,我们打了问号。其实,可以把这两项的收入写成“0”(在实践中,为了计算方便,我们经常会这么做)。

几年之后,也就是我们处在下一个观测状态的时候,情况就可能会有很大的变化(生活中的情况要比图2-2中表现的复杂得多)。有的人找到了好工作,年薪15万元;有的人出国留学去了,仍然在花钱,且不挣钱;还有的人觉得打工不过瘾,自己当了小老板,也有7万元的年收入……林林总总,不一而足。

现在再看上大学、打工、“啃老”这三种抉择,哪一种更有价值呢?其实,就是通过人们作出相关决策之后整体(请注意,这个词也可以用“平均”来代替)有多少收入来判断的。在图2-2中,可以将直线箭头理解为决策动作(决定做什么),将方框理解为状态描述。在第五年的时候,上大学的价值评价可就不是“0收入”了,我们能够看到,后面状态的价值还是比较高的,这就解释了为什么会有一个Rt+1+γRt+22Rt+3+⋯的过程。在表达式里,我们习惯把系数γ(希腊字母Gamma)称作折扣系数或者折扣因子(Discount Factor),它一般是一个0和1之间的数字。显然,如果取0,就是完全忽略在这之后状态的价值,而孤立地评估当前直接得到的回报;如果取1,就表示不论期限有多长,都将回报记在这次“英明决策”的头上。γ的取值也是连续变化的,表示对长期回报的重视程度:越重视长期回报,γ的值就越靠近1(例如0.999、0.99等);越不重视长期回报,γ的值就越靠近0(例如0.001等)。这种思路也是非常自然的。

因为在机器人的“一生”中有太多的不确定因素(人又何尝不是),所以,对一个状态的评价,通常不能以一种“万寿无疆”的视野来评估,而应该采用一种重视“落袋为安”的相对短视的思维方式来评估(如图2-3所示)。

图2-1 动作搜索与转移

R(上大学)=R(留学深造)+γR(在大企业就职)+γ2R(找到好对象)+γ3R(生了个聪明的孩子)+⋯.

就拿“上大学—留学深造”这条路线来说吧,可以像我在前面写的那样来评价。要知道,距离当前时间越久远的事件,对当前状态价值的影响越小。因为“上大学”对“留学深造”确实有影响,所以,把“留学深造”的价值的大部分叠加在“上大学”上是比较合理的,而“在大企业就职”“找到好对象”甚至“生了个聪明的孩子”,与“上大学”所产生的影响的关系一个比一个小,因此,估值就要打折扣了。对这个表达式,我们这样理解就可以了。

对于一个确定的策略π所产生的一系列状态s的访问轨迹及分别获取的奖励值R来说,对这个策略下的这个状态进行较为客观的价值评估的方法就是——多次测量取平均值。

如果你不知道要把策略π描述成什么样子,可以试着这么想:所谓策略,就是一个确定的原则。那么,“确定的原则”应该怎么描述呢?还是以“上大学”之后的内容为例:

如果大学毕业,就扔硬币
如果正面朝上,就出国留学
    如果能拿到学位
      扔硬币。如果正面朝上,就回国找工作
          如果能进入大公司
              就去大公司
          如果不能
              就去中型公司
          如果还不能
              就去读博士
      扔硬币。如果背面朝上,就在国外找工作
          ……
如果背面朝上,就在国内找工作
    ……

尽管用这种方式来描述这个策略显得有点“无厘头”,但它明确地表述了在碰到什么情况的时候应该做什么样的动作。这个策略不仅可以向下延展和嵌套,还可以添加更多的描述信息以处理以后N年内遇到的事情。按照这个原则去做抉择,一定会得到若干在这棵树上的访问路径,并获得一系列的奖励值。计算它们的算术平均值,就相当于对“上大学”这个状态的价值进行评估。现在,你应该理解间接法的值函数是如何进行估算的了吧。

我们回顾一下这种方法的思路(如图2-4所示)。为了使策略π能够在短时间内根据一个状态s找出应该做的最好的动作,我们希望策略π实现一个简单的、只有一层关系的树搜索。按照这种方式,在状态s下做一个动作a后,只要能够迁移到的任意一个状态s′的估值能够被正确地估算出来,那么这个人或者机器人在做决策的时候,就只需要比较估值的大小(哪个s′的估值大,就选择它所对应的动作a)。这种方式操作简单,思路清晰,唯一的问题在于是否能够准确、快速地得到s′的估值。

图2-2 状态变化和估值评价

本书后面将要介绍的大部分传统强化学习算法,都会采用各种手段计算某个状态s的价值v(s),这也是把与传统强化学习相关的书读“薄”的一个基本思路。

2.5 马尔可夫决策过程

在本章中,不仅要介绍强化学习的脉络,还要来一点“干货”。在本节中,让我们一起了解一下马尔可夫决策过程(Markov Decision Process, MDP),如图2-5所示。

图2-3 短视

熟悉马尔可夫安德雷·安德耶维齐·马尔可夫(Aндpeй Aндpeeвич Mapкoв,1856年6月14日-1922年7月20日),俄国数学家。老爷子的读者朋友,可能一下子就能通过“望文生义”的办法猜出我下面要干什么了。可以说,马尔可夫这种“一招鲜,吃遍天”的方法,让我们在很多领域尝到了甜头,例如通信领域的编解码纠错、现代输入法的智能输入预测等。

在数学及其相关领域,提到“马尔可夫”,通常意味着:在一系列事件中,某给定事件发生的概率,只取决于前面发生的事件。言外之意就是:更久以前发生的事件不在研究范围内,只关注前面发生的事件,只针对前面发生的事件和现在发生的事件的关系来做研究。这里的“前面”,指的就是时序上的“先”。

2.5.1 状态转移

马尔可夫决策过程中的环境,需要满足条件

P[St+1|St]=P[St+1|S1,...,St].

这个等式的含义是,前一个状态St到后一个状态St+1的转移概率,不会随着更久以前的状态的加入而改变。如果一个环境中的状态变化满足这样的条件,就可以称状态St是马尔可夫的(或者是满足马尔可夫的)。例如,如果昨天下雨,那么今天下雨的概率是30%,今天不下雨的概率是70%,且不论前天是什么天气,一定会得到这个观测结果,于是,可以说这个地区的天气变化是马尔可夫的。在这种条件下,对一个策略的研究,虽然不能开启“上帝视角”,但总有一些“捷径”可以走。

假设在一个设定好的世界中,有一个机器人,它每天都会根据昨天的天气情况决定今天出门的时候带什么装备。为了讨论方便,我们把模型设置为最简单的状态,如图2-6所示。

图2-4 状态的变化

在这个世界里,我们事先设计了这样的规则:如果第一天是晴天,则第二天是晴天的概率为70%、是雨天的概率为30%;如果第一天是雨天,则第二天是晴天的概率为60%、是雨天的概率为40%。现在,我们把一个机器人放到这个世界里。这个机器人每天都要出门转一圈,能做的动作只有“打伞”和“不打伞”。那么,这个机器人应该怎样设定自己的策略呢?在开始讨论之前,要补充一个重要条件,那就是奖励值,如表2-6所示。

图2-5 马尔可夫决策过程

在这里设定的值,与在2.4.1节中设定的值不一样。不过,没关系,反正这本书的内容像“系列剧”,而不像“连续剧”,场景多一点也好,不会给人留下千篇一律的印象。

事实上,在不同的环境中,这种奖励值的设定几乎是由人一手操办的。因此,本节中的4个奖励值和2.4.1节中的不同,也是有充分理由的。

· 雨天打伞,晴天不打伞,这叫正解,得到1分;

· 晴天原本不用打伞,但非要打伞,就会缩短伞的使用寿命,所以,得到 -0.5分;

· 雨天直接“裸奔”搞不好会生锈的哦,所以,雨天不打伞要重重处罚,得到 -1分。

这样就可以求出一个最棒的策略了吗?是的。其实,方法很多,尤其在简单的题设下,我们甚至可以“拍脑袋”决定。为什么呢?由图2-6可知,晴天后大概率是晴天,雨天后大概率还是晴天,晴天不打伞能得到1分。显然,“拍脑袋”决定不带伞出门是个不错的策略。事实是不是这样呢?我们往后看。

2.5.2 策略与评价

“原地式”转移图(图2-6)不够直观,让我们换一种直观的方式,如图2-7所示。

图2-6 “原地式”天气转移概率图

是不是清楚多了?从上到下,一层就代表一天,时间一天一天地流逝,每一天“晴”和“雨”的概率都根据前一天天气的不同而不同。圆角方框里的数字是概率(例如,晴天之后的一天是晴天的概率为0.7,晴天之后的一天是雨天的概率为0.3)。右侧虚线框内的部分,其实和左侧右下角三个实线框组成的部分是一样的,它只是时间上的一个分支。现在我们来看左侧的两层分支,只要能把左边的那个分支研究清楚,就能把右边的那个分支研究清楚。

由于这个模型是马尔可夫的,机器人出门是否打伞根本不会影响转移的概率变化。那么,在每两层(也就是每两天)中间添加一个对动作选择的表述,会怎么样呢?假设机器人看到某一天是晴天,第二天会有50% 的概率选择打伞出门,有50% 的概率选择不打伞出门,应该是什么样子呢?如图2-8所示。

表2-6 机器人打伞奖励值表

无论在晴天时做什么动作,第二天“晴”和“雨”的概率都是“三七开”,因此,第二层圆角方框中的值一定是0.7、0.3、0.7、0.3。打伞和不打伞的概率各为多少呢?这就是策略。这个例子中的策略(让机器人采用晴天后的一天打伞和不打伞各50% 的概率),写出来应该是这样的:

0.5=πa=打伞|s=晴);

0.5=πa=不打伞|s=晴).

s=晴,指的是前一天;a=打伞,指的是今天。

别忘了前面的假设:机器人只能根据前一天的观测结果来决定今天的动作策略。按照这种策略,晴天时的奖励值是多少呢?如表2-7所示。

图2-7 “时序式”天气转移概率图

在上述情况下,晴天的完整策略所得到回报的数学期望值为0.175。也可以说,当前一天为晴天时,按照50% 的概率打伞、50% 的概率不打伞的策略估算,得到的平均回报值为0.175。这也属于典型的“现世报”或者说瞬时奖励值,即没有添加任何远期回报值的评估,通过相乘和相加就能直接得到结果。

在同样的情况下,假设观测到雨天后,第二天也是50% 的概率打伞、50% 的概率不打伞,会得到多大的回报值呢?如图2-9所示。

图2-8 带有动作的天气转移概率图(观测到晴天)

采取的策略是:

0.5=πa=打伞|s=雨);

0.5=πa=不打伞|s=雨).

如表2-8所示,很容易就能计算出来,这种情况下的奖励值为0.15(比观测到晴天时的奖励值小一些)。对此进行简单的定性分析:因为晴天之后是晴天的概率比雨天之后是晴天的概率大,所以,以同等概率打伞出门的机器人会得到较小的奖励值。

表2-7 晴天时的奖励值分布

可以明确的是,我们已经“做”出了一个策略——不是训练出来的——就是策略π

0.5=πa=打伞|s=晴);

0.5=πa=不打伞|s=晴);

0.5=πa=打伞|s=雨);

0.5=π(a=不打伞|s=雨).

这“四句话”组合起来,就是一个完整的策略。如果把它们写成程序,应该是一个类似“查表+if…else…语句+随机数”的简单策略。即便只靠“脑补”,相信大家也能把这个程序琢磨得差不多。现在,我们能不能量化评价这个策略的水平或者能力呢?可能暂时无法给出完整的评价。毕竟一个状态下的“现世报”的奖励值太片面了,要想对某些值进行相对准确的预估,需要将眼光放长远些,而眼下,我们只有“眼下”的内容……不要紧,我们至少可以先写出基于一个策略的某个状态的价值的表达式:

从广义上说,策略就得用这种看上去既抽象又枯燥的东西来表示,因为越具象的东西,所能指代的内容就越具体,迁移性也就越低。上面这个表达式说的就是:在策略π驱使下的状态s的价值,可以通过等号右边的部分计算出来;等号右边的部分,表示把所有的动作以策略所规定的输出概率π(a|s)取一遍,然后分别乘以各自的估值qπ(s,a)

这里引入了一个新概念,就是qπ(s,a)

qπ(s,a)表示,在策略π的驱使下,以状态s做动作a的估值(这个估值就是价值估值)。在强化学习中,q的含义是没有二义性的,就是指动作的估值(与vπ(s)的视角不同,vπ(s)是状态的估值)。这样,在本节的例子里,晴天这个状态在策略π下的价值为:

vπ(晴)=0.5×qπ(晴,打伞)+0.5×qπ(晴,不打伞).

别管这个数字具体是多少,先弄明白它们之间的数量关系。这就是前面我们通过加权平均的方法算出来的价值,只不过,在前面算出来的是“现世报”的价值。

qπ(s,a)应该怎么计算呢?

公式就是这么冷冰冰的,我们还是画一幅图来表示吧(如图2-10所示)。

图2-9 带有动作的天气转移概率图(观测到雨天)

图2-10 qπ(晴,打伞)

假如,要评价qπ(晴,打伞)的估值,应该怎么计算呢?

根据图2-10, “打伞”这件事已经发生了,“晴”和“雨”的概率是“三七开”。先是“现世报”部分,也就是“晴天概率×晴天奖励值+雨天概率×雨天奖励值”(0.7×1+0.3×(−1))。接下来,是一个打了折扣的远期估值。在这里,我顺手给出了 γ=0.9,也就是到达每个状态s′的概率分别乘以其状态估值的这样一个求和的数学期望值,具体写出来就是:

qπ(晴,打伞)=(0.7×1+0.3×(−1))+0.9×(0.7×vπ(晴)+0.3×vπ(雨)).

qπ(晴,不打伞)也能通过这种方式得出具体的表达式。不过,写出这个表达式以后,你心里可能一下就凉了——这简直成了循环论证,vπ里面套着qπ,qπ里面套着vπ,没完没了。其实,可以写成vπ,也可以写成qπ,最好能通过传统的解方程的方法,用qπ来代换vπ——只剩一个未知数,解起来应该容易一些吧。

如果能够解出qπ(s,a),并且能够得到一个最优化的qπ(s,a),就得到了一个完整的策略。从形式上看,qπ(s,a)直接表达了在状态s下做动作a的价值有多大,这对机器人的自动决策来说就是查表或者做选择题,非常直观。这个表达式是这样的:

这个公式实在太长了,令人不忍直视,但实际上,它只是将vπ做了代换。只要你能理解vπqπ的含义,那么这个公式里就没有新概念了,只有旧概念的堆叠。更让人沮丧的是,这个方程很难通过传统解方程的方法解出来。一般来说,一个好的π,需要通过值迭代、策略迭代(或者我们将在第5章中学习的时间差分法)等方法找到。如果你现在还不习惯,后面还有很多机会来熟悉它们。

2.5.3 策略优化

有关策略优化,在本节中只介绍策略迭代(Policy Iteration)。

策略迭代操作起来比较简单,大致过程如下。

①以某种策略开始在环境中做动作,就像我们试着执行那个以“五五开”的概率打伞的策略一样。在这个时候,会得到相应的vπ(s),当然,也可以得到相应的qπ(s,a)

②在一个确定的策略下,得到qπ(s,a)的值。只要能得到这个值,就一定能在确定的状态s的输入下,从qπ(s,a)中找到估值最大的qπ(s,a)的值。我们还是通过机器人根据天气决定是否打伞的例子来讲解。有两个不同的状态,以及两个不同的动作,所以,表中一共有4个值。如果有n个不同的状态,以及m个不同的动作,就应该有一个n ×m的表来保存qπ(s,a)的值,同时借助这个表输出一个完整的策略——每一次都挑选估值最大的动作作为新的策略,然后再来一次。我们将这个策略命名为π′

③使用π′在环境里做动作,会得到新的v′π(s)q′π(s,a),而且比前一个策略π要好(因为每次都会选择比原来的估值大的动作前往估值大的状态)。一个迭代结束后,还会产生π′′、π′′′这样的策略。只要将这个过程持续下去,总会收敛到最优策略上。

这就是策略迭代的方法,看上去有点像“贪心法”,因为每次都选择得分最高的动作,每一代都比上一代进步一点。最优的策略肯定是存在的,因为机器人表现得再好,也是在每个状态下得到一个有限的分数,做得好分数就高一些,做得不好分数就低一些,而策略估值的上限和下限都是存在的。

2.6 Model-Based和Model-Free

在学习强化学习的过程中,有两个名词早晚会出现在我们面前,就是Model-Based和Model-Free。在一些资料中,我们经常会见到“这是一个Model-Based的算法”或者“这个方法是典型的Model-Free的算法”的说法。“Model-Based”通常被翻译成“基于模型”,“Model-Free”通常被翻译成“无模型”。

可能有人会问:为什么会有这样两个算法呢?这就要从它们各自的含义说起。

2.6.1 Model-Based

“Model-Based”既然被翻译成“基于模型”,那么关键就在于理解什么是模型。这里的“模型”,是我们常说的用机器学习的方法训练出来的模型吗?不是。这里的模型是指,在一个环境中各个状态之间转换的概率分布描述。还是以天气为例。我在广东省珠海市,想要用刚刚提到的“模型”的概念描述天气(或者说建立一个天气模型),应该怎么做呢?我要想办法建立一个表格,如表2-9所示。

表2-8 雨天时的奖励值分布

表2-9 天气模型

左侧的纵坐标表示第一天的天气状况,上方的横坐标表示第二天的天气状况。经过长期的统计,得到了这样一个天气转移概率表。其中,第3行第5列表示在第一天是阴天的情况下第二天有雨的概率。

这就是一个天气模型,和我们在本章开头讨论的SARS′ 相比,少了AR。拥有了这样的模型(Model),我们能做什么呢?不管是否满足马尔可夫特性,只要有这么一个模型存在,就必然能够在初始状态确定的情况下找出一条满足特定要求的路径。只要模型是确定的,转移概率就是确定的。只要转移概率是确定的,我们就能知道对应于SS′ 的转移概率,以及在状态S下做什么样的动作A会有最高的回报值。这样,一个状态的估值vπ(s),以及一个状态下的动作估值qπ(s,a),就比较容易被准确地估计出来了。

2.6.2 规划问题

在1.2.1节中,我们提到过一个在四四方方的城市范围内导航的例子,它就是一个比较典型的规划问题的例子。

规划问题(Planning Problem)是运筹学的一个分支,是用于解决决策问题的,或者说,是用于在一定的约束条件下得出最优决策的。规划问题常用的套路,要么是解方程组,要么是解不等式组,并试着求出满足限制条件的极大值或者极小值。1.2.1节中那个导航的例子比较理想化,由于解的空间比较小,我们采用了最为直接的穷举排序的方式来求出满足路程成本极小值的路径。对于解的空间较大,尤其是解的空间是连续值的情况,通常就要使用其他解法了,例如梯度下降(上升)法、模拟退火算法、遗传算法等(求解一个函数处于极小值时的函数自变量)。

在1.2.1节那个导航的例子中我们曾经说过,由于开启了“上帝视角”,用GPS等高科技手段掌握了全城的道路情况,在求解这个问题时,我们根本不需要建立一个含有待定系数的模型、通过正向传播让它产生误差、最终通过最优化的手段把极小值解出来的过程——在这里,完全没有使用强化学习的必要。

这就是规划问题的应用场景了。如果在一个环境中,能够得到在一个状态下做某个动作后转移到另一个状态的概率,并且清楚地知道在这个过程中获得的奖励值的数学期望值,那么,这个问题就是一个规划问题。也就是说,可以通过遍历树、解方程、解不等式等一列工程方法求一个函数的极小值来获解,不需要采用机器学习的手段,更不需要采用强化学习的手段。我想,编过代码、写过遍历树的程序员朋友,一定明白我在说什么。

2.6.3 Model-Free

理解了Model-Base的概念,就可以理解Model-Free的概念了——Model-Base的对立面。

在前面提到过,如果一个问题看起来满足规划问题的条件,那就把它当成规划问题来解决,不需要使用强化学习算法。可是,模型的建立工作由谁来完成呢?如果在环境建立之后没有人去建立模型,我们就不能进行人工智能手段上的策略探索和学习了吗?答案是否定的。事实上,情况恰恰相反:有人帮我们做好模型的情况很少出现。在绝大多数场景中,模型是未知的,至少是未曾精确量化的。怎么办?其实,这才是强化学习希望得到的更具普适性的方式和方法。

随着学习的深入,你会了解更多的 Model-Free算法。现在,你可以先建立一个基本的印象。例如,Q-Learning是通过不断求解一个状态下的动作估值函数Q(s,a)来进行策略学习的,它并没有采用先根据统计结果做出一个模型再做规划的方法,而是直接以类似查表的方法,估算Q(s,a)中每个“小格子”的值,从而进行建模和求解的。这个思路是很好的——我们不是“先知”,怎么知道模型长什么样?因此,采用一个直观的方法来解决问题会更靠谱。

2.7 本章小结

在这一章中,我们一起整理了强化学习的知识脉络。

强化学习是机器学习的一个分支,要想把它弄明白,需要有扎实的数学和机器学习基础理论功底。然而,数学和机器学习功夫过硬的读者,已经能够去啃大部头的经典教材了。本书希望服务的读者,主要是对强化学习感兴趣,但掌握的知识比较有限的读者,因此,只能在有限的篇幅内进行适当的取舍,以强化学习为主线,串联讲解必须掌握的知识点,并通过前后呼应的方式让读者跟随本书的内容反复学习。只有这样,才能尽量避免出现“零零散散地阅读了一大堆概念,但在脑子里还是无法将它们联系起来”的问题。

现在,我们碰到的问题是什么?做出一个能在一定的范围和环境中智能地行动的机器人。什么叫“智能”?能够高质量地完成一个完整的任务就叫“智能”。

因为一个完整的任务是由多个步骤或状态的转移构成的,所以,在建模时,是以S→A→R→S′的方式来描述的。

如果任务比较简单、已知的环境条件描述比较充足,或者说,任务可以用传统的解决规划问题的方法及穷举、遍历的方法解决,那么,就直接使用这些方法来解决。

如果直接通过上述方法无法完成任务,那么,先看看它是不是MDP,或者看看它是否有完整的Model描述。如果有,那就太好了,这仍旧是一个规划问题,可以采取规划问题的解决方案来解决。通过基于Model的状态转移来统计并计算当前哪个状态下的哪个路径是期望的奖励值最高的——这就是Model-Base的方式。如果Model信息不全,或者不方便通过推导Model来建立整个模型,就需要借助其他方式。例如,通过Model-Free的方式,一边在环境中试探,收集像SARS′ 这样的Transition,一边通过统计的方法更新一个状态下的不同动作的估值。当某个状态下的估值逐渐变得准确的时候,就可以通过类似查表的方法得到一个确定的、优质的动作决策了。

这是一个把解决问题方法的复杂度提升的过程。如果能使用简单的方法,就尽量使用简单的方法。实在不行,才退而求其次,用基于模型的统计方法进行规划,逐步得到每个状态下的最优动作。如果还是不行(例如没有模型信息),就只能一边试探,一边计算估值,通过大量的实验,把空间“试探”出来,把一棵完整的搜索树“强化”出来。这就是解决相关贯序决策问题的完整思路。

我不想咬文嚼字,从学术的视角去解释概念或者抛出枯燥的术语,那样做对理解问题帮助不大。我认为,顺着一个自然的推导过程、采用一种具有生发性的思维去考虑问题,应该会对理解问题的全貌有更大的帮助。

接下来,我们将紧扣Model-Free思想下的算法族和算法体系进行讨论,这些都是理解强化学习思维的重点。读到这里,希望你能感觉到,这不是一本照本宣科的教条手册,而是一个能与你一起聊天、一起思考的伙伴。