(以下内容均来源于 CS 294 Lecture 8)
首先我们假设环境是确定性的,即在某个状态执行某个动作之后,转移到的下一个状态是确定的,不存在任何随机性。而在这种情况下,我们想做的是在环境给了我们一个初始状态的条件下,根据我们需要完成的任务以及环境模型,直接得出从初始状态到任务完成状态中间最优的动作序列。因为环境是确定的,而我们又已知环境模型,因而以上想法是自然且可行的。下图展示了我们想做的事情:
现在我们将以上问题抽象成一个正式的优化问题:
其中
但是在随机环境下,解决与确定环境的类似的如上优化问题并不能得到与确定环境一样的最优解。原因在于我们只接受环境反馈回来的初始状态,接着便凭借着我们掌握的环境模型在脑海中进行规划。这种方法在确定环境下没有任何问题,但在随机环境下,智能体实际会转移到的状态可能并不符合我们的预期,因为它是从一个条件状态分布中随机采样的。而一旦从某一个状态开始与我们的预期产生偏差,那么后续的所有状态都会产生偏差,而我们设想的最优动作序列便不是最优了。从优化函数的角度来看,我们优化的只是一个期望值,而不是某一次随机采样的值。
我们把上述解决问题的方法叫做开环方法,与之对应的叫做闭环方法。那么这个“环”具体是指什么呢?具体示意图如下:
开环方法是只在最开始时接收环境反馈的初始状态,然后开始规划从开始到任务完成的过程中所经历的所有状态对应的最优动作,并不需要一个基于状态产生动作的策略;反之,闭环方法在每一个时间步都会接收环境反馈的状态,然后利用一个根据状态输出动作的策略来产生一个动作。我们可以看出,对于一个随机环境,闭环方法显然比开环方法更具优势,因为其可以根据所处的状态随时调整自己的动作。
但接下来我们还是首先假定一个确定性的环境,因而采用开环方法来解决上述问题。下面将介绍三种优化方法:随机优化方法、蒙特卡洛树搜索法以及轨迹优化方法。
随机优化方法
对于随机优化方法来讲,上述优化问题可以简化为如下等价优化问题:
随机优化方法完全不关系优化目标的特殊结构等信息,而是把任何优化问题都当作上图右半边这样的一般优化问题。
随即发射方法
最简单的随机优化方法就是随机瞎猜,即随机选择一个动作序列,然后评估其累积的代价。如上过程不断进行,最后选择一个累积代价最小的动作序列作为上述优化问题的最优解,因而这类方法也叫做“随机发射方法”:
CMA算法
但是这种方法在相对高维的情况下效率会很低,因为搜索空间太大但是目标区域比较小。回顾一下上述方法,我们可以在采样分布上做些文章。假设第一次从一个均匀分布采样一些动作序列之后,得到的累积代价分别为如下情况:
那么下一次我们可以不再继续从一个均匀分布中采样了,我们可以聚焦于累积代价较小(累积回报较大)的区域,然后估计那个区域的分布,在这里我们假设分布是一个高斯分布:
接下来的采样我们就从这个新的分布中进行采样:
然后在下一次采样之前,我们再次聚焦于性能更好的区域然后估计其分布:
就这样不断迭代,直到满足停止条件。以上方法就是Cross-Entropy Method(CEM)算法,其伪代码如下:
该方法还有个进阶版的算法叫做CMA-ES算法,后者可以看作是CMA算法带动量的版本。CMA算法会直接舍弃之前采样的数据点,但是CMA-ES算法会保留部分之前采样的数据点的相关信息,用来指导后续的采样。可以类比一下梯度下降法以及带动量的梯度下降法。
总结
随机优化方法具有以下优点:
- 并行化后效率极高
- 实现起来十分简单
但是也存在如下不可避免地缺点:
- 极易受到维度灾难的影响
- 只适用于开环情形
随即优化方法虽然可以同时适用于连续变量以及离散变量的情况,但不是专门为离散情况设计的。下面我们将介绍一种专门为离散动作空间设计的强大的优化方法(严格来讲叫做启发式搜索算法):蒙特卡洛树搜索MCTS方法。
蒙特卡洛树搜索算法
MCTS方法本质是一个搜索算法:
假设我们想要训练一个智能体能够自动去玩上面这个游戏(击沉敌方潜水艇将会获得分数,但是潜水艇自身的氧气储存量是逐渐减少的,需要不时地去浮出水面补充氧气。被敌方潜水艇撞上会损失生命值,游戏目标就是获得尽可能多的分数)。一个简单的暴力搜索算法可能会包含上图右边的过程,假设一段最优动作序列仅仅包含十个时间步,每个状态下仅仅包含两个可能动作,那么最后一个时间步就包含1024个可能性。但对于大多数问题来说,十个时间步远远不足以完成目标,因而暴力搜索算法是不可行的。
那么蒙特卡洛算法是如何在不穷举所有可能性直到到达终点的情况下对一个动作序列进行评估的呢?考虑潜水艇游戏,在潜水艇做出攻击指令后,由于炮弹的运行需要时间,因而几个时间步之后敌方潜水艇才会被击沉从而受到奖励,在潜水艇做出攻击指令那个时间步是没有任何奖励的,因而智能体可能认为这个动作并不是一个优秀的动作。对于以上情况,其实我们只需要在做出攻击指令后,如果要评估这个动作的优劣,“等待”几个时间步 即可。蒙特卡洛树搜索算法正是采用这种思想,同样用上图右边的过程举例,当动作执行到第三层时,如何评估这四个动作序列的性能好坏呢?算法进行了某种“等待”,即从第三层开始,不再把树进行完全的扩展了,而是采用一个随机策略随机执行动作直到游戏结束或者到达某个设定的时间步。这就类似于在潜水艇游戏中,潜水艇在发出炮弹后,随机执行一些动作,直到炮弹击中敌方潜水艇。
而蒙特卡洛算法正是通过这种评估方法来避免暴力搜索,具体来说,蒙特卡洛树搜索算法会根据评估结果的好坏以及访问次数来决定下一步应该搜索哪一条路径:
可能以上描述有点难以理解,那么下面我们过一遍蒙特卡洛树搜索方法的搜索过程。我们首先给出算法的执行步骤:
首先我们处于一个初始状态:
然后我们进行算法第一步,根据一个“树策略”找到一个叶子节点,注意这里找到一个叶节点的意思是找到一个**新的*叶节点。树策略的具体形式如下:
根据以上策略,由于初始状态没有被完全扩展,因而随机选择一个动作,并执行第二步使用默认策略来评估执行这个动作的好坏,这里默认策略使用的是随机采样策略:
假设评估结果如下:
这里Q代表环境定义的回报,N代表访问这个状态的次数。**这里值得注意的是,N记录的并不是某个具体的状态的访问次数,而是执行某个动作的次数,执行这个动作后在随机环境下可能转移到很多个不同的状态,但在树中均显示为一个节点。**评估完之后,我们需要更新根节点到这个新加入的叶节点之间所有节点的Q值以及N值。由于这里两者之间并没有其他的节点,因而跳过这一步。然后以上过程开始循环,我们再将状态跳回到初始状态,遵循树策略,找到下一个新的叶节点。由于初始状态还是没有扩展完毕,因此这一次执行下一个未被执行过的状态:
再采用默认策略对其进行评估,假设我们得到了以下结果:
由于根节点与新的叶节点之间的路径并没有其他节点,因而更新步骤略过。再次重复以上过程,将状态跳回到初始状态,执行树策略找到一个新的叶节点。首先根据树策略,初始状态已经被完全扩展开了(即所有可能的动作均已经执行过),这个时候我们根据树策略中的公式计算每一条路径的一个分数。从分数计算公式可以看出,这个分数是同时考虑动作的回报以及动作的执行次数,更加倾向于执行被执行次数少的回报高的动作。在这里,由于两个动作被执行次数均为1,因而我们选择回报更高的第二个动作执行,然后再根据树策略(在没有找到新的叶节点之前,循环执行树策略),第二层的状态没有被完全扩展,因而随机选择一个动作执行:
依据默认策略进行评估:
注意,到了这一步,根节点到新的叶节点之间的路径存在其他节点了,我们就要用最新的叶节点的评估值以及访问次数加到这些中间节点的评估值以及访问次数上:
再次重复上述过程,将状态跳回到初始状态,调用树策略,这时候根据分数计算公式,在假设一些超参数的情况下,我们假定这个时候更加侧重于执行被执行次数更小的动作并评估:
然后再更新再跳回......
如果想详细了解蒙特卡洛树搜索算法的扩展以及应用,可以参考下面这篇综述:
这里讲一个比较有意思的案例:
其思想其实是将DAgger算法与MCTS算法进行结合。由于DAgger算法需要人工的不断参与进行新数据的标注,以上案例将专家标注的过程用MCTS算法进行替代,学习一个MCTS的策略估计器:
那么为什么不直接使用MCTS算法呢?其实是基于以下两点考虑的:
- 实时性要求较高的任务中MCTS太慢了
- 采用类似神经网络的策略估计器具有更好的泛化性
路径优化算法
让我们再次回顾以下优化问题:
直接丢弃掉以上优化问题中的特殊结构显然不是十分恰当的,接下来让我们回到一般解决以上优化问题的思路。我们一看到以上问题,就会首先想到能不能利用类似梯度下降的方法呢?为了与最优控制中路径优化算法的一般符号记法一致,我们将以上问题重写为以下形式:
我们可以将约束部分放进优化函数中从而将以上问题转变为一个无约束问题:
对于以上问题,只要我们知晓以下四项,即可根据链式法则得出其最优解:
LQR算法
确定性环境
为了解决以上优化问题,我们接下来将介绍一种路径优化算法LQR,此算法假设环境模型是线性的,并且代价函数是二次的:
为了解决这种特殊形式的以上优化问题,我们采用动态规划的思想,先找出最优的最后一个时间步的动作。之所以这样做,是因为我们可以发现,以上连加项中只有最后一项是与最后一个时间步的动作相关的。如果我们首先解决第一个时间步的最优动作,那么连加项的所有项都与第一个时间步的动作相关。接下来,我们把最后一项中连续的函数求值简写为
然后我们将线性项系数以及二次项系数展开:
然后,为了得出最优动作,我们令这个优化目标关于最后一个时间步动作的梯度等于0:
求解以上线性方程,可以得出最后一个时间步的最优动作为:
将其进行简单的转化,我们可以看出,最后一个时间步的最优动作是最后一个时间步状态(现在还是未知项)的线性函数(以上关系适用于所有时间步):
其中:
由于最后一步的最优动作完全可以用最后一步的状态表示,我们可以得出最后一个时间步的最优的Q值,这里我们将其记为V:
这里的Q值以及V值其实是和强化学习中的定义是一致的。接下来,我们将上式展开:
将上式合并同类项可得:
其中:
因而我们可以得到另一个关系,**最后一个时间步的V值(最优Q值)是最后一个时间步状态的二次函数(以上关系适用于所有时间步)。**进行到这里,我们已经解出最后一个时间步的最优动作了。接下来,我们要在此基础上解出倒数第二个时间步的最优动作。首先我们注意到,倒数第二个时间步的Q值函数可以记为:
将环境模型引入可将V值展开:
我们将展开后的V值代入倒数第二时间步的Q值函数中:
其中:
同样,为了求出倒数第二个时间步的最优动作,我们令相关梯度为零:
解得倒数第二个时间步的最优动作为:
其中:
让我们不断地重复以上过程,直到第一个时间步。值得注意的是,由于每一时间步的最优动作与那个时间步的状态有关,但是状态是未知的。
当整个过程回溯到初始时间步时,情况发生了变化,**初始状态我们是已知的!**因而,我们就可以算法初始时间步的最优动作。利用环境模型,我们就可以得知第二个时间步的状态,如此循环下去,我们就可以得知所有时间步的最优动作:
以上就是整个LQR算法的执行过程。
非确定性环境 (未完成)
对于非确定性环境,假设我们的环境模型如下:
那么LQR算法依旧是完全可行的。
iLQR算法
LQR算法由于假设环境模型以及代价函数是线性以及二次的,表达能力有限,对于更加复杂的任务显然不能很好的估计。因而,解决这个问题的iLQR算法应运而生。其基本思想很简单,既然线性以及二次函数不足以估计全局的真实函数,那么估计局部的总是足够的。因而我们可以对环境模型以及代价函数分别做一阶以及二阶的泰勒展开!:
那么我们的问题其实又转变回了原始的LQR设定:
其中:
iLQR算法的具体框架如下:
**该算法之所以采用迭代的形式,是因为其需要不断地用真实样本来去”矫正“其对于环境模型以及代价函数的估计。**更严格来讲,该算法之所以能够达到很好的效果,是因为它和牛顿方法的本质是一样的(通过泰勒展示来估计一个复杂的非线性函数的局部特性):
而如果我们对环境模型估计时也进行二阶泰勒展开:
那么我们的算法就变为微分动态规划算法(DDP)。但是在实际情况中,代价函数的形式一般比较简单,因而进行二阶泰勒展开代价不大。但是环境模型一般是十分复杂的,一阶展开还好,一旦进行二阶展开其复杂性将会大大增加。事实表明一阶展开其实是足够的。
但是以上算法还存在一个问题,考虑以下估计误差:
对于这种情况,其实我们只要简单的在原始iLQR算法中加一个line search过程即可:
最后我们看一个iLQR算法在实际情况应用的实例:
为了保证iLQR更加稳定,这个工作采用了如下形式的改进:
即在每一步都进行一个完整的规划,但是考虑到iLQR的估计误差随着时间会产生累积,因而每次只执行规划的第一步。