动态规划算法(DP):在马尔可夫决策过程(MDP)的完美环境模型下计算最优策略。但其在强化学习中实用性有限,其一是它是基于环境模型已知;其二是它的计算成本很大。但它在理论伤仍然很重要,其他的一些算法与动态规划算法(DP)十分相似,只是计算量小及没有假设环境模型已知。
动态规划算法(DP)和一般的强化学习算法的关键思想都是基于价值函数对策略的搜索,如前所述,一旦我们找到满足贝尔曼最优方程的最优价值函数 v ∗ v_\ast v∗ 或 q ∗ q_\ast q∗,我们就可以很容易地获得最优策略。
v ∗ ( s ) = max a E [ R t + 1 + γ v ∗ ( S t + 1 ) ∣ S t = s , A t = a ] = max a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v ∗ ( s ′ ) ] , o r q ∗ ( s , a ) = E [ R t + 1 + γ max a ′ q ∗ ( S t + 1 , a ′ ) ∣ S t = s , A t = a ] = ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ max a ′ q ∗ ( s ′ , a ′ ) ] \begin{aligned} v_\ast(s) &=\max_a\Bbb{E}[R_{t+1}+\gamma v_\ast(S_{t+1})|S_t=s,A_t=a]\\ &=\max_a\sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma v_\ast(s^\prime)\Big],\quad \rm{or}\\ q_\ast(s,a)&=\Bbb{E}\Big[R_{t+1}+\gamma\max_{a^\prime}q_\ast(S_{t+1},a^\prime)\Big |S_t=s,A_t=a\Big]\\ &=\sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma\max_{a^\prime}q_\ast(s^\prime,a^\prime)\Big] \end{aligned} v∗(s)q∗(s,a)=amaxE[Rt+1+γv∗(St+1)∣St=s,At=a]=amaxs′,r∑p(s′,r∣s,a)[r+γv∗(s′)],or=E[Rt+1+γa′maxq∗(St+1,a′) St=s,At=a]=s′,r∑p(s′,r∣s,a)[r+γa′maxq∗(s′,a′)]
首先,我们考虑如何计算任意策略 π \pi π 下的状态价值函数 v π v_\pi vπ,我们称其为策略评估
v π ( s ) ≐ E π [ G t ∣ S t = s ] = E π [ R t + 1 + γ G t + 1 ∣ S t = s ] = E π [ R t + 1 + γ v π ( S t + 1 ) ∣ S t = s ] = ∑ a π ( a ∣ s ) ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] \begin{aligned} v_\pi(s)&\doteq \Bbb{E}_\pi[G_t|S_t=s]\\ &=\Bbb{E}_\pi[R_{t+1}+\gamma G_{t+1}|S_{t}=s]\\ &=\Bbb{E}_\pi[R_{t+1}+\gamma v_\pi(S_{t+1})|S_t=s]\\ &=\sum_a\pi(a|s)\sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma v_\pi(s^\prime)\Big] \end{aligned} vπ(s)≐Eπ[Gt∣St=s]=Eπ[Rt+1+γGt+1∣St=s]=Eπ[Rt+1+γvπ(St+1)∣St=s]=a∑π(a∣s)s′,r∑p(s′,r∣s,a)[r+γvπ(s′)]
其中, π ( a ∣ s ) \pi(a|s) π(a∣s) 表示在策略 π \pi π 下当状态为 s s s 时采取动作 a a a 的概率,以 π \pi π 为下标的期望是指其计算是基于策略 π \pi π 的。只要保证 γ < 1 \gamma<1 γ<1 及存在终止状态,则 v π v_\pi vπ 存在且唯一。
如果环境动态模型完全已知,那么上述方程可通过迭代计算来求解,即
v k + 1 ( s ) ≐ E π [ R t + 1 + γ v k ( S t + 1 ) ∣ S t = s ] = ∑ a π ( a ∣ s ) ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] \begin{aligned} v_{k+1}(s)&\doteq \Bbb{E}_\pi[R_{t+1}+\gamma v_k(S_{t+1})|S_t=s]\\ &=\sum_a\pi(a|s)\sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma v_\pi(s^\prime)\Big] \end{aligned} vk+1(s)≐Eπ[Rt+1+γvk(St+1)∣St=s]=a∑π(a∣s)s′,r∑p(s′,r∣s,a)[r+γvπ(s′)]
显然 v k = v π v_k=v_\pi vk=vπ 是这个更新规则的不动点,因为贝尔曼方程保证了其相等,实际上在保证 v π v_\pi vπ 存在的条件下,当 k → ∞ k\rightarrow\infty k→∞时,序列 { v k } \{v_k\} {vk}可以收敛至序列 v π v_\pi vπ,这种算法成为迭代策略评估。
为了使 v k + 1 v_{k+1} vk+1 相比 v j v_j vj 更加逼近 v π v_\pi vπ,迭代策略评估对每个状态 s s s 应用如下操作:用状态 s s s 的旧价值来更新 s s s 的新价值,再用 s s s 的新价值替换 s s s 的旧价值,我们称这种操作为预期更新。迭代策略评估的每次更新都会产生新的估计价值函数 v k + 1 v_{k+1} vk+1。
若要编写程序实现上述的迭代策略评估,必须使用两个数组,一个储存旧价值 v k ( s ) v_k(s) vk(s),另一个储存新价值 v k + 1 ( s ) v_{k+1}(s) vk+1(s),我们用旧价值数组来一个接一个地计算新价值数组,过程中可以立刻改变旧价值数组,也可以更新完毕再改变旧价值数组,这两种方法均收敛于 v π v_\pi vπ,事实上前者收敛速度更快。
网格中除了灰色格子每个格子都对应一种状态,即非终端状态为 S = { 1 , 2 , ⋯ , 14 } \cal {S}=\{1,2,\cdots,14\} S={1,2,⋯,14},每个状态都有四种可能的动作,即 A = { u p , d o w n , r i g h t , l e f t } \cal{A}=\{\rm{up,down,right,left}\} A={up,down,right,left},每种状态都会使得状态发生变化(注意,移动至网格外的动作会使状态保持不变),在到达终端状态之前,所有的奖励都是 -1,终端状态为灰色格子(尽管为两个格子,但实际是一个状态),因此 r ( s , a , s ′ ) = − 1 r(s,a,s^\prime)=-1 r(s,a,s′)=−1,假设智能体遵循等概率随机策略(等概率随机选择动作),计算每个状态到终止状态的期望收益。
import numpy as np
world_size = 4 # 网格为4*4
a_position = [0, 0]
b_position = [world_size - 1, world_size - 1]
actions = [
np.array([0, -1]), # 左
np.array([-1, 0]), # 上
np.array([0, 1]), # 右
np.array([1, 0]) # 下
]
action_prob = 0.25
def step(state, action):
"""
:param state: 当前状态,坐标的list,比如[1,1]
:param action: 当前采取的动作
:return: 下一个状态(坐标的list)和reward
"""
if state == a_position:
return a_position, 0
if state == b_position:
return b_position, 0
next_position = (np.array(state) + action).tolist()
x, y = next_position
# 判断是否出界
if x < 0 or x >= world_size or y < 0 or y >= world_size:
reward = - 1.0
next_position = state
else:
reward = - 1.0
return next_position, reward
def grid_world_value_function():
value = np.zeros((world_size, world_size))
episode = 0
while True:
episode += 1
# 每轮迭代都会产生一个new_value,直到new_value和value很接近即收敛为止
new_value = np.zeros_like(value)
for i in range(world_size):
for j in range(world_size):
for action in actions:
(next_i, next_j), reward = step([i, j], action)
new_value[i, j] += action_prob * (reward + value[next_i, next_j])
error = np.sum(np.abs(new_value - value))
if error < 1e-4:
break
value = new_value
return value
if __name__ == '__main__':
value1 = grid_world_value_function()
print(value1)
[[ 0. -13.99990421 -19.99985806 -21.99984116]
[-13.99990421 -17.99987496 -19.99985901 -19.99985806]
[-19.99985806 -19.99985901 -17.99987496 -13.99990421]
[-21.99984116 -19.99985806 -13.99990421 0. ]]
我们计算策略的价值函数的原因是为了找到更好的策略,假设我们已经知道某策略 π \pi π 的价值函数 v π v_\pi vπ,对于某些状态我们想知道是否应该改变策略,虽然我们根据 v π v_\pi vπ 知道当前的策略有“多好”,但是更换策略是“更好”还是“更差”呢?一种方法就是在状态 s s s 时确定性地选择动作价值函数最高的动作 a a a,然后遵循现有的策略 π \pi π,
q π ( s , a ) ≐ E [ R t + 1 + γ v π ( S t + 1 ) ∣ S t = s , A t = a ] = ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] \begin{aligned} q_\pi(s,a)&\doteq \Bbb{E}[R_{t+1}+\gamma v_\pi(S_{t+1})|S_t=s,A_t=a]\\ &= \sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma v_\pi(s^\prime)\Big] \end{aligned} qπ(s,a)≐E[Rt+1+γvπ(St+1)∣St=s,At=a]=s′,r∑p(s′,r∣s,a)[r+γvπ(s′)]
关键在于它是大于还是小于 v π ( s ) v_\pi(s) vπ(s),如果它更大,那么也就是说在状态 s s s 选择一次(根据上述公式,只有这一次的动作选择不遵循策略 π \pi π)动作 a a a 的策略比一直遵循策略 π \pi π 要更好,那么也就是说每次遇到状态 s s s 都确定性地选择动作 a a a 会更好,事实上新策略确实更好。
假设 π \pi π 和 π ′ \pi^\prime π′ 是任意一对确定性策略,有 q π ( s , π ′ ( s ) ) ≥ v π ( s ) q_\pi(s,\pi^\prime(s))\geq v_\pi(s) qπ(s,π′(s))≥vπ(s),也就是说策略 π ′ \pi^\prime π′ 优于策略 π \pi π,也就是说它在所有状态下均获得更多的期望收益,即 v π ′ ( s ) ≥ v π ( s ) v_{\pi^\prime}(s)\geq v_\pi(s) vπ′(s)≥vπ(s),我们称其为策略改进定理。
到目前为止,在给定策略及其价值函数的条件下,我可以轻松地在单个状态下对动作的更改,我们将其延伸至所有状态下动作的更改,即在每个状态下根据 q π ( s , a ) q_\pi(s,a) qπ(s,a) 来选择最佳的动作,也就是选择新的贪心策略 π ′ \pi^\prime π′,即
π ′ ( s ) ≐ arg max a q π ( s , a ) = arg max a E [ R t + 1 + γ v π ( S t + 1 ) ∣ S t = s , A t = a ] = arg max a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v π ( s ′ ) ] \begin{aligned} \pi^\prime(s)&\doteq \argmax_aq_\pi(s,a)\\ &=\argmax_a\Bbb{E}[R_{t+1}+\gamma v_\pi(S_{t+1})|S_t=s,A_t=a]\\ &=\argmax_a\sum_{s^\prime,r}p(s^\prime,r|s,a)\Big[r+\gamma v_\pi(s^\prime)\Big] \end{aligned} π′(s)≐aargmaxqπ(s,a)=aargmaxE[Rt+1+γvπ(St+1)∣St=s,At=a]=aargmaxs′,r∑p(s′,r∣s,a)[r+γvπ(s′)]
贪心策略采取的是在短期内看起来最好的动作,可以看出它优于原策略。根据原策略的价值函数通过贪心方法改进原策略,从而得到新策略,我们称其为策略改进。
到目前为止,我考虑的是确定性策略这种特殊情况,事实上,上述所有思想可以很容易地扩展到随机策略。
一旦通过价值函数 v π v_\pi vπ 改进策略 π \pi π,得到更好的策略 π ′ \pi^\prime π′,我们就可以计算价值函数 v π ′ v_{\pi^\prime} vπ′,再改进策略 π ′ \pi^\prime π′,得到更好的策略 π ′ ′ \pi^{\prime\prime} π′′,由此我们可以得到一系列单调改进的策略和价值函数:
π 0 ⟶ E v π 0 ⟶ I π 1 ⟶ E v π 1 ⟶ I π 2 ⟶ E ⋯ ⟶ I π ∗ ⟶ E v ∗ \pi_0\stackrel{E}{\longrightarrow}v_{\pi_0}\stackrel{I}{\longrightarrow}\pi_1\stackrel{E}{\longrightarrow}v_{\pi_1}\stackrel{I}{\longrightarrow}\pi_2\stackrel{E}{\longrightarrow}\cdots\stackrel{I}{\longrightarrow}\pi_\ast\stackrel{E}{\longrightarrow}v_\ast π0⟶Evπ0⟶Iπ1⟶Evπ1⟶Iπ2⟶E⋯⟶Iπ∗⟶Ev∗
其中 ⟶ E \stackrel{E}{\longrightarrow} ⟶E 表示策略评估, ⟶ I \stackrel{I}{\longrightarrow} ⟶I 表示策略改进,每个策略都优于前一个策略。由于有限马尔可夫决策过程只有有限个策略,因此该过程必然会在有限次的迭代中收敛到最优策略和最优价值函数。
这种寻找最优策略的方法被称为策略迭代,完整算法如下所示,可以看出每次策略评估本身就是一次迭代计算,都是从前一个策略的价值函数开始,这通常会使得策略评估的收敛速度大大提高。
策略迭代的一个缺点是:它得每次迭代都要进行策略评估,这本身就是一个冗长的迭代计算,而策略评估只有在极限的情况下才收敛到 v π v_\pi vπ,我们是否可以在此之前就截断迭代呢?答案是可以的。实际上,在保证策略迭代收敛的前提下,可以通过多种方式截断策略迭代中的策略评估过程,一种特殊的方式是,策略评估时每个状态仅更新一次就停止,这种算法称为值迭代。它可以写成一个特别简单的更新操作,其中结合了策略改进和截断策略评估:
v k + 1 ( s ) ≐ max a E [ R t + 1 + γ v k ( S t + 1 ) ∣ S t = s , A t = a ] = max a ∑ s ′ , r p ( s ′ , r ∣ s , a ) [ r + γ v k ( s ′ ) ] \begin{aligned} v_{k+1}(s)&\doteq \max_a\Bbb{E}[R_{t+1}+\gamma v_k(S_{t+1})|S_t=s,A_t=a]\\ &=\max_a\sum_{s^\prime,r}p(s^\prime,r|s,a)[r+\gamma v_k(s^\prime)] \end{aligned} vk+1(s)≐amaxE[Rt+1+γvk(St+1)∣St=s,At=a]=amaxs′,r∑p(s′,r∣s,a)[r+γvk(s′)]
对于任意的 v 0 v_0 v0,序列 { v k } \{v_k\} {vk} 都会收敛于 v ∗ v_\ast v∗。理解值迭代的另一种方法就是参考贝尔曼最优方程,只需要将贝尔曼最优方程转换为更新规则即可获得值迭代。最好我们看一下值迭代是如何终止的,与策略评估一样,值迭代需要无限次迭代才能精确收敛到 v ∗ v_\ast v∗,但实际上,值函数在一次迭代过程只发生了极小的变换,我们就停止迭代,完整算法如下所示:
值迭代在每次迭代过程中都有效的结合了一次策略评估和一次策略改进,通过在每个策略改进之间插入多个策略评估,通常可以实现更快的收敛。