RL 学习笔记 #8 策略梯度方法
本文最后更新于:2024年12月23日 下午
在之前的学习中,我们讨论了 Value-based 方法,例如 Q-Learning 和 SARSA。这类方法都是以值函数为核心,先估计或学习值函数再间接推导出策略,不断进行采样和迭代优化。然而,在许多复杂场景中,直接优化策略往往是更为高效的做法。
因此,从本节开始,我们将介绍 Policy-based 方法,核心是直接对策略进行建模和优化。本节主要介绍策略梯度(Policy Gradient),而下一节会扩展到 Actor-Critic 方法。
基于策略的目标函数
之前我们的所有策略也都是表格形式的 —— 使用 \((s,a)\) 作为索引的二维表格,每个值代表状态 \(s\) 下采取动作 \(a\) 的概率。这种策略往往是基于值函数推导出来的,例如 \(\varepsilon\)-greedy。
Policy-based 方法的基本思想是直接用参数化的策略 \(\pi(a \mid s; \theta)\) 代替基于值函数推导的策略。这里,策略 \(\pi(a \mid s; \theta)\) 是某个概率分布的模型,参数为 \(\theta\)(例如,最常用的神经网络模型)。这个策略的输入是 \(s\),输出是状态 \(s\) 下可执行的所有 \(a_i \in A(s)\) 的概率。这里的策略有时候也会写作 \(\pi_\theta(a \mid s)\)。
与 Value-based 方法相比,参数化策略有以下优点:
- 自然处理连续动作空间:Value-based 方法通常依赖离散化处理(即使是值函数近似,最终策略也是基于表格计算的),而参数化策略能够高效地直接优化连续的动作概率分布。
- 更高效和可泛化的优化过程:Value-based 方法只有当索引访问到 \((s,a)\) 时才会更新对应的策略,而 Policy-based 方法在访问一个 \((s,a)\) 时对函数的优化也会作用到其他状态-动作。
- 探索更加多样化:由于策略是一个概率分布,天然地支持随机探索。
为了优化这个策略,我们需要定义最优策略 \(\pi^*\)。在之前的表格形式中,我们定义: \[ v_{\pi^*}(s) \ge v_{\pi}(s),\;\; \forall s \in S \] 而在参数化情况下,我们需要定义一个标量目标函数 \(J(\theta)\),而这个目标函数通常与策略的长期表现(长期回报)相关。在优化过程中,我们无法直接修改 \(\pi(a \mid s)\) 的概率分布,而是需要对参数 \(\theta\) 进行更新从而修改概率。
接下来我们将介绍这个目标函数 \(J(\theta)\) 的构成。
指标一:Average Value
我们定义策略 \(\pi\) 的平均状态值为: \[ \bar{v}_\pi= \mathbb{E}_{s \sim d} \left[ v_\pi(s) \right]=\sum_{s\in \mathcal{S}}d(s) v_\pi(s)=d^\top v_\pi \] 其中,\(d(s)\) 是状态 \(s\) 的权重,满足 \(\sum_{s\in \mathcal{S}}d(s)=1\)。在 Average Value 中,\(d\) 可以有以下两种形式:
策略无关的分布:我们将其记为 \(d_0\)。此时在 \(\bar{v}_\pi\) 中仅有 \(v_\pi\) 与策略有关,记为 \(\bar{v}_\pi^0\),因此在求梯度 \(\nabla_\pi \bar{v}_\pi^0\) 时就不需要考虑分布 \(d_0\),更方便计算。常见的一种情况是将所有状态同等看待: \[ d_0(s) = \frac{1}{|\mathcal{S}|}, \] 也可以自定义偏好,例如赋予初始状态高权重: \[ d_0(s_0) = 1,\quad d_0(s\ne s_0) = 0. \]
稳态分布(Stationary Distribution):与上一节定义值函数近似目标函数类似,我们考虑智能体在策略 \(\pi\) 下在每个状态停留的概率。此时访问次数多的状态自然就被赋予了高权重。
考虑到 \(v_\pi(s)\) 可以展开为状态 \(s\) 的平均回报: \[ v_\pi(s) =\mathbb{E}\left[\sum_{t=0}^\infty \gamma^t R_{t+1} \mid S_0=s \right] \] 因此,\(\bar{v}_\pi\) 还有另一个等价的形式: \[ \begin{aligned} \bar{v}_\pi &= \sum_{s\in \mathcal{S}}d(s)\mathbb{E}\left[\sum_{t=0}^\infty \gamma^t R_{t+1} \mid S_0=s \right] \\ &=\mathbb{E}\left[\sum_{t=0}^\infty \gamma^t R_{t+1} \right]\\ \end{aligned} \]
指标二:Average Reward
对于策略 \(\pi\),我们也可以定义一个更加通用的平均奖励 / 平均单步奖励: \[ \bar{r}_\pi= \mathbb{E}_{s \sim d_\pi} \left[ r_\pi(s) \right]=\sum_{s\in \mathcal{S}}d_\pi(s) r_\pi(s) \] 其中:
- 与 Average Value 不同的是,这里的 \(d_\pi\) 直接是稳态分布,依赖于策略 \(\pi\)。
- \(r_\pi(s)\) 表示状态 \(s\) 下的平均奖励: \(r_\pi(s) = \sum_{a\in \mathcal{A}}\pi(a\mid s) r(s,a)\);
- \(r(s,a)\) 表示状态 \(s\) 时执行动作 \(a\) 的平均奖励:\(r(s,a)= \sum_{r}r p(r\mid s,a)\)。
它还有另一个等价的形式: \[ \begin{aligned} & \lim _{n \rightarrow \infty} \frac{1}{n} \mathbb{E}\left[R_{t+1}+R_{t+2}+\cdots+R_{t+n} \mid S_t=s_0\right] \\ = & \lim _{n \rightarrow \infty} \frac{1}{n} \mathbb{E}\left[\sum_{k=1}^n R_{t+k} \mid S_t=s_0\right] \end{aligned} \] 其中,\(\{(R_{t+1}, R_{t+1}, \ldots)\}\) 是智能体从状态 \(s_0\) 出发基于策略 \(\pi_\theta\) 生成的一个轨迹下的每步奖励。考虑到当 \(n \rightarrow \infty\) 时,起点 \(s_0\) 也失去了意义,所以有: \[ \bar{r}_\pi=\lim _{n \rightarrow \infty} \frac{1}{n} \mathbb{E}\left[\sum_{k=1}^n R_{t+k} \right] \] 需要注意的是,这里的 \(\bar{r}_\pi\) 只考虑即时奖励,因此不含有折扣因子 \(\gamma\)。关于这两个表达形式等价的证明,这里不再展开介绍。
两个指标的联系
两个指标都是关于 \(\theta\) 的函数,因此我们的目标就是去最大化这些指标,这就是策略梯度(Policy Gradient)的基本思路。
直观上看,Average Reward 好像更短视,因为它只关心即时奖励,而 Average Value 关注到整体回报。但可以证明,在含有折扣因子 \(\gamma < 1\) 的情况下,二者等效: \[ \bar{r}_\pi=(1-\gamma)\bar{v}_\pi \] 在优化其中一个指标时,另一个指标也会跟随着优化,并且同时达到极值。
策略梯度 | Policy Gradient
有了目标函数后,为了优化策略,我们需要计算目标函数 \(J(\theta)\) 对策略参数 \(\theta\) 的梯度 —— 这是策略梯度方法中最复杂的一步——因为涉及到不同形式的指标、是否有折扣等等。
目标函数的梯度计算
为了简单起见,这里先给出统一的梯度表达式: \[ \nabla_\theta J(\theta)=\sum_{s \in \mathcal{S}} \eta(s) \sum_{a \in \mathcal{A}} \nabla_\theta \pi(a \mid s, \theta) q_\pi(s, a) \] 其中:
- 目标函数 \(J(\theta)\) 可以是 \(\bar{v}_\pi\),\(\bar{r}_\pi\) 或 \(\bar{v}_\pi^0\);
- 等号「\(=\)」可以是严格相等 \(=\)、约等 \(\simeq\) 或成比例等 \(\propto\),取决于 \(J(\theta)\);
- \(\eta\) 是一个特殊的分布,对于不同的 \(J(\theta)\) 会呈现不同的形式。
具体而言: \[ \begin{gathered} \nabla_\theta \bar{r}_\pi \simeq \sum_s d_\pi(s) \sum_a \nabla_\theta \pi(a \mid s, \theta) q_\pi(s, a), \\ \nabla_\theta \bar{v}_\pi=\frac{1}{1-\gamma} \nabla_\theta \bar{r}_\pi, \\ \nabla_\theta \bar{v}_\pi^0=\sum_{s \in \mathcal{S}} \rho_\pi(s) \sum_{a \in \mathcal{A}} \nabla_\theta \pi(a \mid s, \theta) q_\pi(s, a). \end{gathered} \] 这组公式也被称为策略梯度定理(Policy Gradient Theorem)。它的推导基于对轨迹概率的链式分解,具体证明详见:【策略梯度定理】推导、证明、深入理解与代码实现 - 知乎。
当然最重要的是,\(\nabla_\theta J(\theta)\) 还可以进一步写成期望形式: \[ \begin{aligned} \nabla_\theta J(\theta) & =\sum_{s \in \mathcal{S}} \eta(s) \sum_{a \in \mathcal{A}} \nabla_\theta \pi(a \mid s, \theta) q_\pi(s, a)\\ &=\sum_{s \in \mathcal{S}} \eta(s) \sum_{a \in \mathcal{A}} \pi(a \mid s, \theta) \nabla_\theta \ln \pi(A \mid S;\theta) q_\pi(s, a)\\ &=\mathbb{E}_{S\sim \eta} \left[ \sum_{a \in \mathcal{A}} \pi(a \mid s, \theta) \nabla_\theta \ln \pi(A \mid S;\theta) q_\pi(s, a)\right]\\ &=\mathbb{E}_{S\sim \eta, A \sim \pi} \left[\nabla_\theta \ln \pi(A \mid S;\theta) \cdot q_\pi(S, A)\right]\\ &=\mathbb{E} \left[\nabla_\theta \ln \pi(A \mid S;\theta) \cdot q_\pi(S, A)\right]\\ \end{aligned} \] 其中,\(\ln \pi(a \mid s;\theta)\) 是策略函数的自然对数,这里有一个关键的变形: \[ \nabla_\theta \ln \pi(A \mid S;\theta)=\frac{\nabla_\theta \pi(A \mid S;\theta)}{\pi(A \mid S;\theta)} \] 为什么需要期望形式呢?因为原始表达式中的分布均无法准确计算,而一旦引入期望,我们就能用采样来近似这个值!进而使用随机梯度上升来最大化这个目标。
注意到,当我们想计算 \(\ln \pi(A \mid S;\theta)\),还需要满足 \(\pi(A \mid S;\theta) >0\),因此为了我们需要在神经网络的输出层引入 Softmax 运算,将 \((-\infty,+\infty)\) 映射到 \((0,1)\)。
因此,最终策略 \(\pi\) 会呈现如下形式: \[ \pi(a \mid s; \theta)=\frac{e^{h(a\mid s;\theta)}}{\sum_{a^{\prime} \in \mathcal{A}} e^{h\left(a^{\prime}\mid s;\theta\right)}} \] 其中的 \(h(a\mid s;\theta)\) 就类似上一节介绍的 Feature Function,使用神经网络来自动学习特征。输入 \(s\) 后经过参数为 \(\theta\) 的网络,得到若干个 \(h(a^{\prime}\mid s;\theta)\),再一起映射到 \((0,1)\) 输出。
由于 \(\pi(A \mid S;\theta) >0\),显然此时的策略就是随机性策略,具有较强的探索性。在下一节中我们将介绍 Deterministic Policy Gradient (DPG) 就是确定性策略。
REINFORCE 算法中的近似
在得到梯度的期望形式后,策略梯度方法的最基础实现是 REINFORCE 算法,也称随机梯度策略优化。这是一个基于 Monte-Carlo 方法的策略优化算法,稍后我们将介绍它如何从环境中采样得到的回报来更新策略参数。
首先要明确,策略参数 \(\theta\) 的更新本质上是一个梯度上升(Gradient Ascent)过程,因为我们希望最大化目标函数 \(J(\theta)\),于是有: \[ \begin{aligned} \theta_{t+1} &= \theta_t + \alpha \nabla_\theta J(\theta_t) \\ &= \theta_t + \alpha \mathbb{E} \left[\nabla_\theta \ln \pi(A \mid S;\theta_t) \cdot q_\pi(S, A)\right]\\ \end{aligned} \] 其中涉及到无法获取的期望,于是我们用随机采样来代替: \[ \theta_{t+1} =\theta_t + \alpha \nabla_\theta \ln \pi(a_t \mid s_t;\theta_t) \cdot q_\pi(s_t, a_t) \] 但这个表达式中也涉及到未知的 \(q_\pi\),因此我们还需要将其也近似为 \(q_t(s_t,a_t)\),最简单的办法就是使用蒙特卡洛采样近似,这也是 REINFORCE 最重要的点。
要估计 \(q_\pi(s_t,a_t)\),我们就从 \((s,a)\) 出发得到一个完整 Episode,使用累计奖励回报 \(g_t\) 来近似结果。此外,我们还可以用上时序差分等方法进行估计(例如,之后会介绍的 Actor-Critic 方法)。
策略梯度的物理意义
为了进一步理解 REINFORCE 的优化过程,我们来分析一下策略梯度的物理意义。我们先对更新表达式进一步改写: \[ \begin{aligned} \theta_{t+1} & =\theta_t+\alpha \nabla_\theta \ln \pi\left(a_t \mid s_t; \theta_t\right) q_t\left(s_t, a_t\right) \\ & =\theta_t+\alpha \underbrace{\left(\frac{q_t\left(s_t, a_t\right)}{\pi\left(a_t \mid s_t; \theta_t\right)}\right)}_{\beta_t} \nabla_\theta \pi\left(a_t \mid s_t; \theta_t\right) \end{aligned} \] 使用 \(\beta_t\) 简写后,更新表达式变为: \[ \theta_{t+1} =\theta_t+\alpha \beta_t \nabla_\theta \pi\left(a_t \mid s_t; \theta_t\right) \] 如果将 \(\alpha \beta_t\) 认为是新的更新步长,则这个式子的目标就变成了最大化 \(\pi\left(a_t \mid s_t\right)\)!这个时候大家应该也意识到了,什么时候需要最大化动作 \(a_t\) 在 \(s_t\) 下的发生概率?当且仅当这个动作是好动作的时候!
从微分的视角可以证明:当 \(\beta_t>0\) 且 \(|\alpha \beta_t|\) 充分小的时候,一定有 \(\pi\left(a_t \mid s_t; \theta_{t+1}\right) > \pi\left(a_t \mid s_t; \theta_{t}\right)\);而当 \(\beta_t<0\) 且 \(|\alpha \beta_t|\) 充分小的时候,一定有 \(\pi\left(a_t \mid s_t; \theta_{t+1}\right) < \pi\left(a_t \mid s_t; \theta_{t}\right)\)。
事实上,\(\beta_t\) 可以很好地平衡探索(Exploration)与利用(Exploitation):
- 利用:当分子 \(q_t\left(s_t, a_t\right)\) 越大,\(\beta_t\) 就越大,\(\pi\left(a_t \mid s_t; \theta_{t+1}\right)\) 也就越大,意味着新的策略会将更大的概率分配给已经有较大价值的动作;
- 探索:当分母 \(\pi\left(a_t \mid s_t; \theta_{t}\right)\) 越小,\(\beta_t\) 就越大,\(\pi\left(a_t \mid s_t; \theta_{t+1}\right)\) 也就越大,意味着新的策略会将更大的概率分配给先前选择概率小的动作;
REINFORCE 算法步骤
在实际执行的过程中,我们需要有两次采样,第一次是随机梯度采样的 \((s,a)\),第二次是蒙特卡洛采样的 \(g_t\)。而在采样 \((s,a)\) 的过程中,还有一个分布问题需要解决。
考虑到 \(S\sim d_\pi\),我们需要用稳态分布来获取 \(s\),但实际情况下我们不会太在意这一点。而考虑到 \(A\sim \pi(A\mid, S;\theta)\),我们需要用策略 \(\pi(\theta_t)\) 的分布来获取 \(a\)。所以 Policy Gradient 实际上是一种 On-Policy 算法,其行为策略就是我要改进的目标策略。
当然也有 Off-Policy 的实现形式,但会需要额外的技巧,这将在下一节介绍。
以下是 REINFORCE 的完整算法步骤:
初始化策略参数:设定初始参数 \(\theta\);
蒙特卡洛采样轨迹:根据当前策略 \(\pi_\theta(a \mid s)\) 与环境交互,生成一个轨迹 \(\tau = \{s_0, a_0, r_1, s_1, \dots, s_T\}\);
估计价值和更新策略参数:对轨迹中的每一步,执行:
Value Updata:利用累计奖励回报估计动作价值: \[ q_t\left(s_t, a_t\right) = \sum_{k=t+1}^T \gamma^{k-t-1} r_k \]
Policy Update:利用策略梯度公式更新参数:
\[ \theta_{t+1} =\theta_t + \alpha \nabla_\theta \ln \pi(a_t \mid s_t;\theta) \cdot q_\pi(s_t, a_t) \]
重复:在遍历完一条轨迹后,使用最新策略重复步骤 2 继续采样,直至策略收敛。
看到这里可能大家已经发现了 REINFORCE 的一个提升空间:每次采样都需要生成一个完整轨迹,并且需要将整个轨迹遍历完后才能用最新的策略再采样新的轨迹。而中间在 Policy Update 的时候,尽管 \(\theta_t\) 一直在更新,我们使用的还是旧策略采样的旧轨迹。
显然,我们可以边更新 \(\theta_t\) 边采样新的数据,这就是下一节将要介绍的基于 TD Learning 的策略梯度方法。