PyTorch强化学习——马尔科夫决策过程

1,171 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第19天,点击查看活动详情

前言

在马尔可夫链的基础上实现的马尔科夫决策过程 (Markov Decision Process, MDP) 涉及智能体和决策过程。接下来,我们将实现马尔科夫决策过程并在最佳策略下计算值函数。

马尔可夫决策过程

除了一组可能的状态 S=s0,s1,...,smS = {s_0,s_1,...,s_m} 外,马尔科夫决策过程还包括一组动作 A=a0,a1,...,anA = {a_0, a1, ..., an}、状态转移函数 T(s,a,s)T(s,a,s')、奖励函数 R(s)R(s) 和折扣因子 γ\gamma。状态转移函数 T(s,a,s)T(s, a, s') 表示从状态 ss 采取行动 aa 然后转移到状态 ss' 的概率。折扣因子 γ\gamma 用于权衡未来奖励和当前奖励之间的重要程度。

为了更好的理解马尔科夫决策,我们使用另外一个状态 s2(code)s_2(code) 来扩展在《马尔科夫链》中介绍的 studysleep 过程,假设有两个可以选择的动作,分别为 a0(work)a_0(work)a1slack)a_1slack)3×2×33\times 2 \times 3 的转换矩阵 $T(s,a,s')如下:

T={[0.80.10.10.10.60.3][0.70.20.10.10.80.1][0.60.20.20.10.40.5]T=\left\{ \begin{matrix} \begin{bmatrix} 0.8 & 0.1 & 0.1 \\ 0.1 & 0.6 & 0.3 \\ \end{bmatrix}\\ \begin{bmatrix} 0.7 & 0.2 & 0.1 \\ 0.1 & 0.8 & 0.1 \\ \end{bmatrix} \\ \begin{bmatrix} 0.6 & 0.2 & 0.2 \\ 0.1 & 0.4 & 0.5 \\ \end{bmatrix} \\ \end{matrix} \right.

例如,在状态 s0(study)s_0(study) 时采取动作 a1(slack)a_1(slack) 时,有 60% 的概率将转换为状态 s1(sleep)s_1(sleep),有 30% 的概率将转换为状态 s2(code)s_2(code),且有 10% 的概率继续 study。我们将三种状态的奖励函数定义为[+1,0,1][+1,0,-1]。显然,在这种情况下,最佳策略是在每个时间步中选择动作 a0a_0,保持 study 状态,将折扣因子设为 0.5,在下一节中,我们将在最佳策略下计算状态值函数 (state-value function,也称为值函数或值)。

使用 PyTorch 实现 MDP

本节中,我们使用 PyTorch 实现 MDP

首先,导入所需库并定义过渡矩阵、奖励函数和折扣因子:

import torch
T = torch.tensor([[[0.8, 0.1, 0.1],
                   [0.1, 0.6, 0.3]],
                  [[0.7, 0.2, 0.1],
                   [0.1, 0.8, 0.1]],
                  [[0.6, 0.2, 0.2],
                   [0.1, 0.4, 0.5]]]
                 )
R = torch.tensor([1.0, 0, -1.0])
gamma = 0.5

在此环境下,最佳策略是在所有情况下都选择操作 a0a_0

action = 0

定义函数,使用逆矩阵法来计算最优策略的值函数 VV,关于如何推导该值函数,我们将在下一节中介绍:

def cal_value_matrix_inversion(gamma, trans_matrix, rewards):
    inv = torch.inverse(torch.eye(rewards.shape[0]) - gamma * trans_matrix)
    V = torch.matmul(inv, rewards.reshape(-1, 1))
return V

我们向函数提供所有变量,包括与动作 a0a_0 相关的转移概率:

trans_matrix = T[:, action]
V = cal_value_matrix_inversion(gamma, trans_matrix, R)
print("The value function under the optimal policy is:\n{}".format(V))

运行程序可以得到以下输出结果:

The value function under the optimal policy is:
tensor([[ 1.6787],
        [ 0.6260],
        [-0.4820]])

在这种简单的 study-sleep-code 过程中,最佳策略(即获得最高总奖励的策略)是在所有时间步中均选择动作 a0a_0。但是,在大多数情况下,情况并非都是如此简单,在各个时间步中需要采取的动作也不一定相同,这通常取决于不同状态。因此,我们必须在实际应用中根据不同情况找到最优策略来解决马尔科夫决策过程。

一个策略的值函数可用与衡量在遵循该策略的情况下,智能体在每种状态下的好坏程度。值越大,状态越好。我们使用逆矩阵发计算最优策略的值 VV。根据 Bellman 方程,步骤 t+1t + 1 的值与步骤 tt 的值之间的关系可以表示为:

Vt+1=R+γ×T×VtV_{t+1}=R+\gamma\times T\times V_t

当值收敛时,意味着 Vt+1=VtV_{t + 1} = V_t,我们可以得出值 VV,如下所示:

V=R+γ×T×VV=(Iγ×T)1×R\begin{matrix} V=R+\gamma\times T\times V \\ V=(I-\gamma\times T)^{-1}\times R\\ \end{matrix}

其中,II 是主对角线上值为 1 的单位矩阵。 使用逆矩阵法求解 MDP 的优势在于总是可以获得准确的解。但是缺点是它的可扩展性,由于我们需要计算 m×mm \times m 矩阵的逆矩阵(其中 mm 是可能的状态数),因此如果存在大量状态,则计算代价将变得很十分高昂。 我们可以尝试使用不同大小的折扣因子。当折扣因子为 0 时,表示我们只关心即时奖励:

gamma = 0
V = cal_value_matrix_inversion(gamma, trans_matrix, R)
print("The value function under the optimal policy is:\n{}".format(V))

输出结果如下,可以看到其与奖励函数完全相同,这是因为我们仅考虑下一步动作中获得的奖励:

The value function under the optimal policy is:
tensor([[ 1.],
        [ 0.],
        [-1.]])

当折扣因子增加到 1 时,表示长期奖励和即时奖励同等重要。接下来,我们查看当 γ=0.99\gamma = 0.99 时的值 VV

gamma = 0.99
V = cal_value_matrix_inversion(gamma, trans_matrix, R)
print("The value function under the optimal policy is:\n{}".format(V))

输出结果如下所示:

The value function under the optimal policy is:
tensor([[65.8293],
        [64.7194],
        [63.4876]])