接上一篇博客[RL] 4 Dynamic Programming (1)。
Policy Iteration
对于给定的
policyπ
,一旦我们通过
vπ
改进后得到
π′
,我们就可以计算新的value function
v′π
,然后我们就可以进一步改进
π′
得到
π′′
。因此我们可以得到policies和value functions的非下降序列:
其中, −→E 代表policy evaluation, −→I 代表policy improvement。因为finite MDP只有有限个数的policies,所以这个序列一定会在有限步数的迭代之后收敛到一个optimal policy,并得到一个optimal value function。这种寻找optimal policy的方法我们称为 policy iteration。
Pseudocode伪代码:
- Initialization
V(s)∈Randπ(s)∈A(s)arbitrarilyforalls∈S
- Policy Evaluation
Repeat
Δ←0
Foreachs∈S:
v←V(s)
V(s)←∑s′,rp(s′,r∣s,π(s))[r+γV(s′)]
Δ←max(Δ,|v−V(s)|)
Until Δ<θ(asmallpositivenumber)
- Policy Improvement
policy-stable←true
Foreachs∈S:
old-action←π(s)
π(s)←argmaxa∑s′,rp(s′,r∣s,a)[r+γV(s′)]
Ifold-action≠π(s),then policy-statble←false
If policy-stable,then stop and return V≈v∗ and π≈π∗; else go to 2
这段伪代码有一个小bug,就是最终可能在两个一样好的policies之间不断跳转。可以通过添加一个额外的标志位来解决,但为了代码看上去更清晰,这里我们不解决这个bug。
Value Iteration
Policy iteration的一个弊端是它的每一轮迭代都涉及到policy evaluation,而这本身又是需要扫遍整个状态集的耗时的迭代计算过程。事实上,我们可以约减掉policy evaluation。我们使用下式来迭代地计算optimal value function:
对任意的 v0 ,如果 v∗ 存在,则序列 {vk} 将收敛到 v∗ 。这种方法我们称为 value iteration。
(1)式可以从Bellman optimality equation的角度理解:
实际上,和上一篇博客中policy evaluation的想法一样的,只不过policy evaluation的时候,我们是在给定policy下迭代地去求value function,而这里,我们直接通过迭代的方式去求optimal value function。
Pseudocode伪代码:
Initialize array V arbitrarily (e.g., V(s)=0foralls∈S+ )
Repeat
Δ←0
Foreachs∈S:
v←V(s)
V(s)←maxa∑s′,rp(s′,r∣s,a)[r+γV(s′)]
Δ←max(Δ,|v−V(s)|)
Until Δ<θ(asmallpositivenumber)
Output a deterministic policy, π≈π∗ , such that
π(s)=argmaxa∑s′,rp(s′,r∣s,a)[r+γV(s′)]
实际上,value iteration高效地合并了policy evaluation和policy improvement。当然,有时候在其中插入一些policy evaluation会使得收敛速度更快。也就是说,我们的算法可以看做一轮一轮的迭代,在有些轮次上使用policy evaluation,而在有些轮次上使用value iteration。
Asynchronous Dynamic Programming
DP的不足之处,就是在每一轮迭代时,会涉及到整个状态集。如果状态集非常大,那么即使是一轮简单的迭代,也会有高昂的开销。比如西洋双陆棋就有超过1020个状态,即使我们可以每秒处理一百万个状态,我们仍然需要超过一千年来完成一轮迭代。
Asynchronous DP不完整地遍历每个state作为一轮迭代,它每一次任意地选择一个state然后根据(1)式更新它的value function。也就是说,asynchronous DP更灵活,它可以按任意次序迭代地更新state。Asynchronous DP的优势在于,它可以加快收敛的速度,因为它可以有意识地挑选收敛更快的state进行更新。另外,它也很适用于实时交互的场景,它可以在有限时间内给出一个较优的policy。
Asynchronous DP算法具体如何计算我们暂时不在这里展开。
Generalized Policy Iteration
Policy iteration由两步构成,一步是通过当前policy计算相应的value function,一步是根据当前的value function改进policy。在policy iteration中,这两个步骤交替进行,必须在对方执行完成后开始进行。在value iteration中,我们看到两个步骤交替进行是没有必要的,policy evaluation可以在改进policy的同时进行。而asynchronous DP方法更是将policy evaluation和policy improvement的交替执行划分到更细的粒度。无论如何,最终的结果都是收敛到optimal value function和optimal policy。
我们使用术语generalized policy iteration(GPI)来描述让policy evaluation和policy improvement相互交互的想法,与具体的粒度无关,如图1。
图1 GPI
在GPI中,evaluation和improvement之间的关系可以看做是竞争与合作的关系。它们朝两个相反的方向相互竞争,根据value function改进的policy会使得在新policy下原来的value function不再是最优的,而根据policy计算得到的value function会使得当前的policy不再是最优的,它们是相互竞争的,但它们最终会收敛到同一点,因此也是相互合作的,如图2。
图2 evaluation和improvement的竞争与合作
Efficiency of Dynamic Programming
对于大规模的问题,DP并不实用,但是相比较其他解MDP的方法,DP实际上还是相当高效的。如果我们不考虑一些技术上的细节,DP寻找一个optimal policy的最坏时间,是关于states和actions的数量的多项式。假设n和k是states和actions的数量,尽管可能的policies的数量是指数kn的,但DP的时间复杂度是n和k的多项式时间。
线性规划方法(linear programming methods)也可以用来解MDP,而且在一些实例上,他们的时间复杂度要优于DP,但是线性规划的方法在states数量增加的时候变得不切实际,因此在较大规模的问题上DP更合适。
但DP也会有不适用的时候,主要是因为维度灾难(curse of dimensionality)。实际上,states的个数与state变量的个数是成指数关系的,state变量相当于维数,每扩展一维,states的数量就呈指数增长。但事实上,DP比直接暴力搜索和线性规划方法更适合处理state空间大的问题。
在实际应用中,使用现在的计算机,DP可以解百万数量级states的MDP问题。Policy iteration和value iteration都被广泛地使用,也无法说明哪一个方法更优。在实际应用中,DP的收敛速度比理论上的最坏情况通常要好得多,特别是如果他们有一个好的初始value function或policy的时候。
在较大state空间的问题下,我们更倾向于使用asynchronous DP。对于synchronous DP,一轮计算都需要在每一个state上消耗计算和存储,对于有些问题,可能即使是一轮的空间和时间开销都是无法满足的。但这些问题依然有可解的可能性,因为实际上只有相对较少的states会出现在optimal solution的轨迹上。Asynchronous DP或者GPI的一些其他变体可以在这些问题上应用,会比synchronous方法更快地得到一个较优或最优policy。