Model-Free中的基础技术
前面的策略迭代、价值迭代都是基于模型的,在模型完全已知的情况下,计算、都相对简单,但很多时候模型并不是已知的,那对于、只能估计。
1 Monte Carlo Method
这可能是最直观的方法了。注意因为模型未知所以只能从推出,反着不行。所以估计更有意义。
那么给定策略如何估计?我们令agent用该策略和环境交互,采样得到一系列episodes,根据这些episodes,就可以计算每个动作-状态对的累积收益,如果这个对在一条episode中第一次出现,则作为这个动作-状态对出发的累积收益的一个估计值。然后求均值作为期望累积收益的估计值。这种方式叫首次估计。还有一种每次估计,是指每次出现都用来计算期望累积收益。伪代码如下:
returns = defaultdict(list)
q = dict()
for episode in episodes:
G = 0
for t in reversed(range(len(episode))):
S, A, R = episode[t]
G = gamma * G + R
# 判断是否第一次出现
if S, A not in episode[1:t]:
returns[S, A].append(G)
q[S, A] = avg(returns[S, A])
至此我们建立了model-free的策略评估方法,那接下来按照model-based部分的思路,很自然会想如何基于进行策略改进。我们发现之前取argmax的思路在这里还是有用的,只不过为了充分利用样本,采用广义策略迭代的思想,每次更新都随之更新policy。
此外,不同于策略评估只需要被动的采样,策略改进需要我们仅可能准的估计,因此采样质量需要尽可能高采用两个技巧:
- 初始状态采用试探性假设,即每一个有可能出现的动作-状态对都有成为初始状态的可能。
- -soft策略,即任何一个动作被选择的概率 ,-greedy作为一个特例,是最接近最优情况的,这个参照策略改进定理可以证明,如下和分别是任意一个soft和相应的-greedy策略,如果把soft变成-greedy,能不能有提升?推导过程如下:
最后一个大于号的意思是,q里面的最大值,大于等于对所有q的加权平均,只是这里的权重设置非常艺术,即兼顾了和前面的因子约分,也兼顾了和后面的求和项抵消。当然这个问题本身很直观,就是我在满足软性要求的情况下,把概率全都给了取最大了,那他肯定比别的策略好啊。
因此我们通常训练时会采用这种方法,不过估计完了之后实际用agent的时候,就不需要了,而是直接取最优结果。
初始化 policy, q, returns
for i = 1,2,..., T:
# 试探性出发假设
choose S0, A0 s.t. all posiibility non-zero
episode = generate sequence from S0, A0 based on soft-policy
G = 0
for t in reversed(range(len(episode))):
S, A, R = episode[t]
G = gamma * G + R
if S, A not in episode[1:t]:
returns[S, A].append(G)
q[S, A] = avg(returns[S, A])
# 广义策略迭代思想,更新一次q接着进行策略改进
policy[S] = argmax(q[S, A]) with prob (1-eps/|A|) while other with prob eps/|A|
2 on-policy与off-policy
一但涉及控制(改进策略),就自然带来一个问题,用来获取样本的探索策略和作为优化对象的策略到底要不要是同一个策略。同一个叫on-policy,否则叫off-policy。
off-policy可以更好平衡eplore-exploit问题,policy在优化过程中减少了explore,但是如果想对环境估计准确,就必须explore,注意这个问题是在model-free情况下而产生的新问题。主要两种方法:
- 普通加权采样:
- 加权重要度采样:
两者只有分母不一样。其中 表示状态导致策略更新的时刻(首次估计和每次估计会有区别),表示的是t所在这一幕结束的时刻。这里为了方便表示其实约定了把episode连接成了一个整体。最重要的
这个其实很直观,就是对于G,后面的状态和action都是基于策略的,所以他出现的概率换成策略会有变化,如何变呢,就是除以的概率再乘的概率。
这个式子左侧如果是也是一样,只不过时刻的含义变成了动作-状态对的首次/每次出现时刻。还要注意普通采样虽然无偏,但是方差无限。加权重要性采样虽然渐进无偏,但是方差有限。后者应用更多。
代码为了保持和上述符号一致就直接截图了。
几个细节如下:
- 为什么取argmax的tie-breaking需要固定,因为这个算法求的是一个确定性算法,所以同一个状态对应的action应该是确定的,否则会出现随机性
- 为什么有一个判定会退出内层循环?因为如果 那就意味着当前action是一个根据现在优化策略不可能出现的action,所以相当于策略出现了一个永远不会出现的状态,那这一个episode就废了。这也预示着如果选取的不合适,跟始终相差很大,那么很容易episode能用的部分都很短,训练会减慢。
- 为什么最后增量处理的重要性因子分子是1,这个用第1个问题的回答就能解决。首先我保证了是一个确定性算法,进一步我要求在时刻采取的策略必须是我优化后的目标策略也能取到的,所以这个分子肯定是1,否则就是0,直接退出了循环。
- 更新的公式似乎和前面的加权重要度采样公式不一样?其实是一样的。这是一个等价变形。如果,那么
3 时序差分
蒙特卡洛不自举,但是依赖环境,DP自举,但是不依赖环境。TD是两者的结合产物。他既不需要依赖环境,又能利用自举。为什么自举是一个优势?因为不需要等待一个完整的episode,而且方差更小。
对于预测问题,自举价值函数的更新公式为
关键不同于MC的点是被替换成了
几个经典的TD算法
- SARSA算法(on-policy): 这个算法一次迭代需要action两次,两次动作的选择都可以用-greedy
- Q-Learning (off-policy):
- 期望SARSA on/off-policy:
这里on/off-policy关键看自举估计的方式所隐含的policy(实际输出的policy)跟采样的policy是不是一个。比如q-learning明显估计时候用的是greedy,但采样的可能是soft。期望sarsa可以看作是on-policy的,因为是当前的探索策略。也可以是off-policy的,如果是一个其他的策略。如果是贪心,那他恰好就是Q-Learning。这个算法alpha即使比较大性能也ok
为什么这里的off-policy没有重要性系数?因为不同于MC算法,他是自举的,没有使用一整条episode来估计累计收益。所以不存在policy不同产生的累积误差。更新是按照目标策略在更新,并不是按照探索策略在更新
4 TD(n)
蒙特卡洛是一种episode看到底的视角,TD(0)是一种只看下一步的视角,这是两种极端情况,可以取一个折衷,效果会更好。
理论支撑:误差减少性质:
Sarsa(n)
其中 ,
注意变成重要性采样系数的角标发生变化,这是因为时刻的已经确定了,所以多了一个因子。如果是期望SARSA,那么结尾变成,这是因为最后一步用期望算了,也没有。
重要性采样虽然保证了可以使用一个不同于目标策略的策略保持探索,但是因为重要性系数使得方差变大了,迫使使用一个小alpha,带来缓慢的收敛,有没有可能不用重要性采样呢?对于单步算法是可以的,比如QL和SARSA的off-policy就没有重要性采样,如果n步怎么搞?这就是下面的算法
n步树回溯算法
选取的action用+来估计,其他没选取的action直接自举估计。
这里的最后一项需要倒序求解避免重复计算
代码如下
算法
综合比较off-policy的期望-SARSA、n-SARSA、树回溯算法的回溯图,(注意这个问题实在off-poliy的范畴下讨论的,因为树回溯就是为了去掉重要性采样而生),发现有相似之处,能否进行统一?即每一步都可以选择是采样还是回溯?于是有了算法
其中就是对求和算出来的。
5 资格迹
offline -reward:经典
利用-回报估计期望累积收益作为价值函数的逼近目标:
lambda为1,就是MC,lambda为0,就是TD(0),前面(1-)是归一化系数。对比MC、TD的话,他拓展了估计价值函数的新维度,MC和TD只是在一个期望累积收益算多少步的问题上有区别,而这个直接算了多个期望累积收益。
用的算法只能是offline的,因为他需要用到后面的reward。为了解决这个问题,使用前向视角优化。
TD():一种高效的近似
前向预测方式为:
之所以前向因为需要用t往后的(向前看)回报叠加。针对上述方法提出改进,形成了这种后向算法:
- 改进一:每一步更新,而不是episode结束后更新
- 改进二:计算负担平均分配在每个episode上
- 改进三:适用于持续性问题,不仅仅是episodic
算法如下:
理解:是一个长期记忆,在训练中积累,是一个短期记忆,随时间衰减,是一种backward view。也就是说,在步更新时,算法更新的梯度也有之前计算出来的梯度方向,如果站在之前梯度对应的时刻,相当于在那个梯度时间点之后更新了。
如果=0,那么他就是TD(0) 如果=1,=1,那么短期记忆不衰减,就是一种MC,这种MC比前面那种好,因为他是backward的,意味着可以在episode中间执行更新
这个算法似乎完美的解决了offline reward不能在线的问题,但实际上在线算法对的估计是近似的,所以人们还是不死心,希望能够提出更加明确的方法来优化offline-reward。为此,先提出来基于截断的TTD的方法来对offline近似,然后再把截断的长度不断推进得到online-reward的算法,不过发现计算代价太高,所以又提出利用荷兰迹的True Online算法
Truncated-TD:offline的近似优化
前面offline-reward算法是求和到episode结束的,一个自然的想法是采用截断来近似,这种方法叫,这样就有
实际实现时会用后面的差分误差项来表示,具体方式为:
online-reward:从TTD改进offline得到的online算法
有了TTD,我们可以重新审视offline-reward并改进成online版本,最直接的方法就是:随着episode前进,不断地增加。这就是所谓online-reward算法,但这个算法代价极其高昂,因为每当增加1,所有的的估计就变了。本着探索越多,估计越好的假设,我们需要利用新的从头更新一遍梯度。之所以需要从头是因为新的对应的梯度更新需要用到的权重,而这个权重我们只有时候计算的,没有当前计算的,所以只能从通来一遍。 这种方法引发了平方复杂度,于是有人提出True Online
TTOD:优化高昂的代价
这一块可以参考这个博客 zhuanlan.zhihu.com/p/348333751
就是巧妙的考察梯度之间依赖关系和我们实际使用的梯度,化简计算过程。这个化简思路就是递归展开加重排:
这个过程中的和之前的资格迹略有不同,称为荷兰迹,伪代码如下:
这四种算法的计算量,TD< True-Online < off-line < online
其他技巧和注意事项
- 双学习:有些动作因为方差导致估计值大于了实际值,错误地选择之作为最优动作,为此引入双学习,训练两个Q,等概率选择一个更新,选action的时候把两Q加起来,消除方差。
- 后位状态:take action之后的状态,棋局游戏能够很明确知道take action之后的状态,而且很多状态可能重复,可以加速收敛。
- 优先遍历:显然均匀采样不是一个高效的做法,如果能够有选择的挑选更能带来价值函数更新的(s,a),能有效提高效率。
- 期望更新与采样更新的权衡:期望更新是指根据对后继状态求期望来估计,采样更新是指只用一个后继状态去估计。
- Rollout MCTS: 从当前状态,模拟多个可能结果,实现一个较好的状态估计
- RTDP: 一种异步DP,他可以限制从某些有用的状态出发,然后on-policy的方式更新相关状态,节约计算量。
- Dyna-Q: 他首先直接从刚获得经验(S、A、S')更新,这和Q-Learning一样。但是会另外把经验保存并设计一个模型去拟合收集的经验,内部造一个小环境。然后利用模型更新(随机选一个状态,然后用这个内部小模型更新n次)。但是这样存在一个问题,如果环境是随机变化的,或者模型对环境的近似有缺陷,那么可能从模型规划更新起反作用。如果模型比较乐观,那还好,因为我们会发现实际的收益比模型给出来的少,这样就会更新价值函数重新调整策略。但如果模型本身给出来的就比较差,那就不一定很容易更新了。特别是在函数已经基本收敛的情况下。这其实也是一种探索-利用权衡问题。
- Dyna-Q+: 给长时间没有与真实环境交互的(s,a)一个新的收益 是距离上次真实遇到该元组的时刻。这样鼓励了探索那些长时间没有探索的(s,a)。思想和UCB是一样的。
- 收敛问题致命三要素:函数逼近、自举、off-policy。而且这种风险并不是因为GPI/环境未知导致的(因为很良好的情况也可能出现)所以为了避免发散,我们需要放弃三要素中的某一个。函数逼近很难放弃,因为它能压缩状态。自举虽然可以,但是数据效率上也有很大损失。off-policy也很难放弃。所以这个事还挺麻烦。