Week 11: 策略梯度方法 (Policy Gradient Methods)
回顾:基于价值的强化学习 (Value-Based RL)
到目前为止,我们学习的方法(SARSA, Q-Learning, DQN)都属于基于价值 (Value-Based) 的强化学习方法。
- 核心思想: 学习一个价值函数(通常是动作值函数 \(Q(s, a)\)),然后隐式地从价值函数中推导出策略。
- 策略通常是相对于 Q 函数的贪心策略(或 \(\epsilon\)-greedy):\(\pi(s) = \text{argmax}_a Q(s, a)\)。
- 代表算法: Q-Learning, SARSA, DQN。
- 优点: 在离散动作空间问题上通常样本效率较高,比较稳定。
- 局限性:
- 难以处理连续动作空间: \(max_a Q(s, a)\) 操作在连续动作空间中难以进行(需要在无限多的动作中找到最大值)。虽然有一些扩展方法(如 DDPG),但基本形式不适用。
- 可能学习到确定性策略: 基于
argmax
的策略通常是确定性的。但在某些情况下,最优策略本身就是随机性的(例如,在石头剪刀布游戏中,最优策略是随机出拳;或者在部分可观察环境中,需要随机性来处理不确定性)。基于价值的方法难以直接学习随机策略。 - 价值函数可能非常复杂: 有时,最优价值函数可能比最优策略本身复杂得多,学习价值函数可能比直接学习策略更困难。
为了克服这些局限性,我们需要另一类强化学习方法:策略梯度方法 (Policy Gradient Methods)。
策略梯度方法核心思想:直接学习策略
策略梯度 (Policy Gradient, PG) 方法直接参数化并优化策略本身,而不是通过价值函数间接学习。
- 策略参数化: 我们用一个带参数 \(\theta\) 的函数 \(\pi(a|s, \theta)\) 来表示策略。这个函数直接输出在状态 \(s\) 下采取动作 \(a\) 的概率(对于离散动作)或动作的具体参数(对于连续动作)。
- \(\pi(a|s, \theta) = P(A=a | S=s, \theta)\)
- 参数 \(\theta\) 通常是神经网络的权重。
- 目标: 找到最优的参数 \(\theta\),使得某种性能指标 \(J(\theta)\) 最大化。
- 性能指标 \(J(\theta)\) 通常定义为遵循策略 \(\pi(·|·, \theta)\) 的预期累积回报(例如,从某个起始状态分布开始的预期回报)。
- 优化方法: 使用梯度上升 (Gradient Ascent) 来优化参数 \(\theta\)。我们需要计算性能指标 \(J(\theta)\) 相对于参数 \(\theta\) 的梯度 \(\nabla J(\theta)\),然后沿着梯度的方向更新参数:
- \(\theta \leftarrow \theta + \alpha \nabla J(\theta)\) (\(\alpha\) 是学习率)
关键问题: 如何计算策略性能的梯度 \(\nabla J(\theta)\)?
策略梯度定理 (Policy Gradient Theorem)
我们想通过调整策略的参数 \(\theta\) 来最大化预期回报 \(J(\theta)\)。梯度上升告诉我们,更新方向应该是梯度的方向:\(\theta \leftarrow \theta + \alpha \nabla J(\theta)\)。
那么,核心问题就变成了:这个梯度 \(\nabla J(\theta)\) 究竟是什么?我们如何计算它?
直接计算这个梯度似乎很棘手。因为策略参数 \(\theta\) 的改变,不仅会影响在特定状态下选择某个动作的概率,还会间接影响到我们会进入哪些状态(状态的分布)。想象一下,如果你的策略变了,你可能会更频繁地走到某些奖励高的区域,或者避开某些惩罚多的区域。
幸运的是,策略梯度定理提供了一个非常巧妙(甚至有点神奇)的方法来计算这个梯度,而不需要我们去计算策略变化对状态分布的影响!这极大地简化了问题。
定理告诉我们,性能指标 \(J(\theta)\) 对参数 \(\theta\) 的梯度可以表示为:
\(\nabla J(\theta) \approx E_{\pi_\theta} [ \nabla \log \pi(A_t|S_t, \theta) \cdot \text{RewardSignal}_t ]\)
这里的 \(E_{\pi_\theta}[\cdot]\) 表示在当前策略 \(\pi_\theta\) 下收集的经验的期望。
这是一个非常好的问题,也是策略梯度定理的神奇之处!
我们知道,策略参数 \(\theta\) 的改变会影响两件事:
- 在某个状态 \(s\) 下选择动作 \(a\) 的概率 \(\pi(a|s, \theta)\)。
- 智能体访问到不同状态 \(s\) 的概率分布 \(d^{\pi_\theta}(s)\)(即哪些状态更容易被访问到)。
如果直接对目标函数 \(J(\theta)\) 求导,我们会发现梯度中既包含了对动作选择概率的导数项 \(\nabla_\theta \pi(a|s, \theta)\),也可能包含了对状态分布的导数项 \(\nabla_\theta d^{\pi_\theta}(s)\)。计算后一项(状态分布如何随 \(\theta\) 变化)通常非常复杂和棘手。
策略梯度定理的精妙之处在于,它通过数学推导证明了,在计算策略梯度时,涉及状态分布变化的那部分梯度项最终会相互抵消或者可以被巧妙地重写,从而使得最终的梯度表达式中不再显式地包含状态分布对 \(\theta\) 的导数 \(\nabla_\theta d^{\pi_\theta}(s)\)。
简单来说,定理告诉我们,我们只需要关注:
- 当前策略 \(\pi_\theta\) 下,我们实际采样到的轨迹中,访问了哪些状态 \(S_t\) 并采取了哪些动作 \(A_t\)。
- 对于这些 \((S_t, A_t)\),我们如何调整 \(\theta\) 才能增加那些导致好的结果(高 \(\text{RewardSignal}_t\))的动作的概率,并减少那些导致坏结果的动作的概率。
我们沿着这个计算出来的梯度方向更新 \(\theta\)。在下一次迭代中,由于策略 \(\pi_\theta\) 已经改变,智能体访问状态的分布 \(d^{\pi_\theta}(s)\) 自然也会随之改变。然后,我们会基于这个新的状态分布和新的策略,再次计算梯度。
所以,我们并不是说状态分布不重要或者不改变,而是策略梯度定理提供了一个计算梯度的方法,这个方法在当前这一步的计算中,不需要我们去显式地计算状态分布是如何随着 \(\theta\) 的微小变化而变化的。这极大地简化了梯度的计算,使得直接优化策略成为可能。
更详细的数学证明可以参考 Sutton & Barto 的《强化学习》第二版第 13.1 和 13.2 节,或者原始论文。
策略梯度定理最初由 Richard Sutton 等人在 1999 年的论文《Policy Gradient Methods for Reinforcement Learning with Function Approximation》中提出并证明。
论文核心贡献: 1. 首次严格证明了策略梯度定理的形式 2. 展示了策略梯度方法可以兼容函数近似(如神经网络) 3. 为后续策略梯度算法奠定了理论基础
引用信息: Sutton, R. S., McAllester, D. A., Singh, S. P., & Mansour, Y. (1999). Policy gradient methods for reinforcement learning with function approximation. Advances in neural information processing systems, 12.
论文链接: https://proceedings.neurips.cc/paper/1999/file/464d828b85b0bed98e80ade0a5c43b0f-Paper.pdf
让我们来直观地理解一下这个公式的各个部分:
\(\pi(A_t|S_t, \theta)\): 这是我们的策略。在状态 \(S_t\) 下,根据参数 \(\theta\) 选择动作 \(A_t\) 的概率。
\(\log \pi(A_t|S_t, \theta)\): 对概率取对数。这在数学和计算上有一些方便之处。
\(\nabla \log \pi(A_t|S_t, \theta)\): 这部分通常被称为 Score Function。
- 方向性:它告诉我们,参数 \(\theta\) 应该往哪个方向调整,才能使得动作 \(A_t\) 在状态 \(S_t\) 下被选中的概率增大。
- 可以把它想象成一个”指针”,指向参数空间中能让 \(A_t\) 更可能发生的方向。
\(\text{RewardSignal}_t\): 这是对动作 \(A_t\) 好坏的衡量。
- 这个”奖励信号”告诉我们,在状态 \(S_t\) 执行动作 \(A_t\) 之后,我们最终得到了多少回报。
- 这个信号越好(比如,获得了很高的累积回报),我们就越希望增加 \(A_t\) 的概率。
- 如果信号很差(比如,导致了很低的累积回报),我们就希望减小 \(A_t\) 的概率。
策略梯度定理的两种常见形式,主要区别在于如何定义 \(\text{RewardSignal}_t\):
\(\nabla J(\theta) = E_{\pi_\theta} [ \sum_{t=0}^{T-1} \nabla \log \pi(A_t|S_t, \theta) \cdot G_t ]\)
- 这里的 \(G_t = \sum_{k=t+1}^{T} \gamma^{k-t-1} R_k\) 是从时间步 \(t\) 开始,直到回合结束的完整未来折扣回报。
- 直观理解: 如果在 \(S_t\) 采取的动作 \(A_t\) 最终导致了很高的总回报 \(G_t\),那么我们就沿着 \(\nabla \log \pi(A_t|S_t, \theta)\) 的方向更新 \(\theta\),使得将来在 \(S_t\) 更倾向于选择 \(A_t\)。反之,如果 \(G_t\) 很低,更新就会朝相反方向,降低选择 \(A_t\) 的概率。
- 这是 REINFORCE 算法使用的形式。
\(\nabla J(\theta) = E_{\pi_\theta} [ \nabla \log \pi(A_t|S_t, \theta) \cdot Q^{\pi}(S_t, A_t) ]\)
- 这里的 \(Q^{\pi}(S_t, A_t)\) 是在策略 \(\pi\) 下,在状态 \(S_t\) 执行动作 \(A_t\) 的预期回报。
- 直观理解: 类似地,如果动作 \(A_t\) 的价值 \(Q^{\pi}(S_t, A_t)\) 很高,我们就增加选择它的概率。
- 这种形式在理论上更常见,并且引出了后续很多改进算法,比如 Actor-Critic 方法中会用到对 \(Q^{\pi}(S_t, A_t)\) 的估计。
虽然两种形式看起来相似,但它们在理论和实践上有重要区别:
- 时间尺度不同:
- 形式一 (\(G_t\)) 是蒙特卡洛方法,必须等到回合结束才能计算完整回报
- 形式二 (\(Q^\pi\)) 是时序差分方法,可以即时估计动作价值,实现单步更新
- 方差特性:
- \(G_t\) 包含从当前时刻到回合结束的所有随机性,方差很大
- \(Q^\pi\) 是期望值,已经平均了未来所有可能的轨迹,方差较小
- 实际应用:
- REINFORCE 使用 \(G_t\) 形式,实现简单但收敛慢
- Actor-Critic 方法使用 \(Q^\pi\) 形式,需要额外学习价值函数,但更稳定
- 理论关系:
- \(G_t\) 是 \(Q^\pi(S_t,A_t)\) 的一个无偏但高方差的样本估计
- 当使用函数近似时,\(Q^\pi\) 形式更易于理论分析
总结一下策略梯度定理的直观意义:
我们通过实际运行策略来收集数据。对于收集到的每一个 (状态, 动作)
对,我们看看这个动作最终带来了多大的好处 (RewardSignal)。然后,我们调整策略的参数,使得那些带来好处的动作在相应的状态下更有可能被选中,而那些导致坏结果的动作则更不可能被选中。调整的幅度和方向由 Score Function 和 RewardSignal 共同决定。
这个定理是策略梯度方法能够工作的基石。它告诉我们如何通过可观测和可计算的量来估计策略性能的梯度,从而进行优化。
REINFORCE 算法 (蒙特卡洛策略梯度)
REINFORCE 是最基础的策略梯度算法之一,它直接使用策略梯度定理的第一种形式(使用完整回报 \(G_t\))。它是一种蒙特卡洛 (Monte Carlo) 方法,因为它需要完整的样本回合来计算回报 \(G_t\)。
算法流程:
- 初始化策略网络 \(\pi(a|s, \theta)\) 的参数 \(\theta\)。
- 循环(对于每个回合):
- 使用当前策略 \(\pi(·|·, \theta)\) 与环境交互,生成一个完整的回合: \(S_0, A_0, R_1, S_1, A_1, R_2, ..., S_{T-1}, A_{T-1}, R_T\)。
- 对于回合中的每一步 t = 0, 1, …, T-1:
- 计算从该步开始的未来折扣回报 \(G_t\): \(G_t = \sum_{k=t+1}^T \gamma^{k-t-1} R_k\)。
- 计算 Score Function * 回报: \(\nabla \log \pi(A_t|S_t, \theta) * G_t\)。
- 累加整个回合的梯度信息(或者使用回合中所有步的平均梯度)。
- 更新策略参数 \(\theta\): \(\theta\) ← \(\theta\) + \(\alpha\) * (累加或平均的梯度)。
在REINFORCE算法中,参数更新的频率取决于具体实现方式:
- 经典REINFORCE(如伪代码所示):
- 每个回合结束后,会对该回合中所有步骤计算梯度
- 然后一次性应用这些梯度的总和/平均来更新参数
- 因此是每个回合更新一次参数
- 变体实现:
- 有些实现会为每个步骤单独计算梯度并立即更新(即每步更新)
- 但这样会破坏蒙特卡洛方法的性质,因为后续步骤的决策已经受前步更新影响
- 因此不推荐这种实现方式
- 批量更新优势:
- 回合级更新能保证所有梯度都是在相同策略下计算的
- 避免了”非平稳性”问题(即用不同策略产生的数据来更新当前策略)
- 与蒙特卡洛方法的精神一致:使用完整轨迹信息
- 与TD方法的区别:
- 后续的Actor-Critic方法可以单步更新
- 但REINFORCE作为蒙特卡洛方法,需要回合完整信息
REINFORCE 伪代码:
Initialize policy parameter θ arbitrarily
α ← learning rate
Loop forever (for each episode):
Generate an episode S₀, A₀, R₁, ..., S_{T-1}, A_{T-1}, R_T following π(·|·, θ)
Loop for each step of the episode t = 0, ..., T-1:
G ← Σ_{k=t+1}^T γ^{k-t-1} R_k # Calculate the return from time t
# Update policy parameter θ using stochastic gradient ascent
θ ← θ + α * γ^t * G * ∇ log π(A_t|S_t, θ) # γ^t is sometimes included/omitted
(注意: 伪代码中的 γ^t 因子有时会被包含以强调早期状态的重要性,但更常见的形式是直接使用 G_t)
REINFORCE 的特点:
- 简单: 算法概念相对直接。
- 无偏梯度估计: 使用完整的蒙特卡洛回报 \(G_t\),对梯度的估计是无偏的。
- 高方差 (High Variance): 这是 REINFORCE 的主要缺点。回报 \(G_t\) 依赖于整个回合的随机性,方差很大。这导致梯度估计的方差也很大,使得训练过程不稳定,收敛速度慢,需要大量的样本回合。
- 需要完整回合: 像 MC 方法一样,需要等到回合结束后才能计算 \(G_t\) 并进行更新。
基线 (Baseline) 的作用:减小方差
为了缓解 REINFORCE (以及其他策略梯度方法) 的高方差问题,一个关键的技术是引入基线 (Baseline)。
思想: 从回报 \(G_t\) (或 \(Q_{\pi}(S_t, A_t)\)) 中减去一个不依赖于动作 \(A_t\) 的基线值 \(b(S_t)\),然后再乘以 Score Function。
改进后的梯度估计:
\[\nabla J(\theta) \approx E_{\pi_\theta} [ \nabla \log \pi(A_t|S_t, \theta) * (G_t - b(S_t)) ]\] 或 \[\nabla J(\theta) \approx E_{\pi_\theta} [ \nabla \log \pi(A_t|S_t, \theta) * (Q_{\pi}(S_t, A_t) - b(S_t)) ]\]
可以证明,只要基线 \(b(S_t)\) 不依赖于动作 \(A_t\),减去它不会改变梯度估计的期望值(即梯度仍然是无偏的或近似无偏的)。
通过减去一个基线,我们可以减小 \((G_t - b(S_t))\) 或 \((Q_{\pi}(S_t, A_t) - b(S_t))\) 的方差。
- 直观解释: 我们不再是看动作 \(A_t\) 的绝对回报 \(G_t\) 好不好,而是看它相对于这个状态 \(S_t\) 的平均水平 \(b(S_t)\) 来说好不好。
- 如果 \(G_t > b(S_t)\),说明动作 \(A_t\) 比平均水平好,我们仍然增加其概率。
- 如果 \(G_t < b(S_t)\),说明动作 \(A_t\) 比平均水平差,我们会减小其概率。
- 如果 \(G_t \approx b(S_t)\),说明动作 \(A_t\) 表现平平,梯度接近于 0,参数更新幅度很小。
- 这使得梯度估计更加集中,减少了随机波动带来的噪声,从而加速收敛并提高稳定性。
最常用的基线是状态值函数 \(V_{\pi}(S_t)\)。
\[b(S_t) = V_{\pi}(S_t) = E_{π_θ} [G_t | S_t = s]\]
这时,\(Q_{\pi}(S_t, A_t) - V_{\pi}(S_t)\) 被称为优势函数 (Advantage Function) \(A_{\pi}(S_t, A_t)\)。 \[A_{\pi}(S_t, A_t) = Q_{\pi}(S_t, A_t) - V_{\pi}(S_t)\]
优势函数衡量了在状态 \(S_t\) 采取动作 \(A_t\) 比平均情况下好多少。使用优势函数通常能显著降低策略梯度的方差。
梯度变为: \[\nabla J(\theta) = E_{π_θ} [ \nabla \log \pi(A_t|S_t, \theta) * A_{\pi}(S_t, A_t) ]\]
我们通常也不知道 \(V_{\pi}(S_t)\),所以需要同时学习或估计 \(V_{\pi}(S_t)\) 作为基线。这自然地引出了 Actor-Critic 方法。
策略梯度方法讨论
优势
- 处理连续动作空间: 策略网络可以直接输出连续动作的参数(例如,高斯分布的均值和标准差),这是基于价值的方法难以做到的。
- 学习随机策略: 策略网络可以自然地表示随机策略 \(\pi(a|s, \theta)\),这在某些问题中是必要的。
- 更好的收敛性质 (某些情况下): 尽管方差可能大,但策略梯度方法有时比基于价值的方法具有更好的收敛保证(尤其是在函数逼近下)。
- 可以学习更简单的策略: 有时最优策略可能比最优价值函数简单得多,直接学习策略可能更容易。
劣势
- 高方差: 基本的策略梯度方法(如 REINFORCE)梯度估计方差很大,导致收敛慢、不稳定。需要使用基线、Actor-Critic 等技术来缓解。
- 样本效率通常较低: 相对于 Off-Policy 的 DQN 等方法,On-Policy 的策略梯度方法通常需要更多的样本才能学习。
- 容易收敛到局部最优: 梯度上升可能会陷入局部最优的策略参数。
- 对超参数敏感: 学习率、基线的设计等对性能影响较大。
引出 Actor-Critic
基本的 REINFORCE 算法使用蒙特卡洛方法估计回报 \(G_t\) (或 \(Q_{\pi}\)),导致高方差。引入基线 \(V_{\pi}\) 可以减小方差,但我们又需要估计 \(V_{\pi}\)。
Actor-Critic 方法 正是为了解决这个问题而提出的:
- Actor (行动者): 负责选择动作。它就是我们上面讨论的策略网络 \(\pi(a|s, \theta)\),参数为 \(\theta\)。
- Critic (评论家): 负责评估动作的好坏。它学习一个价值函数(通常是状态值函数 \(V(s, w)\) 或动作值函数 \(Q(s, a, w)\)),参数为 \(w\)。Critic 的输出用于指导 Actor 的更新(例如,作为基线或计算优势函数)。
Actor 和 Critic 同时学习和更新:
- Actor 根据当前策略 \(\pi(·|·, \theta)\) 选择动作 \(A_t\)。
- 执行动作,观察 \(R_{t+1}, S_{t+1}\)。
- Critic 使用 TD 误差等方法更新其价值函数参数 \(w\) (学习如何更好地评估)。
- Actor 使用 Critic 提供的信息(如 TD 误差或优势函数估计)来更新其策略参数 \(\theta\) (学习如何选择更好的动作)。
这种结构结合了策略梯度(Actor 更新)和 TD 学习(Critic 更新)的优点,通常比纯粹的 REINFORCE 或纯粹的价值学习方法更稳定和高效。我们将在下周详细学习 Actor-Critic 方法。
下周预告: Actor-Critic 方法。我们将学习 Actor-Critic 框架,以及具体的 A2C/A3C 算法概念,并使用 Stable Baselines3 运行 A2C 算法。