Lecture 6: 策略梯度 II —— 基线、方差缩减与 PPO(Policy Gradient II: Baselines, Alternative Targets, and PPO)

目录 · ← l5 · l7 →

Lecture 6: 策略梯度 II —— 基线、方差缩减与 PPO(Policy Gradient II: Baselines, Alternative Targets, and PPO)

对应材料:官方 lecture6pre.pdf(73 页)/ lecture6post.pdf(48 页),另含 lecture5pre.pdf p61–p77 的基线部分|Week 4 周一(Jan 26, 2026)|参考阅读 SB Chp 13;Joshua Achiam, Advanced Policy Gradient 讲义(本讲多数幻灯片取自该讲义并做了微调) 一句话定位:本讲接续 L5 的 REINFORCE,把「似然比策略梯度」从能算推进到能实用:先用基线(baseline)替代目标(alternative targets)把方差压下来,再诊断策略梯度的三大病灶(样本效率、步长敏感、参数距离 ≠ 策略距离),最后引出以信任域(trust region)思想为核心的 PPO(Proximal Policy Optimization)。它是 L7(单调改进理论、TRPO、GAE)的直接铺垫,也是当今 RLHF/大模型对齐的主力算法。


6.1 概述

上一讲(L5)得到了策略梯度定理:$\nabla_\theta J(\theta)=\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(s,a)Q^{\pi_\theta}(s,a)]$,并给出了最朴素的 REINFORCE 更新 $\theta\leftarrow\theta+\alpha\nabla_\theta\log\pi_\theta(s_t,a_t)G_t$。它无偏但方差极大,且每批数据只能做一次梯度更新。

本讲沿讲义第 5 页给出的 Today 大纲分四步走:(1)基线 $b(s)$ 减方差,并证明它不引入偏差(p11–p18,含完整推导与「为什么能降方差」的加权最小二乘论证);(2)替代目标把 $G_t$ 换成 $Q^\pi_w$、$A^\pi_w=Q^\pi_w-V^\pi_w$、TD 残差 $\delta_t$ 或 n-step 回报(p19–p23、p70–p73),引出 Actor-Critic(演员-评论家)(3) 诊断策略梯度的三大问题并建立相对性能界(p26–p41),说明「只优化代理目标 $L_\pi(\pi^{\prime})$ 不够,必须约束 KL」;(4) 给出 PPO 的两个变体——自适应 KL 惩罚裁剪目标(clipped objective)——的公式、伪代码与实现细节(p42–p53)。

在本课程知识链中,本讲是「从梯度上升走向信任域」的转折点:L5 解决「梯度怎么算」,L6 解决「步子该迈多大」,L7 才解决「为什么这样的步子能保证单调改进」。


6.2 核心概念的数学形式化

6.2.1 复习:似然比技巧、得分函数与策略梯度定理

严格定义。设 $\tau=(s_0,a_0,r_0,s_1,\dots)$ 为轨迹,$\rho(\tau)$ 为其概率,策略目标为

\[J(\theta)\doteq\mathbb{E}_{\tau\sim\pi_\theta}\Big[\sum_{t=0}^{\infty}\gamma^t r_t\Big].\]

似然比技巧(likelihood ratio trick / score function trick) 指恒等式

\[\nabla_\theta\pi_\theta(a\vert s)=\pi_\theta(a\vert s)\,\nabla_\theta\log\pi_\theta(a\vert s).\]

其中 $\nabla_\theta\log\pi_\theta(a\vert s)$ 称为得分函数(score function)。L5 的策略梯度定理即

\[\nabla_\theta J(\theta)=\mathbb{E}_{\tau\sim\pi_\theta}\Big[\sum_{t=0}^{\infty}\gamma^t\nabla_\theta\log\pi_\theta(a_t\vert s_t)\,A^{\pi_\theta}(s_t,a_t)\Big],\]

蒙特卡洛策略梯度(REINFORCE) 版本用 $G_t$ 代替 $A^{\pi_\theta}$:

\[\Delta\theta_t=\alpha\,\nabla_\theta\log\pi_\theta(s_t,a_t)\,G_t,\qquad G_t=\sum_{t'=t}^{T-1}r_{t'}.\]

直观解释。得分函数是「在这个状态下把动作 $a$ 的概率往上推」的方向;回报 $G_t$ 是「这一步到底有多好」的权重。两者相乘即:好动作加大概率,坏动作减小概率。这就是「试错学习」的数学化身。

具体示例。讲义 p31 给出一个极小的策略族:$\pi_\theta(a)=\sigma(\theta)$($a=1$)、$1-\sigma(\theta)$($a=2$)。取 $\theta=0$ 时 $\pi=(0.5,0.5)$;$\theta=2$ 时 $\pi=(0.881,0.119)$;$\theta=6$ 时 $\pi=(0.9975,0.0025)$。注意 $\theta$ 从 2 变到 6 只走了 4 个单位的参数距离,但策略已经几乎变成确定性——这正是 p31「参数空间的微小变化可能引起策略空间的巨大变化」的算例。

与监督学习的对比。监督学习里参数距离与函数距离由损失函数的曲率(Hessian)控制;而策略空间是概率单形(simplex) $\Pi=\{\pi:\pi\in\mathbb{R}^{\vert \mathcal{S}\vert \times\vert \mathcal{A}\vert },\sum_a\pi_{sa}=1,\pi_{sa}\ge0\}$(p27),其自然的距离度量是 KL 散度而非欧氏距离。这一差异是本讲全部麻烦的根源。

6.2.2 基线(baseline)与优势函数(advantage function)

严格定义。对任意只依赖状态的函数 $b:\mathcal{S}\to\mathbb{R}$,定义带基线的策略梯度估计器

\[\nabla_\theta\mathbb{E}_\tau[R]=\mathbb{E}_\tau\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi(a_t\vert s_t;\theta)\Big(\sum_{t^{\prime}=t}^{T-1}r_{t^{\prime}}-b(s_t)\Big)\Big].\]

定理(无偏性):对任意 $b(s)$,该估计器的期望与原策略梯度完全相同。

下面给出讲义 p12–p13 的完整推导。先只看单个时刻的基线项:

\[\begin{aligned} \mathbb{E}_\tau\big[\nabla_\theta\log\pi(a_t\|s_t;\theta)\,b(s_t)\big] &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[\mathbb{E}_{s_{t+1:T},\,a_{t:T-1}}\big[\nabla_\theta\log\pi(a_t\|s_t;\theta)b(s_t)\big]\Big] &&\text{(拆开期望)}\\ &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[b(s_t)\,\mathbb{E}_{s_{t+1:T},\,a_{t:T-1}}\big[\nabla_\theta\log\pi(a_t\|s_t;\theta)\big]\Big] &&\text{(基线不依赖后续变量,提出去)}\\ &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[b(s_t)\,\mathbb{E}_{a_t}\big[\nabla_\theta\log\pi(a_t\|s_t;\theta)\big]\Big] &&\text{(删去无关变量)}\\ &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[b(s_t)\sum_a\pi_\theta(a_t\|s_t)\frac{\nabla_\theta\pi(a_t\|s_t;\theta)}{\pi_\theta(a_t\|s_t)}\Big] &&\text{(似然比技巧)}\\ &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[b(s_t)\sum_a\nabla_\theta\pi(a_t\|s_t;\theta)\Big] =\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\Big[b(s_t)\,\nabla_\theta\underbrace{\sum_a\pi(a_t\|s_t;\theta)}_{=1}\Big]\\ &=\mathbb{E}_{s_{0:t},\,a_{0:t-1}}\big[b(s_t)\cdot 0\big]=0. \end{aligned}\]

最后一步的 $\sum_a\pi(a\vert s;\theta)\equiv1$ 是概率归一化的必然结果,其梯度恒为 $0$。因此任何只依赖状态的 $b(s)$ 都不引入偏差——这正是讲义 p11 说的 “For any choice of $b$, gradient estimator is unbiased”。

最常用、也最自然的基线是状态值函数(p18、p23):

\[b(s_t)=V^{\pi_\theta}(s_t)=\mathbb{E}_{a\sim\pi_\theta}\big[Q^{\pi_\theta}(s_t,a)\big],\]

代入后权重变成优势函数(advantage function)

\[A^{\pi}(s,a)\doteq Q^{\pi}(s,a)-V^{\pi}(s),\]

于是得到课程中最常用的梯度形式:

\[\nabla_\theta\mathbb{E}_\tau[R]\approx\mathbb{E}_\tau\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi(a_t\vert s_t;\theta)\,\hat{A}^{\pi}(s_t,a_t)\Big].\]

直观解释。$G_t$ 回答「这一步的回报是多少」,而 $G_t-b(s_t)$ 回答「这一步比在这个状态下通常能拿到的多多少」。讲义 p11 的原话是:把动作 $a_t$ 的 log 概率按回报超出预期的程度成比例增加。用打游戏的类比:场均得分 20 分的选手拿 25 分不值得表扬,而场均 2 分的替补拿 10 分才应该被重点表扬——基线去掉的就是「场均水平」这个公共偏移。

具体示例(本讲实验用的 4 状态网格世界,$\gamma=0.9$,动作 forward/back/reset,滑移概率 0.15,每步 $-0.02$,到达终态 $+1.3$)。取固定策略

\[\pi(\cdot\vert s)=\mathrm{softmax}\big([0.2,-0.3,0.1],[-0.1,0.4,0.0],[0.5,-0.2,-0.4]\big),\]

解析解得 $V^\pi=(0.1035,\,0.2032,\,0.6948,\,0)$,$Q^\pi(0,\cdot)=(0.1494,\,0.0732,\,0.0732)$,故 $A^\pi(0,\cdot)=(+0.0459,\,-0.0304,\,-0.0304)$。也就是说:在状态 0 选择 forward 比平均水平高 $0.0459$,选 back/reset 则低 $0.0304$——策略梯度就会把 forward 的概率往上推。

为什么基线能降方差(讲义 p14–p15)。设 $G_t(s)$ 为从 $(s,a_t)$ 出发的回报,目标是

\[\arg\max_b\operatorname{Var}\big[\nabla_\theta\log\pi(a_t\vert s_t;\theta)(G_t(s)-b(s))\big].\]

由于 $b$ 不影响期望(已证),最小化方差等价于最小化二阶矩:

\[\arg\min_b\;\mathbb{E}\Big[\big(\nabla_\theta\log\pi(a_t\|s_t;\theta)\big)^2\big(G_t(s)-b(s)\big)^2\Big] =\arg\min_b\;\mathbb{E}_{s\sim d^\pi}\Big[\mathbb{E}_{a\sim\pi(\cdot\|s),\,G\|s,a}\big[(\nabla_\theta\log\pi)^2(G_t(s)-b(s))^2\big]\Big].\]

这是一个加权最小二乘(weighted least squares)问题:权重是 $(\nabla_\theta\log\pi)^2$,拟合目标是 $G_t(s)$。求导置零得

\[b^*(s)=\frac{\mathbb{E}_{a\sim\pi(\cdot\vert s),\,G\vert s,a}\big[(\nabla_\theta\log\pi(a_t\vert s;\theta))^2\,G_t(s)\big]}{\mathbb{E}_{a\sim\pi(\cdot\vert s),\,G\vert s,a}\big[(\nabla_\theta\log\pi(a_t\vert s;\theta))^2\big]}\;\approx\;\mathbb{E}_{a\sim\pi(\cdot\vert s),\,G\vert s,a}\big[G_t(s)\big].\]

关键结论:最优基线是「按得分函数平方加权」的回报均值;由于权重与回报只弱相关,用 $\mathbb{E}[G_t]=V^\pi(s)$ 作为基线就近最优,这就是实务中普遍采用 $V^\pi$ 当基线的理论依据。

6.2.3 替代目标 / 不同 critic 目标(alternative targets)

$G_t^{(i)}$ 是从单条轨迹得到的值函数估计(p21):无偏但高方差。讲义明确指出可以用自举(bootstrapping)与函数逼近引入偏差来换方差,这与 L3/L4 中 TD vs MC、值函数逼近的取舍完全同构。

由此得到一族权重(p20、p23):

权重 $w_t$(即 $\hat{A}_t$)公式偏差方差备注
蒙特卡洛回报$G_t$无偏最高REINFORCE;需完整轨迹
减常数基线$G_t-b$无偏$b$ 不改变期望,只削峰
减状态值基线$G_t-V^\pi(s_t)$无偏MC 优势;$V$ 需拟合
真实优势$A^\pi=Q^\pi-V^\pi$无偏最低理论理想值,需精确 critic
TD 残差$\delta_t=r_t+\gamma V(s_{t+1})-V(s_t)$有偏只需一步自举
n-step 优势$\hat{A}^{(n)}t=\sum{l<n}\gamma^l r_{t+l}+\gamma^n V(s_{t+n})-V(s_t)$偏差随 $n$ 递减(前提:critic 误差随状态平滑变化;若 critic 误差近似常数 $e$,则 $\vert \text{bias}\vert =\vert \gamma^n e-e\vert $ 随 $n$ 递增并饱和于 $\vert e\vert $,见 L05 实验 1)方差随 $n$ 递增TD 与 MC 的连续插值

具体示例(实测数字)。在 6.2.2 的网格世界上,固定同一策略、采样 4000 条轨迹,用精确 $V^\pi,Q^\pi$ 计算各估计器(脚本 L06_baseline_variance.py):

权重 $w_t$迹(Var)$\vert \text{bias}\vert $方差比(相对 $G_t$)
$G_t$0.421750.011611.00×
$G_t-b$($b=0.1608$)0.391930.008631.08×
$G_t-V$0.388070.008641.09×
$A=Q-V$0.057140.001977.38×
TD 残差 $\delta_t$0.064080.001986.58×

其中 $\vert \text{bias}\vert $ 列在 4000 次采样下都只有 $10^{-3}$ 量级,说明它们都是无偏的(残差来自蒙特卡洛噪声),方差则相差 7 倍以上。

与监督学习的对比:把 $w_t$ 当作「标签」、$\nabla_\theta\log\pi$ 当作「特征」,整个估计器就是一次加权最小二乘回归——用 $G_t$ 是「真标签但噪声大」,用 $V$ 是「平滑的伪标签但可能有系统误差」,与监督学习中伪标签(pseudo-labeling)的取舍如出一辙。

6.2.4 n-step 回报估计(p70–p73)

讲义 p71 给出n-step 估计器的族:

\[\hat{R}^{(1)}_t=r_t+\gamma V(s_{t+1}),\quad \hat{R}^{(2)}_t=r_t+\gamma r_{t+1}+\gamma^2 V(s_{t+2}),\quad\cdots,\quad \hat{R}^{(\infty)}_t=r_t+\gamma r_{t+1}+\gamma^2r_{t+2}+\cdots\]

减去基线 $V(s_t)$ 即得n-step 优势估计器

\[\hat{A}^{(n)}_t=\sum_{l=0}^{n-1}\gamma^l r_{t+l}+\gamma^n V(s_{t+n})-V(s_t),\]

它是 $V$ 的伸缩求和(telescoping sum);$n=1$ 时退化为 TD 残差 $\delta_t=r_t+\gamma V(s_{t+1})-V(s_t)$,$n\to\infty$ 时退化为 MC 优势 $G_t-V(s_t)$。讲义强调:”critic can select any blend between TD and MC estimators for the target to substitute for the true state-action value function.”

L6N2 快速检查(p72–p73)的答案:讲义给出四个选项——(1) $\hat{A}^{(1)}$ low variance & low bias;(2) $\hat{A}^{(1)}$ high variance & low bias;(3) $\hat{A}^{(\infty)}$ low variance & high bias;(4) $\hat{A}^{(\infty)}$ high variance & low bias。正确答案是 (1) 与 (4)。

推导(critic 精确 $V=V^{\pi_\theta}$ 时):

\[\mathbb{E}\big[\hat{A}^{(1)}_t\big]=\mathbb{E}\big[r_t+\gamma V(s_{t+1})\big]-V(s_t)=Q^{\pi}(s_t,a_t)-V^{\pi}(s_t)=A^{\pi}(s_t,a_t),\]

故 $\hat{A}^{(1)}$ 无偏;同理 $\hat A^{(\infty)}_t=G_t-V(s_t)$ 也无偏。两个含「high bias」的选项((2) 对 $\hat A^{(\infty)}$ 的 low bias 成立但方差判错、以及 (3))由此排除。方差方面:$\hat A^{(1)}$ 只用一步真实奖励,方差;$\hat A^{(\infty)}$ 是整条轨迹 MC 回报之和,方差

本讲 6.4.1 的实验直接印证(critic 换成系统性错误的 $V_{bad}=0.6V$ 时):迹(Var) 从 $n=1$ 的 $0.03497$ 单调升到 $n=\infty$ 的 $0.37449$(约 $10.7$ 倍)——「$n$ 越小方差越小」是硬结论

限定条件:上面的「low bias」以 critic 精确为前提。critic 有系统误差时,$\hat A^{(1)}$ 会把那一步的 $V$ 误差通过自举直接搬进估计,于是偏差变大(同实验实测 $\vert \text{bias}\vert $ 从 $n=1$ 的 $0.10324$ 降到 $n=\infty$ 的 $0.00993$)。所以「$\hat A^{(1)}$ 低方差」无条件成立,偏差则取决于 critic 质量

(说明:讲义 p72–p73 的答案页在 PDF 中只有题干公式,并未标出勾选项;上述判断由定义与本讲实验推出,未逐字抄录讲义答案。)

同样地,p73 的 Solutions 页在 PDF 文本层未标出勾选项,上述判断依据的是这两类估计器的定义与其方差/偏差性质(与 L3 中 TD vs MC 的分析同构),而非逐字抄录讲义答案。

衔接说明:把 n-step 估计器做指数加权平均就得到广义优势估计(Generalized Advantage Estimation, GAE) $\hat{A}^{\mathrm{GAE}(\gamma,\lambda)}t=\sum{l=0}^\infty(\gamma\lambda)^l\delta_{t+l}$,它属于第 7 讲的内容,本讲不展开。

6.2.5 相对性能、性能差异引理与代理目标

性能差异引理(Performance Difference Lemma,p33,CS234 HW2 要求证明):对任意策略 $\pi,\pi^{\prime}$,

\[J(\pi^{\prime})-J(\pi)=\mathbb{E}_{\tau\sim\pi^{\prime}}\Big[\sum_{t=0}^{\infty}\gamma^t A^{\pi}(s_t,a_t)\Big]=\frac{1}{1-\gamma}\mathbb{E}_{\substack{s\sim d^{\pi^{\prime}}\\ a\sim\pi^{\prime}}}\big[A^{\pi}(s,a)\big],\]

其中 $d^{\pi}(s)=(1-\gamma)\sum_{t=0}^{\infty}\gamma^t P(s_t=s\vert \pi)$ 是折扣状态访问分布(discounted state visitation distribution)

直观解释:新策略的增益,等于「在新策略访问到的状态上,用旧策略的优势函数衡量的平均超出量」。好消息是它把 $\pi^{\prime}$ 的性能写成了 $\pi$ 的优势;坏消息(p34)是它仍然需要对 $\pi^{\prime}$ 采样——而我们正想避免为每个候选 $\pi^{\prime}$ 重新采样。

重要性采样视角(p36):把动作分布从 $\pi^{\prime}$ 换成 $\pi$:

\[J(\pi^{\prime})-J(\pi)=\frac{1}{1-\gamma}\mathbb{E}_{s\sim d^{\pi^{\prime}}}\Big[\mathbb{E}_{a\sim\pi}\Big[\frac{\pi^{\prime}(a\vert s)}{\pi(a\vert s)}A^{\pi}(s,a)\Big]\Big].\]

剩下的唯一障碍(p37):状态分布仍是 $s\sim d^{\pi^{\prime}}$。

有用近似(A Useful Approximation,p38、p40):直接令 $d^{\pi^{\prime}}\approx d^{\pi}$,得到代理目标(surrogate objective)

\[L_\pi(\pi')=\frac{1}{1-\gamma}\mathbb{E}_{\substack{s\sim d^{\pi}\\ a\sim\pi}}\Big[\frac{\pi'(a\|s)}{\pi(a\|s)}A^{\pi}(s,a)\Big] =\mathbb{E}_{\tau\sim\pi}\Big[\sum_{t=0}^{\infty}\gamma^t\frac{\pi'(a_t\|s_t)}{\pi(a_t\|s_t)}A^{\pi}(s_t,a_t)\Big].\]

这是本讲最重要的一个式子:它只需要旧策略 $\pi$ 的轨迹,就可以估计新策略 $\pi^{\prime}$ 的相对性能。讲义 p40 特别指出:它「类似重要性采样,但权重只依赖当前时刻(不依赖此前历史),因此不会消失或爆炸」——这与 p68 的完整轨迹重要性采样权重 $\prod_{t^{\prime}=0}^{t}\frac{\pi_\theta(a_{t^{\prime}}\vert s_{t^{\prime}})}{\pi_{\theta^{\prime}}(a_{t^{\prime}}\vert s_{t^{\prime}})}$「许多小差异连乘成大差异」形成鲜明对比。

相对性能界(p38,Achiam, Held, Tamar, Abbeel 2017)

\[\Big\vert J(\pi^{\prime})-\big(J(\pi)+L_\pi(\pi^{\prime})\big)\Big\vert \le C\sqrt{\mathbb{E}_{s\sim d^{\pi}}\big[D_{\mathrm{KL}}\big(\pi^{\prime}\vert \pi\big)[s]\big]}.\]

即:两个策略的 KL 越小,代理目标对真实性能的近似越好

6.2.6 KL 散度(p39)

严格定义:对离散分布 $P,Q$,

\[D_{\mathrm{KL}}(P\|Q)=\sum_x P(x)\log\frac{P(x)}{Q(x)},\qquad D_{\mathrm{KL}}(\pi'\,\|\,\pi)[s]=\sum_{a\in\mathcal{A}}\pi'(a\|s)\log\frac{\pi'(a\|s)}{\pi(a\|s)}.\]

三条性质:$D_{\mathrm{KL}}(P\vert P)=0$;$D_{\mathrm{KL}}(P\vert Q)\ge0$(Gibbs 不等式);$D_{\mathrm{KL}}(P\vert Q)\ne D_{\mathrm{KL}}(Q\vert P)$——不对称。第三条在 PPO 里非常实际:KL 惩罚项里写 $\bar{D}{\mathrm{KL}}(\theta\vert \theta_k)$ 还是 $\bar{D}{\mathrm{KL}}(\theta_k\vert \theta)$ 会得到不同的算法行为。

具体示例:取 $\pi=(0.5,0.5)$、$\pi^{\prime}=(0.9,0.1)$,则 $D_{\mathrm{KL}}(\pi^{\prime}\vert \pi)=0.9\log1.8+0.1\log0.2=0.368$,而 $D_{\mathrm{KL}}(\pi\vert \pi^{\prime})=0.5\log(0.556)+0.5\log5=0.511$——同样的两个分布,方向不同数值差 39%。

6.2.7 PPO 的两个变体(p43–p50)

变体一:自适应 KL 惩罚(Adaptive KL Penalty)。把「约束」变成「惩罚」,解无约束优化问题(约定:全部笔记统一采用 $\bar D_{\mathrm{KL}}(\theta\vert \theta_k)$ 表示「新策略在前、旧策略在后」,即 $D_{\mathrm{KL}}(\pi_\theta\vert \pi_{\theta_k})$;讲义 p43 式 (10) 的写法方向相反,因 KL 非对称,两者在有限步长下行为略有差异,但在一阶近似下($\theta\approx\theta_k$)数值相同):

\[\theta_{k+1}=\arg\max_\theta\;L_{\theta_k}(\theta)-\beta_k\,\bar{D}_{\mathrm{KL}}(\theta\|\theta_k),\qquad \bar{D}_{\mathrm{KL}}(\theta\|\theta_k)=\mathbb{E}_{s\sim d^{\pi_k}}\big[D_{\mathrm{KL}}\big(\pi_\theta(\cdot\|s)\,\big\|\,\pi_{\theta_k}(\cdot\|s)\big)\big].\]

$\beta_k$ 在迭代间自适应($\delta$ 为目标 KL):

\[\beta_{k+1}=\begin{cases}2\beta_k, & \text{若 }\bar{D}_{\mathrm{KL}}(\theta_{k+1}\vert \theta_k)\ge1.5\,\delta\\[2pt] \beta_k/2, & \text{若 }\bar{D}_{\mathrm{KL}}(\theta_{k+1}\vert \theta_k)\le\delta/1.5\\[2pt] \beta_k, & \text{否则}\end{cases}\]

讲义 p44 备注:「初始 KL 惩罚不太重要——它很快就自适应了;某些迭代会违反 KL 约束,但大多数不会。」

变体二:裁剪目标(Clipped Objective)。令概率比(probability ratio)

\[r_t(\theta)=\frac{\pi_\theta(a_t\vert s_t)}{\pi_{\theta_k}(a_t\vert s_t)},\]

\[L^{\mathrm{CLIP}}_{\theta_k}(\theta)=\mathbb{E}_{\tau\sim\pi_k}\Big[\sum_{t=0}^{T}\min\Big(r_t(\theta)\hat{A}^{\pi_k}_t,\;\mathrm{clip}\big(r_t(\theta),1-\epsilon,1+\epsilon\big)\hat{A}^{\pi_k}_t\Big)\Big],\]

其中 $\epsilon$ 是超参数(讲义建议 $\epsilon=0.2$),策略更新为 $\theta_{k+1}=\arg\max_\theta L^{\mathrm{CLIP}}_{\theta_k}(\theta)$。

clip 与 min 的作用(p49、p50):讲义原话是「通过让目标对远离 $\theta_k$ 的性能尽可能悲观」来把策略拉住。分情况看(下面用 $\hat{A}>0$ 与 $\hat{A}<0$ 两栏展开):

情形$r_t$ 范围$\hat{A}_t>0$:$\min$ 取谁$\hat{A}_t<0$:$\min$ 取谁后果
比在界内$1-\epsilon\le r_t\le1+\epsilon$$r_t\hat{A}$$r_t\hat{A}$正常梯度,与原目标一致
比值过小$r_t<1-\epsilon$$r_t\hat{A}$(未截断支)$(1-\epsilon)\hat{A}$(截断支)好动作被降概率时仍惩罚;坏动作被降概率时停止奖励
比值过大$r_t>1+\epsilon$$(1+\epsilon)\hat{A}$(截断支)$r_t\hat{A}$(未截断支)好动作再加概率时停止奖励;坏动作再加概率时仍惩罚

一句话直觉:clip 单向「封顶」了让目标变好的那个方向——$\hat{A}>0$ 时不允许 $r_t$ 超过 $1+\epsilon$ 继续加分;$\hat{A}<0$ 时不允许 $r_t$ 低于 $1-\epsilon$ 继续减分。换句话说,朝着「已经走对了」的方向再迈大步,不再获得额外奖励。而 $\min$ 则保证「反向走错」仍会被惩罚,使目标成为真实性能的悲观下界(pessimistic lower bound)。于是策略没有被推离 $\theta_k$ 的激励

关于两张图的权威归属:讲义 p47–p48 的快速检查问「左图对应 $\hat A>0$ 还是 $\hat A<0$」。这里必须诚实说明:PDF 抽取文本无法还原幻灯片中的图形,两页 Solutions 在文本层与题目页完全相同(同样地,p73 的 L6N2 Solutions 也只重现了公式而未标出勾选项)。因此上面表格给出的划分是依据 $L^{\mathrm{CLIP}}$ 的数学结构推导的结果,与 Schulman et al. (2017) 论文 Fig. 1(该图恰为讲义 p47 所引用)的原始图形一致,而非逐字抄录自讲义答案页。请以推导为准:$\hat A>0$ 时 $\min$ 在 $r_t<1+\epsilon$ 处取 $r_t\hat A$(随 $r$ 上升),$\hat A<0$ 时取 $r_t\hat A$(随 $r$ 下降),二者只在 $r=1$ 处交汇——哪张图上升、哪张图下降由此唯一确定。


6.3 算法伪代码与完整推导

6.3.1 “Vanilla” 策略梯度算法(p16,带基线的通用模板)

Algorithm: "Vanilla" Policy Gradient
Input:  初始策略参数 theta,初始基线 b
for iteration = 1, 2, ... do
    用当前策略执行,收集一批轨迹 {tau^i}
    对每条轨迹 tau^i 的每个时刻 t:
        计算回报        G_t^i = sum_{t'=t}^{T-1} r_{t'}^i
        计算优势估计    Ahat_t^i = G_t^i - b(s_t^i)
    重新拟合基线:最小化 sum_i sum_t | b(s_t^i) - G_t^i |^2
    用策略梯度估计 ghat = sum_i sum_t grad_theta log pi(a_t|s_t;theta) * Ahat_t^i
    把 ghat 交给 SGD / Adam 更新 theta
end for
return theta

算法逻辑解说:这是一个「采样 → 拟合 critic → 估计优势 → 更新 actor」的循环,即 Actor-Critic(演员-评论家) 结构(p22:actor 维护策略,critic 维护值函数,两者同步更新;A3C 是经典代表)。注意基线的拟合与策略的更新是两个独立的回归问题

与理论的对应:$b$ 的最小二乘拟合对应 6.2.2 中 $b^*(s)$ 的加权最小二乘解(权重为常数的退化情形);Ahat 对应 6.2.3 表中的「减状态值基线」一行。

6.3.2 PPO 与自适应 KL 惩罚(p44)

Algorithm: PPO with Adaptive KL Penalty
Input:  初始策略参数 theta_0,初始 KL 惩罚 beta_0,目标 KL 散度 delta
for k = 0, 1, 2, ... do
    在策略 pi_k = pi(theta_k) 上收集部分轨迹集合 D_k
    用任意优势估计方法估计优势 Ahat_t^{pi_k}
    取 K 步 minibatch SGD(用 Adam)求解
        theta_{k+1} = arg max_theta  L_{theta_k}(theta) - beta_k * Dbar_KL(theta || theta_k)
    if Dbar_KL(theta_{k+1} || theta_k) >= 1.5 * delta then
        beta_{k+1} = 2 * beta_k            # 走太远 -> 加大惩罚
    else if Dbar_KL(theta_{k+1} || theta_k) <= delta / 1.5 then
        beta_{k+1} = beta_k / 2            # 走太近 -> 放松惩罚
    end if
end for

算法逻辑解说:内层 $K$ 步 minibatch SGD 是同一批数据被反复使用 $K$ 次,这正是 PPO 相对 vanilla PG 提升样本效率的关键。外层根据实际 KL 用「乘 2 / 除 2」的比例控制(proportional control)调节 $\beta$,使 KL 围绕 $\delta$ 振荡:KL 超了就罚得更狠,KL 不足就罚得更松。这是一个典型的反馈控制回路

6.3.3 PPO 与裁剪目标(p50)

Algorithm: PPO with Clipped Objective
Input:  初始策略参数 theta_0,裁剪阈值 epsilon
for k = 0, 1, 2, ... do
    在策略 pi_k = pi(theta_k) 上收集部分轨迹集合 D_k
    用任意优势估计方法估计优势 Ahat_t^{pi_k}
    取 K 步 minibatch SGD(用 Adam)求解
        theta_{k+1} = arg max_theta  L^CLIP_{theta_k}(theta)
    其中
        L^CLIP_{theta_k}(theta)
          = E_{tau~pi_k} [ sum_t min( r_t(theta) * Ahat_t^{pi_k},
                                     clip(r_t(theta), 1-eps, 1+eps) * Ahat_t^{pi_k} ) ]
        r_t(theta) = pi_theta(a_t|s_t) / pi_{theta_k}(a_t|s_t)
end for

算法逻辑解说:裁剪目标把「自适应调 $\beta$」这件麻烦事换成了一次 clip 运算,因此更容易实现。讲义 p50 总结:「裁剪阻止策略产生远离 $\theta_{k+1}$ 的激励;裁剪效果至少和带 KL 惩罚的 PPO 一样好,但实现更简单。」代价是理论上不如 KL 惩罚干净(clip 不是真正的 KL 约束)。

数学推导:裁剪目标的梯度。令 $u_t=r_t(\theta)\hat{A}_t$,$c_t=\mathrm{clip}(r_t,1-\epsilon,1+\epsilon)\hat{A}_t$,则 $\min(u_t,c_t)$ 对 $\theta$ 的梯度为

\[\nabla_\theta\min(u_t,c_t)=\begin{cases} \hat{A}_t\,\nabla_\theta r_t(\theta), & u_t<c_t\quad\text{(min 取 $r_t\\hat A$ 一支)}\\ 0, & u_t>c_t\quad\text{(min 取常数 $\\mathrm{clip}$ 一支)} \end{cases}\]

其中 $\nabla_\theta r_t(\theta)=r_t(\theta)\nabla_\theta\log\pi_\theta(a_t\vert s_t)$。这正是代码实现的关键:只有「min 取到 $r_t\hat{A}$ 那一支」的样本才贡献梯度,其余样本梯度为 $0$。本讲代码用 active 掩码精确实现了这一点。

与理论的对应:$L^{\mathrm{CLIP}}$ 是 $L_{\theta_k}(\theta)$ 的悲观化版本——在 $L_{\theta_k}$ 可以继续增长的区域把它压平到 $1\pm\epsilon$ 的高度,从而 $\arg\max_\theta L^{\mathrm{CLIP}}$ 的解天然落在 $\theta_k$ 附近。

6.3.4 为什么大更新会破坏策略

策略梯度是随机梯度上升 $\theta_{k+1}=\theta_k+\alpha_k\hat{g}_k$,步长 $\Delta_k=\alpha_k\hat{g}_k$(p29)。问题有三层:

  1. 步子太大 → 性能崩溃(performance collapse):p30 指出「坏的一步可能导致性能崩溃,而且很难恢复」。
  2. 步子太小 → 收敛慢得无法接受;而「正确的步长随 $\theta$ 而变」。Adam 或优势归一化(advantage normalization)能帮上忙,但不能根治(p30 明确发问 “does this solve the problem?”)。
  3. 问题不止是步长(p31):如 6.2.1 的 $\sigma(\theta)$ 例子所示,参数空间的步长与策略空间的变化量之间没有稳定的换算关系

因此正确的目标不是「调好 $\alpha$」,而是换一个把策略空间距离写进目标的更新规则——这就是代理目标 $L_\pi(\pi^{\prime})$($\pi$ 空间的一阶模型)加 KL 约束($\pi$ 空间的信赖域)的来源。讲义 p33 把它概括为:用最近的策略收集的 rollout尽可能高效,并采取「尊重策略空间距离而非参数空间距离」的步长。


6.4 代码实现与实验分析

本讲全部代码在 cs234/code/ 下:L06_baseline_variance.py(基线与替代目标的偏差/方差)、L06_baseline_theory.py(最优基线的解析验证)、L06_ppo.py(PPO 三组实验)。下面嵌入的是它们的最小可运行版本(仅 numpy + 标准库,无 torch/gym)。

6.4.1 实验一:基线如何改变方差(脚本 L06_baseline_variance.py

import numpy as np
np.random.seed(0)

# ---- 4 状态 episodic MDP(3 非终态 + 1 吸收终态),动作 forward/back/reset ----
S, A, GOAL, GAMMA = 4, 3, 3, 0.9
P = np.zeros((S, A, S))
for s in range(3):
    P[s, 0, min(s + 1, GOAL)] += 0.85; P[s, 0, s] += 0.15
    P[s, 1, max(s - 1, 0)] += 0.85;    P[s, 1, s] += 0.15
    P[s, 2, 0] += 1.0
P[GOAL, :, GOAL] = 1.0
R = np.full((S, A), -0.02); R[:, 0] += 1.3 * P[:, 0, GOAL]; R[GOAL, :] = 0.0
MU = np.array([1.0, 0.0, 0.0, 0.0])

def softmax(z):
    z = z - z.max(-1, keepdims=True); e = np.exp(z); return e / e.sum(-1, keepdims=True)

pi = softmax(np.array([[0.2, -0.3, 0.1], [-0.1, 0.4, 0.0], [0.5, -0.2, -0.4]]))

# ---- 解析求 V^pi, Q^pi, A^pi, d^pi 与精确策略梯度 ----
Ppi = np.einsum('sa,san->sn', pi, P[:3]); Rpi = np.einsum('sa,sa->s', pi, R[:3])
V = np.linalg.solve(np.eye(3) - GAMMA * Ppi[:, :3], Rpi)
Vf = np.concatenate([V, [0.0]])
Q = R[:3] + GAMMA * np.einsum('san,n->sa', P[:3], Vf)
Adv = Q - V[:, None]
d = np.linalg.solve(np.eye(3) - GAMMA * Ppi[:, :3].T, MU[:3])
df = np.concatenate([d, [0.0]])
g_star = np.zeros((3, A))
for s in range(3):
    for a in range(A):
        sc = -pi[s].copy(); sc[a] += 1.0
        g_star[s] += df[s] * pi[s, a] * sc * Adv[s, a]
print("V^pi =", np.round(Vf, 4), " A^pi(s=0) =", np.round(Adv[0], 4))
print("精确策略梯度 g* =\n", np.round(g_star, 5), " ||g*||=%.5f" % np.linalg.norm(g_star))

def episode():
    s, ss, aa, rr = 0, [], [], []
    for _ in range(60):
        if s == GOAL: break
        a = np.random.choice(A, p=pi[s]); rr.append(R[s, a]); ss.append(s); aa.append(a)
        s = np.random.choice(S, p=P[s, a])
    return np.array(ss), np.array(aa), np.array(rr)

def returns(rr):
    G = np.zeros(len(rr)); acc = 0.0
    for t in range(len(rr) - 1, -1, -1): acc = rr[t] + GAMMA * acc; G[t] = acc
    return G

def weight(kind, ss, aa, rr, b):
    """返回替代目标里的权重 w_t,也就是 A_hat_t。"""
    G = returns(rr); T = len(rr); s2 = np.concatenate([ss[1:], [GOAL]])
    if kind == "G_t":            return G
    if kind == "G_t - b":        return G - b
    if kind == "G_t - V":        return G - Vf[ss]
    if kind == "A = Q - V":      return Adv[ss, aa]
    if kind == "TD delta":       return rr + GAMMA * Vf[s2] - Vf[ss]
    k = int(kind.split("=")[1])                      # n-step 估计器
    out = np.zeros(T)
    for t in range(T):
        kk = min(k, T - t)
        ret = sum(GAMMA ** l * rr[t + l] for l in range(kk))
        ret += GAMMA ** kk * Vf[ss[t + kk] if t + kk < T else GOAL]
        out[t] = ret - Vf[ss[t]]
    return out

g_pilot = np.concatenate([returns(episode()[2]) for _ in range(400)])
b = float(g_pilot.mean())                       # 用 pilot 数据拟合常数基线
print("pilot 拟合的常数基线 b = %.4f" % b)

kinds = ["G_t", "G_t - b", "G_t - V", "A = Q - V", "TD delta", "n-step=3"]
X = {k: [] for k in kinds}
for _ in range(4000):
    ss, aa, rr = episode()
    if len(rr) == 0: continue
    for k in kinds:
        w = weight(k, ss, aa, rr, b)
        g = np.zeros((3, A))
        for t in range(len(rr)):
            sc = -pi[ss[t]].copy(); sc[aa[t]] += 1.0
            g[ss[t]] += GAMMA ** t * sc * w[t]
        X[k].append(g.ravel())
print("%-12s %12s %12s %10s" % ("权重 w_t", "迹(Var)", "||bias||", "方差比"))
for k in kinds:
    M = np.array(X[k]); bias = M.mean(0) - g_star.ravel(); tr = np.trace(np.cov(M.T))
    print("%-12s %12.5f %12.5f %9.2fx" % (
        k, tr, np.linalg.norm(bias), np.trace(np.cov(np.array(X["G_t"]).T)) / tr))

代码做什么:先在 4 状态网格世界上用线性方程组解析求出 $V^\pi,Q^\pi,A^\pi,d^\pi$ 以及精确策略梯度 $g^\star$(因为状态少,可以精确解 Bellman 方程),然后用 4000 条蒙特卡洛轨迹分别构造 6 种权重 $w_t$,统计每个估计器的偏差 $\vert \mathbb{E}[\hat g]-g^\star\vert $ 与方差 $\operatorname{tr}(\mathrm{Cov}[\hat g])$。

RL 机制透视:这里把「策略梯度估计器」拆成了两部分——方向 $\nabla_\theta\log\pi(a_t\vert s_t)G_t^{t}$(得分函数乘折扣因子)与权重 $w_t$。基线、优势、TD、n-step 的差别只体现在 $w_t$ 上,得分函数部分完全不变;所以这一小节实际是在比较「同一个特征上的不同标签」。用解析 $g^\star$ 当基准,可以真正把「偏差」与「方差」分开测量,而不是只看任务回报间接推断。

实验观察(真实运行输出):

V^pi = [0.1035 0.2032 0.6948 0.    ]  A^pi(s=0) = [ 0.0459 -0.0304 -0.0304]
精确策略梯度 g* =
 [[ 0.10377 -0.04164 -0.06213]
  [ 0.18017 -0.10309 -0.07708]
  [ 0.11677 -0.05579 -0.06098]]  ||g*||=0.29302
pilot 拟合的常数基线 b = 0.1608
权重 w_t             迹(Var)     ||bias||        方差比
G_t               0.42175      0.01161      1.00x
G_t - b           0.39193      0.00863      1.08x
G_t - V           0.38807      0.00864      1.09x
A = Q - V         0.05714      0.00197      7.38x
TD delta          0.06408      0.00198      6.58x
n-step=3          0.16173      0.00556      2.61x

四点值得注意:(1) 表中六种估计器的 $\vert \text{bias}\vert $ 都在 $2\times10^{-3}\sim1.2\times10^{-2}$,相对于 $\vert g^\star\vert =0.293$ 只有 1%–4%,且随采样数增加而趋零——它们都是无偏的,残余差异纯属蒙特卡洛噪声。(2) 方差差异巨大:用真实优势 $A=Q-V$ 作权重把迹方差从 $0.42175$ 降到 $0.05714$,降幅 7.38 倍(3) 有趣的是 $G_t-V$ 只把方差降了 1.09×,远小于 $A=Q-V$ 的 7.38×——因为在本实验中 $G_t$ 的方差主要来自未来的随机性(滑移与终止时刻),而 $V(s_t)$ 这个基线只消掉了状态间的均值差异;真正的方差削减来自「用 $Q$ 代替 $G_t$」这一自举操作。这正好印证了讲义 p21 的论断:减方差要靠 bootstrapping 引入偏差,而基线本身只能消掉有限的一部分(4) 末行 n-step=3 是 $(3)$ 说的极端版本的中间档:它用 $w_t=\sum_{l<3}\gamma^l r_{t+l}+\gamma^3\hat V(s_{t+3})-\hat V(s_t)$ 截断到 3 步,迹方差 $0.16173$(介于 $G_t-V$ 的 $0.38807$ 与 TD delta 的 $0.06408$ 之间),方差比 $2.61\times$。它同时给出了本表最重要的教学信号:截断步数 $n$ 提供了「$n$ 小 ⇒ 依赖 critic、方差小」「$n$ 大 ⇒ 依赖真实奖励、方差大」之间的连续旋钮,而这里的 critic 恰好精确,所以六种估计器全部近似无偏($\vert \text{bias}\vert \le1.2\times10^{-2}$)——这正是下一实验(有偏 critic)要打破的前提。

6.4.2 实验二:PPO 裁剪目标把策略留在信任域内(脚本 L06_ppo.py

import numpy as np
np.random.seed(0)

# --- 1 维网格世界:状态 0..8 非终态,9 为目标;forward/back 有 15% 滑步 ---
S, A, GOAL, GAMMA = 10, 3, 9, 0.99
P = np.zeros((S, A, S))
for s in range(GOAL):
    P[s, 0, min(s + 1, GOAL)] += 0.85; P[s, 0, s] += 0.15
    P[s, 1, max(s - 1, 0)] += 0.85;    P[s, 1, s] += 0.15
    P[s, 2, 0] += 1.0
P[GOAL, :, GOAL] = 1.0
R = np.full((S, A), -0.02); R[:, 0] += 1.3 * P[:, 0, GOAL]; R[GOAL, :] = 0.0

def softmax(z):
    z = z - z.max(-1, keepdims=True); e = np.exp(z); return e / e.sum(-1, keepdims=True)

def rollout(Theta, rng, n, horizon=60):
    """并行采样 n 条轨迹,返回 (S,A,R,mask),形状均为 (n, horizon)。"""
    pi = softmax(Theta)
    Ss = np.zeros((n, horizon), int); As = np.zeros((n, horizon), int)
    Rs = np.zeros((n, horizon));      Mk = np.zeros((n, horizon), bool)
    s = np.zeros(n, int); done = np.zeros(n, bool)
    for t in range(horizon):
        a = np.array([rng.choice(A, p=pi[i]) if not d else 0 for i, d in zip(s, done)])
        s2 = np.array([rng.choice(S, p=P[i, j]) if not d else i for i, j, d in zip(s, a, done)])
        Mk[:, t], Ss[:, t], As[:, t] = ~done, s, a
        Rs[:, t] = np.where(done, 0.0, R[s, a]); s = s2; done = done | (s == GOAL)
        if done.all(): break
    return Ss, As, Rs, Mk

def evaluate(Theta, n=400, seed=999):
    """固定种子评估,保证不同 epoch / 不同方法之间可比。"""
    rng = np.random.default_rng(seed)
    Ss_, As_, Rs_, Mk_ = rollout(Theta, rng, n)
    return float((Rs_ * Mk_).sum(1).mean())

def make_batch(Ss, As, Rs, Mk, Theta, V, k=3):
    """打平成 (s,a,logpi_old,A_hat);优势用 n-step 估计(讲义 p70-p73)。"""
    pi = softmax(Theta); sl, al, ll, dl = [], [], [], []
    for i in range(len(Ss)):
        idx = np.where(Mk[i])[0]
        if not len(idx): continue
        ss, aa, rr = Ss[i, idx], As[i, idx], Rs[i, idx]; L = len(idx)
        for t in range(L):
            kk = min(k, L - t)
            ret = sum(GAMMA ** l * rr[t + l] for l in range(kk))
            ret += GAMMA ** kk * V[ss[t + kk] if t + kk < L else GOAL]
            sl.append(ss[t]); al.append(aa[t])
            ll.append(np.log(max(pi[ss[t], aa[t]], 1e-12))); dl.append(ret - V[ss[t]])
    return map(np.array, (sl, al, ll, np.array(dl, float)))

def fit_V(V, Ss, As, Rs, Mk, beta=0.3):
    """用 MC 回报的滑动平均拟合表格 critic。"""
    sm_, cn_ = np.zeros(S), np.zeros(S)
    for i in range(len(Ss)):
        idx = np.where(Mk[i])[0]
        if not len(idx): continue
        rr = Rs[i, idx]; acc = 0.0; G = np.zeros(len(rr))
        for t in range(len(rr) - 1, -1, -1): acc = rr[t] + GAMMA * acc; G[t] = acc
        for t in range(len(rr)): sm_[Ss[i, idx[t]]] += G[t]; cn_[Ss[i, idx[t]]] += 1
    return V + beta * np.where(cn_ > 0, sm_ / np.maximum(cn_, 1) - V, 0.0)

def adam(p, g, m, v, t, lr):
    m = 0.9 * m + 0.1 * g; v = 0.999 * v + 0.001 * g * g
    return p + lr * (m / (1 - 0.9 ** t)) / (np.sqrt(v / (1 - 0.999 ** t)) + 1e-8), m, v

# --- 用同一批数据重复 40 个 epoch:未裁剪 vs 裁剪 ---
rng = np.random.default_rng(0)
Theta = np.zeros((S, A)); V = np.zeros(S)
Ss, As, Rs, Mk = rollout(Theta, rng, 32)
V = fit_V(V, Ss, As, Rs, Mk)
sb, ab, lp, adv = make_batch(Ss, As, Rs, Mk, Theta, V)
adv = (adv - adv.mean()) / (adv.std() + 1e-8)       # 优势归一化
Theta0 = Theta.copy()
for name, eps in [("none", None), ("clip", 0.2)]:
    T = Theta0.copy(); m = np.zeros_like(T); v = np.zeros_like(T); row = []
    for ep in range(1, 41):
        pi = softmax(T); ratio = np.exp(np.log(np.clip(pi[sb, ab], 1e-12, None)) - lp)
        if eps is None:
            w = ratio                                     # 未裁剪替代目标
        else:
            cl = np.clip(ratio, 1 - eps, 1 + eps)
            act = (((ratio >= 1 - eps) & (ratio <= 1 + eps))
                   | ((ratio < 1 - eps) & (adv > 0))
                   | ((ratio > 1 + eps) & (adv < 0)))
            w = np.where(act, ratio, 0.0)                 # min 取常数支的样本梯度为 0
        sc = -pi[sb]; sc[np.arange(len(sb)), ab] += 1.0   # softmax 的得分函数 = e_a - pi
        g = (sc * (w * adv)[:, None]).mean(0)
        T, m, v = adam(T, g, m, v, ep, 0.05)
        if ep in (5, 10, 20, 40):
            pi = softmax(T); r = np.exp(np.log(np.clip(pi[sb, ab], 1e-12, None)) - lp)
            kl = float(np.mean(np.sum(softmax(Theta0) * np.log(
                np.clip(softmax(Theta0), 1e-12, None) / np.clip(pi, 1e-12, None)), 1)))
            row.append((ep, kl, r.max(), evaluate(T)))
    print("=== %s" % ("未裁剪 (unclipped)" if name == "none" else "裁剪 (eps=0.2)"))
    for e, kl, mx, J in row:
        print("  %3d |   KL=%8.4f  max r_t=%6.3f  J=%7.3f" % (e, kl, mx, J))

代码做什么:先在 10 状态网格世界上采一批 32 条轨迹,用 n-step 优势与优势归一化构造好 $(s,a,\log\pi_{old},\hat A)$,然后冻结这批数据,分别用「未裁剪的替代目标 $r_t\hat A_t$」与「裁剪目标 $\min(r_t\hat A_t,\mathrm{clip}(r_t,1\pm\epsilon)\hat A_t)$」把它反复训练 40 个 epoch(Adam,lr=0.05)。每 5–10 个 epoch 记录三项指标:策略 KL(新旧策略的平均 KL)、$\max_t r_t$(偏离最大样本的比值)、以及固定种子下的评估回报。

RL 机制透视:这段代码精确实现了 6.3.3 的梯度推导——act 掩码就是「min 取到 $r_t\hat{A}$ 那一支」的条件,被 clip 的样本 w=0不产生任何梯度。这是 PPO 与普通策略梯度在实现层面唯一的差别,却带来质的区别:普通策略梯度没有机制阻止 $r_t\to\infty$,而 PPO 让「已经涨到 $1+\epsilon$ 的样本」失去继续贡献梯度的资格。另外注意 Theta0 是初始均匀策略,所有 KL 都相对它计算,因此该列是「策略被推离起点的总距离」。

实验观察(真实运行输出):

=== 未裁剪 (unclipped)
    5 |   KL=  0.0292  max r_t= 1.356  J= -1.163
   10 |   KL=  0.1207  max r_t= 1.732  J= -0.842
   20 |   KL=  0.4712  max r_t= 2.357  J=  0.598
   40 |   KL=  1.2931  max r_t= 2.829  J=  0.981
=== 裁剪 (eps=0.2)
    5 |   KL=  0.0074  max r_t= 1.175  J= -1.191
   10 |   KL=  0.0090  max r_t= 1.183  J= -1.191
   20 |   KL=  0.0129  max r_t= 1.198  J= -1.191
   40 |   KL=  0.0119  max r_t= 1.208  J= -1.191

对比鲜明:未裁剪时 KL 从 $0.0292$ 一路涨到 $1.2931$(增长 44 倍),$\max_t r_t$ 达到 $2.83$,说明策略已被推到离起点很远的地方;裁剪时 KL 始终停在 $0.0074\sim0.0129$(40 个 epoch 后仍只有 0.0119,几乎不随 epoch 增长),$\max_t r_t$ 稳定在 $1.21$ 左右——恰好在 $1+\epsilon=1.2$ 附近,正是 clip 边界。这就是讲义 p49 那句「让目标对远离 $\theta_k$ 的性能尽可能悲观」的数值体现。

需要诚实说明:在这个小任务上裁剪版的最终回报($-1.191$)并不比未裁剪版($0.981$)好——因为未裁剪版虽然越界,但恰好朝正确方向越界了。裁剪的价值不在于「这个小任务上回报更高」,而在于它把步长从「看运气」变成了「有上界」:无论把 epoch 加到多少,KL 都不会失控。在真实的高维深度 RL 中,失控的 KL 正是性能崩溃与训练不稳定的主因(p30、p53)。

6.4.3 补充实验:相对性能界的数值验证(脚本 L06_ppo.py 实验 C)

由于 4/10 状态网格世界的 $V^\pi,Q^\pi,A^\pi,d^\pi$ 都可解析求解,我们可以直接检验讲义 p38 的性能界。沿一个「未裁剪代理目标梯度方向」从 $\theta$ 插值到 $\theta^{\prime}=\theta+\alpha\cdot\text{step}$,用解析公式计算 $L_\pi(\pi^{\prime})$、$J(\pi^{\prime})-J(\pi)$ 与 $\mathrm{KL}$,结果如下(真实运行输出):

   alpha KL(old||new)    L_pi(pi')   J(pi')-J(pi)        |gap|   |gap|/sqrt(KL)
    0.00      0.00000     -0.00000        0.00000      0.00000           0.0000
    0.25      0.00092      0.00668        0.00863      0.00195           0.0641
    0.50      0.00373      0.01353        0.02284      0.00930           0.1524
    1.00      0.01514      0.02763        0.08055      0.05292           0.4301
    1.50      0.03450      0.04209        0.20693      0.16484           0.8875
    2.00      0.06193      0.05667        0.43829      0.38162           1.5335
比值 |gap|/sqrt(KL) 的上确界 = 1.5335,故性能界 (8) 中的常数可取 C ≈ 1.53。

这说明三件事:(1) $\alpha=0$ 时 gap 严格为 $0$,代理目标在 $\pi^{\prime}=\pi$ 处精确(2) 随 KL 增大,gap 单调上升,且 $\vert \text{gap}\vert /\sqrt{\mathrm{KL}}$ 被一致地界定住(本实验里上确界约 $1.53$),与定理形式完全吻合;(3) 有趣的是 $J(\pi^{\prime})-J(\pi)$ 大于 $L_\pi(\pi^{\prime})$(gap 为负),即代理目标是真实性能的保守下界——这正是「最大化代理目标可以保证性能改进」这一论断(L7 的单调改进理论)的数值影子。


6.5 评估指标与理论保证

评估指标(本讲涉及的):

指标定义在本讲中的作用
策略性能 $J(\theta)$$\mathbb{E}{\tau\sim\pi\theta}[\sum_t\gamma^t r_t]$最终目标;用固定种子的评估 rollout 均值估计
梯度估计器方差$\operatorname{tr}(\mathrm{Cov}[\hat g])$衡量基线/替代目标的减方差效果(6.4.1)
梯度估计器偏差$\vert \mathbb{E}[\hat g]-\nabla_\theta J\vert $检验「基线不引入偏差」、n-step 的偏差
平均 KL $\bar D_{\mathrm{KL}}$$\mathbb{E}{s\sim d^{\pi_k}}[D{\mathrm{KL}}(\pi_\theta\vert \pi_{\theta_k})[s]]$PPO-KL 的约束量、$\beta$ 的自适应信号
裁剪比例(clip fraction)满足 $\vert r_t-1\vert >\epsilon$ 的样本占比诊断步长是否过大;经验上以 0.1–0.3 为宜
$\max_t r_t$单样本最大概率比直接暴露「策略被推多远」
样本效率达到目标回报所需的环境交互步数PPO 相对 vanilla PG 的核心优势(多 epoch 复用)

理论保证

  1. 无偏性:对任意 $b:\mathcal{S}\to\mathbb{R}$,$\mathbb{E}\tau[\nabla\theta\log\pi(a_t\vert s_t;\theta)b(s_t)]=0$,故带基线的估计器无偏(p11–p13,完整推导见 6.2.2)。
  2. 方差削减:最优基线 $b^*(s)=\mathbb{E}[(\nabla_\theta\log\pi)^2G_t]/\mathbb{E}[(\nabla_\theta\log\pi)^2]$ 使单步方差最小;实践中用 $b(s)=V^\pi(s)$ 近似该解(p15)。
  3. 性能差异引理:$J(\pi^{\prime})-J(\pi)=\frac{1}{1-\gamma}\mathbb{E}_{s\sim d^{\pi^{\prime}},a\sim\pi^{\prime}}[A^\pi(s,a)]$——精确恒等式,无近似(p33)。
  4. 相对性能界:$\vert J(\pi^{\prime})-J(\pi)-L_\pi(\pi^{\prime})\vert \le C\sqrt{\mathbb{E}{s\sim d^\pi}[D{\mathrm{KL}}(\pi^{\prime}\vert \pi)[s]]}$,其中 $C$ 依赖 $\gamma$ 与奖励上界,$\gamma\to1$ 时 $C$ 很大(p38;6.4.3 实测 $C\approx1.53$)。
  5. PPO 的性质:PPO 不是严格单调改进算法——裁剪目标是真实性能的悲观近似,没有 TRPO 那样的单调改进定理。它「近似地惩罚策略变化」(p43 原文 “approximately penalize policies from changing too much”),保证是经验性的:p50 指出 “Clipping seems to work at least as well as PPO with KL penalty”。完整的单调改进定理与 TRPO 见第 7 讲

条件依赖分析

  • 探索策略:策略梯度是 on-policy 期望,数据必须来自当前(或极近的)策略;PPO 用重要性比 $r_t$ 把「旧策略数据」的可用范围扩展到 $1\pm\epsilon$ 之内。
  • 函数逼近:critic 用线性/表格时偏差可控;用神经网络时 critic 误差会直接进入优势估计,构成 bias(见 6.4.1 中 $G_t-V$ 与 $A=Q-V$ 的对比)。
  • 在线/离线:本讲全部算法都是在线(on-policy);把 PPO 用于离线数据需要额外的重要性采样修正与保守化,超出本讲范围。
  • $\gamma$ 的影响:$\gamma\to1$ 时性能界常数 $C$ 与 $(1-\gamma)^{-1}$ 的量级都会放大,代理目标更不可信,必须把 KL 约束收得更紧。

6.6 与其他讲次的关联

  • 与 L5(Policy Gradient I):L5 给出似然比技巧、得分函数与策略梯度定理,本讲 p9–p10 直接复用 REINFORCE 作为出发点。L5 的结论是「梯度可以无偏估计」,本讲追问「这个估计器好用吗、步子该迈多大」。
  • 与 L3–L4(TD / 值函数逼近 / DQN):本讲 p21 明确把「用 $G_t$ 还是用 $V/Q$ 当目标」类比为 TD vs MC 的取舍(L3),并提供 Actor-Critic 作为「策略梯度 + 值函数逼近」的合体(p22),其 critic 训练完全沿用 L4 的 TD/半梯度方法。
  • 与 L7(Policy Gradient III + Imitation Learning)本讲是本讲与 L7 的桥梁。6.2.5 的性能差异引理与相对性能界是 L7 的出发点;完整的单调改进定理(Monotonic Improvement Theory)、CPI/TRPO 推导,以及把 n-step 估计器做指数加权得到的 GAE,都留给第 7 讲(讲义 lecture6pre p57–p68 与 lecture7pre 前 20 页)。L7 会证明:若 $\pi_{k+1}=\arg\max_{\pi^{\prime}}L_{\pi_k}(\pi^{\prime})-C\sqrt{\mathbb{E}{s\sim d^{\pi_k}}[D{\mathrm{KL}}(\pi^{\prime}\vert \pi_k)[s]]}$,则 $J(\pi_{k+1})\ge J(\pi_k)$;但由于理论给出的 $C$ 在 $\gamma\to1$ 时过大(步长太小),实务上改用 KL 约束(信任域) —— 这正是 PPO 的祖先 TRPO。
  • 与 L8(Imitation Learning / RLHF / DPO):PPO 是 RLHF 阶段最常用的优化器(讲义 p51 原话:”Wildly popular, and key component of ChatGPT”)。本讲的 $L^{\mathrm{CLIP}}$ 与 KL 惩罚,在 L8 中会以「策略模型 + 参考模型 KL 约束」的形式再次出现。
  • 与 L11–L12(Fast RL / 探索):基线里的 $V^\pi$ 与优势函数是「乐观初始化(optimistic initialization)」「RMax」等探索方法的共同语言——它们都需要值函数来量化「哪些状态还没探索够」。

6.7 关键要点

  • 基线零成本:对任意 $b(s)$,$\mathbb{E}[\nabla_\theta\log\pi\cdot b(s)]=0$ 恒成立(因为 $\sum_a\pi(a\vert s)\equiv1$)。所以加基线永远不会引入偏差,是「免费的方差削减」。最优基线是加权最小二乘解 $b^*(s)=\mathbb{E}[(\nabla\log\pi)^2G]/\mathbb{E}[(\nabla\log\pi)^2]$,实践中用 $V^\pi(s)$。
  • 优势是策略梯度的正确权重:$A^\pi(s,a)=Q^\pi(s,a)-V^\pi(s)$ 回答「比这个状态的平均水平好多少」,比原始回报 $G_t$ 的方差小一个量级(本讲实测 7.38×)。
  • 降方差主要靠自举而非基线:基线与 $V$ 只消掉状态间均值差异;真正的方差削减来自用 $Q$/$V$ 代替 $G_t$ 的 bootstrapping(6.4.1 实测 $G_t-V$ 仅降 1.09×,而 $A=Q-V$ 降 7.38×)。
  • 代理目标是本讲的枢纽:$L_\pi(\pi^{\prime})=\mathbb{E}_{\tau\sim\pi}[\sum_t\gamma^t\frac{\pi^{\prime}(a_t\vert s_t)}{\pi(a_t\vert s_t)}A^\pi(s_t,a_t)]$ 只用旧数据就能估计新策略的相对性能,其误差被 KL 一致界定。
  • 参数距离 ≠ 策略距离:$\sigma(\theta)$ 的最简例子说明参数小变化可致策略剧变(p31)。因此「调学习率」不是解法,「用 KL 定义信任域」才是。
  • PPO 用两种方式近似信任域:KL 惩罚(自适应 $\beta$,乘 2/除 2 反馈控制)或直接 clip 概率比(更简单,实测同样把 KL 压在 0.01 量级)。二者都通过多 epoch 复用同一批数据换来样本效率。

6.8 常见误区与注意事项

误区 1:「减去基线相当于引入了偏差,只是用偏差换方差」。 改正:基线不引入任何偏差。讲义 p11 明说 “For any choice of $b$, gradient estimator is unbiased”,p12–p13 的推导显示 $\mathbb{E}[\nabla_\theta\log\pi\cdot b(s)]=b(s)\nabla_\theta\sum_a\pi(a\vert s)=b(s)\cdot0=0$,关键在概率归一化。真正「用偏差换方差」的是自举(TD/n-step/用 $V$ 代替 $G_t$),不是基线本身。本讲实测也印证:$G_t$、$G_t-b$、$G_t-V$ 三者的 $\vert \text{bias}\vert $ 都在 $10^{-2}$ 量级且随样本数趋零。

误区 2(L6N1 快速检查,p2–p3):「$\theta$ 总是沿 $\nabla_\theta\ln\pi(S_t,A_t,\theta)$ 的方向增大」。 改正:命题 2 是错的。更新的方向是 $\nabla_\theta\log\pi\cdot\hat{A}t$,还要乘上 Q 值/回报;若优势为负,$\theta$ 会朝反方向走(降低该动作概率)。本题正确答案是 1 和 3:(1) $\nabla\theta V(\theta)=\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(s,a)Q^{\pi_\theta}(s,a)]$ 成立;(3) 「估计 Q 值更高的状态-动作对的概率平均而言会上升」成立。命题 4 也错:策略梯度只能保证收敛到局部最优,无法保证全局最优(因为 $J(\theta)$ 关于 $\theta$ 非凸)。

误区 3(PPO 快速检查,p47–p48):「$L^{\mathrm{CLIP}}$ 的图形取决于 $\epsilon$,无法判断哪张图对应 $A>0$」。 改正:正确答案是 选项 1左图对应 $\hat A>0$,右图对应 $\hat A<0$(见 6.2.7 的说明:此结论由 $L^{\mathrm{CLIP}}$ 的数学结构推出,与 Schulman et al. 2017 Fig. 1 一致;PDF 文本层无法还原讲义图形)。理由:$\hat A>0$ 时目标随 $r$ 上升、在 $r>1+\epsilon$ 处被削平为常数 $(1+\epsilon)\hat A$;$\hat A<0$ 时目标随 $r$ 下降,在 $r<1-\epsilon$ 处被削平为常数 $(1-\epsilon)\hat A$。两者恰好在 $r=1$ 处交汇于 $\hat A$(此时两条分支都等于 $r\hat A=\hat A$;而不是相交于 0——除非你画的是相对基线 $\hat A$ 的增量 $L^{\mathrm{CLIP}}-\hat A$,那时交点才落在 0,Schulman et al. 2017 Fig. 1 正是画这个增量),且左右两支斜率符号相反。选项 3 是典型干扰项:$\epsilon$ 只决定削平点的位置($1\pm\epsilon$),不改变左右两图的归属

误区 4(L6N2 快速检查,p72–p73):把 $\hat A^{(1)}$ 与 $\hat A^{(\infty)}$ 的方差关系搞反。 改正:正确选项是 (1) $\hat A^{(1)}$ low variance & low bias(4) $\hat A^{(\infty)}$ high variance & low bias(critic 精确时)。最常见的两个错误是:(a) 以为「TD 用了一步奖励、还要乘 $V$ 的估计,所以方差更高」——恰恰相反,$\hat A^{(1)}$ 只依赖一步真实奖励,方差是最低的;$\hat A^{(\infty)}$ 才是 MC 回报、方差最大。本讲实验实测迹(Var) $0.03497\to0.37449$($n=1\to\infty$,约 $10.7$ 倍),方向毫不含糊。(b) 把「偏差」与「方差」的来源混为一谈:$\hat A^{(1)}$ 的低偏差以 critic 精确为前提,critic 有错时它会通过自举把 $V$ 的误差搬进来,偏差反而在 $n$ 小时更大(实测 $\vert \text{bias}\vert $:$n=1$ 为 $0.10324$,$n=\infty$ 为 $0.00993$)。记住这个要点方差的方向无条件($n$ 越大方差越大);偏差的方向取决于 critic 质量。真正兼顾两者的做法是把它们按 $n$(或第 7 讲的 $\lambda$)加权。

误区 5:「PPO 是单调改进算法,所以每次更新性能都不会下降」。 改正:PPO 没有单调改进保证。讲义 p43 用词是 “approximately penalize”,p50 说裁剪 “seems to work at least as well as PPO with KL penalty”——都是经验性陈述。有单调改进定理的是 TRPO/CPI 家族($J(\pi^{\prime})\ge L_\pi(\pi^{\prime})-C\sqrt{\mathbb{E}[D_{\mathrm{KL}}]}$,见 6.5 与 L7),而 PPO 用 clip 或自适应 $\beta$ 近似那一约束。这也是本讲 6.4.2 实验里「裁剪把 KL 压住了但回报并不更高」的原因:PPO 换来的是稳定性与样本效率,不是每次迭代的单调性。

误区 6:「把 $G_t$ 换成 $Q^\pi_w$ 就一定更好,因为 $Q$ 更准」。 改正:换成 $Q^\pi_w$ 是用偏差换方差——只有 critic 准确时才划算。若 $V_w$ 系统性偏差 40%,本讲脚本 L06_baseline_variance.py 的实测显示:$n=1$(TD 残差)的 $\vert \text{bias}\vert =0.10324$,随 $n$ 增大迅速下降并在 $n=5$ 达到最低点 $0.00481$($n=3$ 为 $0.00758$、$n=10$ 为 $0.00541$、$n=\infty$ 回升到 $0.00993$),同时迹方差从 $0.03497$ 单调涨到 $0.37449$。注意偏差并非在 $n=\infty$ 最小——它在中间某个 $n$ 取到最小值后略回升,因为 $n$ 过大时有限时域的截断误差开始显现。也就是说 critic 越差、越应该把 $n$ 调大(更靠近 MC)。这与 L3 中「TD 在 critic 不准时会发散」是同一个道理。

注意事项:实现 PPO 时,讲义 p53 特别引用了 Engstrom 等人的 Implementation Matters in Deep RL (ICLR 2020),指出 奖励缩放(reward scaling)、学习率退火(learning rate annealing) 等看似琐碎的细节会对结果产生显著影响。本讲实验中也可以看到,优势归一化 adv = (adv - adv.mean())/(adv.std()+1e-8) 是不可省略的一步。


6.9 思考题(带答案)

题目 1(推导):证明对任意只依赖状态的基线 $b(s)$,有

\[\mathbb{E}_{a_t\sim\pi_\theta(\cdot\vert s_t)}\big[\nabla_\theta\log\pi_\theta(a_t\vert s_t;\theta)\,b(s_t)\big]=0,\]

并说明「$b$ 可以依赖 $s_t$ 但不能依赖 $a_t$」这一限制为什么必要。

答案:由 $b(s_t)$ 与 $a_t$ 无关,可提出期望:

\[\mathbb{E}_{a_t}\big[\nabla_\theta\log\pi_\theta(a_t\vert s_t;\theta)b(s_t)\big]=b(s_t)\sum_a\pi_\theta(a\vert s_t)\frac{\nabla_\theta\pi_\theta(a\vert s_t;\theta)}{\pi_\theta(a\vert s_t)}=b(s_t)\sum_a\nabla_\theta\pi_\theta(a\vert s_t;\theta)=b(s_t)\nabla_\theta\underbrace{\sum_a\pi_\theta(a\vert s_t;\theta)}_{=1}=0.\]

限制的必要性:若 $b$ 依赖 $a_t$(即 $b(s_t,a_t)$),则不能把 $b$ 提到期望外,得到的是 $\sum_a\pi_\theta(a\vert s_t)\nabla_\theta\log\pi_\theta(a\vert s_t)b(s_t,a)=\sum_a b(s_t,a)\nabla_\theta\pi_\theta(a\vert s_t)$。这一项一般不为零,因为 $\sum_a b(s,a)\nabla_\theta\pi(a\vert s)\ne\nabla_\theta[\sum_a\pi(a\vert s)]$($b$ 也在求导范围内)。例如取 $b(s,a)=Q^\pi(s,a)$,就得到 $\sum_aQ^\pi(s,a)\nabla_\theta\pi(a\vert s)$,这是另一个合法的梯度估计方向(并非零),它对应的是 REINFORCE-with-Q 而不是 baseline 修正。所以「基线」的定义严格限定为只依赖状态的函数。

题目 2(计算):给定单状态 bandit,动作空间 $\mathcal{A}=\{1,2,3\}$,当前策略 $\pi=(0.5,0.3,0.2)$,策略参数为 logits $z$($\pi=\mathrm{softmax}(z)$)。三条轨迹采样得到的回报为 $G(a=1)=1.0$、$G(a=2)=0.0$、$G(a=3)=-1.0$。(a) 写出得分函数 $\nabla_z\log\pi(a)$ 的表达式(对 $a=1$,给出具体数字向量)。(b) 分别计算 $b=0$、$b=0.35$、$b=E[G]$ 三种基线下的单样本梯度估计($a=1$ 被采样),并比较它们的方差(只考虑 $a=1$ 这一步的贡献)。

答案:softmax 的得分函数为 $\nabla_z\log\pi(a)=e_a-\pi$,其中 $e_a$ 是第 $a$ 个基向量。

(a) 对 $a=1$:$\nabla_z\log\pi(1)=e_1-\pi=(1-0.5,\;0-0.3,\;0-0.2)=(0.5,\,-0.3,\,-0.2)$。同理 $\nabla_z\log\pi(2)=(-0.5,0.7,-0.2)$,$\nabla_z\log\pi(3)=(-0.5,-0.3,0.8)$。

(b) $E[G]=0.5\times1.0+0.3\times0.0+0.2\times(-1.0)=0.3$。

  • 用 $b=0$:权重 $w=G=1.0$,梯度估计 $\hat g=(0.5,-0.3,-0.2)$,$\vert \hat g\vert ^2=0.25+0.09+0.04=0.38$。
  • 用 $b=0.35$:$w=1.0-0.35=0.65$,$\hat g=(0.325,-0.195,-0.13)$,$\vert \hat g\vert ^2=0.105625+0.038025+0.0169=0.16055$。
  • 用 $b=E[G]=0.3$:$w=0.7$,$\hat g=(0.35,-0.21,-0.14)$,$\vert \hat g\vert ^2=0.1225+0.0441+0.0196=0.1862$。

三者期望相同(都无偏),但二阶矩从 $0.38$ 降到 $0.16\sim0.19$,方差降幅约 51%–58%关键观察:当 $b=E[G]=0.3$ 时单步权重的绝对值最小($\vert 1.0-0.3\vert =0.7$ 是该动作下相对均值的偏离),若考虑三个动作的加权效果,方差与 $\sum_a\pi_a(G_a-b)^2$ 成正比,在 $b=E[G]$ 附近取到较小的值——这正是「基线消掉状态(这里是 bandit)内公共均值」的机制。更精确的最优 $b^$ 还要按 $(\nabla\log\pi)^2$ 加权,但在这个例子里 $b^$ 与 $E[G]$ 很接近。

题目 3(分析):某实现把 PPO 的 $\epsilon$ 从 $0.2$ 改成 $0.02$,训练日志显示裁剪比例(clip fraction)从 0.15 飙升到 0.85,但最终回报反而下降。请解释这两件事同时发生的机制,并说明该调哪个超参数。

答案:$\epsilon$ 决定信任域半径,它同时影响两件相反的事

(1) 裁剪比例飙升的原因:$\epsilon=0.02$ 意味着只有 $r_t\in[0.98,1.02]$ 的样本能自由贡献梯度。一次 Adam 更新(lr=0.05)之后,很多样本的比值早已越过 $0.02$ 的边界,于是 85% 的样本 w=0、梯度为 0。有效样本量骤降到 15%

(2) 最终回报下降的原因:梯度信号被严重稀疏化。更大的问题是,被裁剪的样本并非随机分布——恰恰是那些「策略变化最大、优势估计最极端」的样本($\vert r_t-1\vert $ 大且 $\vert \hat A_t\vert $ 大)最容易被裁掉,而这些样本本来承载最多的学习信息。剩下的 15% 大多是「没什么可学」的样本,于是更新方向噪声占比上升,学习变慢甚至有偏。这与本讲实验 C 的结论呼应:KL 很小的时候代理目标确实更准,但代理目标本身回到 $L\approx0$、梯度也趋零,什么也学不到。

(3) 该调哪个超参数:不应单纯把 $\epsilon$ 调回 0.2 收工,而应意识到 $\epsilon$ 与内层更新步数 $K$、学习率 $\alpha$ 三者是耦合的。合理的诊断顺序是:先降低学习率(例如 $0.05\to0.01$)或减少 epoch 数($4\to2$),让单次更新走得慢一点,使大多数样本留在 $[1-\epsilon,1+\epsilon]$ 内;再把 $\epsilon$ 设回 $0.1$–$0.2$。经验判据是让 clip fraction 保持在 0.1–0.3 之间:太低说明策略根本没怎么动(浪费了多 epoch 复用),太高说明步长相对信任域过大。本讲 6.4.2 的实验提供了直接证据:$\epsilon=0.2$ 时 40 个 epoch 后 $\max_t r_t$ 稳定在 $1.21$(略高于 $1+\epsilon$),KL 稳定在 $0.012$——恰好是「边界上工作」的健康状态。

题目 4(辨析):有同学说:「PPO 的裁剪目标和 KL 惩罚都只是为了让策略别变太快,那我直接把学习率调小不就完了?」请给出反驳,并引用讲义 p30–p31 的论据。

答案调学习率不能替代信任域约束,理由有三层,均来自讲义。

(1) 问题不止是步长(p31):讲义用一个极简策略族 $\pi_\theta(a)=\sigma(\theta)$ 说明「参数的微小变化可能意外导致策略的巨大变化」。当 $\theta$ 从 2 变到 6(参数距离 4),策略从 $(0.881,0.119)$ 变成 $(0.9975,0.0025)$——几乎完全确定化。同一个 $\alpha$ 在不同的 $\theta$ 处对应的策略变化量完全不同,因为策略对参数的敏感度($\sigma^{\prime}(\theta)=\sigma(1-\sigma)$,在 $\theta$ 大时趋近 0、在 $\theta=0$ 附近最大)随 $\theta$ 变化。

(2) 「正确的」步长随 $\theta$ 变化(p30):讲义原文 “‘Right’ step size changes based on $\theta$”。因此不存在一个全局合适的 $\alpha$:大到能快速学习就会在某些 $\theta$ 处崩溃,小到不会崩溃就会慢得无法接受。Adam、优势归一化等自适应手段「能帮上忙」,但讲义紧接着发问 “But does this solve the problem?”——答案是不能,因为它们仍在参数空间做自适应,而破坏性能的是策略空间的距离。

(3) 信任域直接在策略空间设限:PPO 的 clip 与 KL 惩罚约束的是 $r_t(\theta)$ 与 $\bar D_{\mathrm{KL}}$——这些量直接度量策略空间的距离,与参数化方式无关。无论用 softmax 线性策略还是深度网络,只要 $r_t$ 被压在 $1\pm\epsilon$ 内,策略就没有被推远。本讲 6.4.2 的实验直接验证了这一点:固定一批数据、做 40 个 epoch,未裁剪时 KL 涨到 1.29、$\max_t r_t$ 涨到 2.83;裁剪时 KL 始终在 0.01 附近、$\max_t r_t$ 稳定在 1.21。学习率调得再小,只要 epoch 足够多,未裁剪目标最终仍会把策略推出信任域——只有约束本身才能给出与 epoch 数无关的上界。