Lecture 5: 策略梯度 I —— 从值方法到直接策略优化(Policy Gradient I)

目录 · ← l4 · l6 →

Lecture 5: 策略梯度 I —— 从值方法到直接策略优化(Policy Gradient I)

对应材料:官方 lecture5pre.pdf / lecture5post.pdf(pre 78 页、post 61 页)|Week 3 周三 Jan 21, 2026(1/19 为 MLK 假期)|参考阅读 Sutton & Barto 2018 Chp 13.1–13.3;David Silver Lec 7、John Schulman、Pieter Abbeel 讲义 一句话定位:本讲完成从「学值函数、隐式导出策略」到「直接参数化并优化策略」的范式切换,给出似然比/得分函数技巧与策略梯度定理,落地为 REINFORCE,并首次引入基线、优势函数与 Actor-Critic 的雏形。

5.1 概述

前四讲解决的是基于值(value-based)的强化学习(Reinforcement Learning, RL):先估计 $Q^\pi$ 或 $Q^*$,再由值函数隐式地导出策略($\epsilon$-greedy 或 greedy)。本讲转向基于策略(policy-based)的方法:直接用参数 $\theta$ 参数化策略 $\pi_\theta(a\vert s)$,构造策略性能目标 $J(\theta)$,并沿 $\nabla_\theta J(\theta)$ 做梯度上升。

核心技术困难在于:$J(\theta)=\sum_\tau P(\tau;\theta)R(\tau)$ 中转移概率 $P(s^{\prime}\vert s,a)$ 也依赖轨迹分布,看似必须知道模型才能求导。本讲用似然比(likelihood ratio)/ 得分函数(score function)技巧 $\nabla_\theta \pi_\theta(a\vert s)=\pi_\theta(a\vert s)\nabla_\theta\log\pi_\theta(a\vert s)$ 把模型项消掉,得到不需要动力学模型的估计量;再结合时序结构得到 REINFORCE,并用基线(baseline)与 Actor-Critic 控制方差。

本讲同时收尾 L4 的 DQN(经验回放、固定 Q 目标),并用别名网格世界(aliased gridworld)说明值方法的根本局限:在最优点处随机策略严格优于任何确定性策略。这为 L6 的基线完整论证、PPO 与 L7 的单调改进、GAE 埋下伏笔。

5.2 核心概念的数学形式化

5.2.1 从 L4 收尾:值函数逼近下的增量式无模型控制

严格定义。在带函数逼近(function approximation)的无模型控制中,真实 $Q(s_t,a_t)$ 未知,于是用某个目标值(target)替代它,统一写成

\[\Delta w=\alpha\big(\underbrace{\text{target}}_{\text{替代真值 }Q(s_t,a_t)}-\hat{Q}(s_t,a_t;w)\big)\nabla_w\hat{Q}(s_t,a_t;w)\]

四种算法的差别只在于 target 如何取(讲义 p5):

方法target更新式是否自举在线/离线
蒙特卡洛控制(MC control)回报 $G_t$$\Delta w=\alpha(G_t-\hat Q)\nabla_w\hat Q$on-policy
SARSA$r+\gamma\hat Q(s^{\prime},a^{\prime};w)$$\Delta w=\alpha(r+\gamma\hat Q(s^{\prime},a^{\prime};w)-\hat Q)\nabla_w\hat Q$on-policy
Q-learning$r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w)$$\Delta w=\alpha(r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w)-\hat Q)\nabla_w\hat Q$off-policy
DQN$r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w^-)$同上,但 target 用固定旧权重 $w^-$off-policy

其中 $\hat Q(s,a;w)\approx Q^\pi(s,a)$,$\alpha$ 为学习率,$\nabla_w\hat Q$ 是半梯度(semi-gradient)方向。

直观解释。target 就是「我现在认为这一步之后应该值多少」。MC 用实际发生的完整回报,最准但最晚;SARSA/Q-learning 用自己当前的估计去猜未来,学得快但可能自我强化错误。

具体示例。取 4×4 网格世界(左上起点、右下目标、每步 $-0.04$、到达 $+1$、$\gamma=0.95$、10% 滑步),若 $G_t=0.61$ 而 $\hat Q(s_t,a_t;w)=0.50$,则 TD 误差 $=0.11>0$,更新会抬高该 $(s,a)$ 的估计值。

与前序方法对比。表格情形下 Q-learning 收敛到 $Q^*$;一旦叠加函数逼近,Bellman 算子是压缩但「拟合到固定特征表示」这一步可能是扩张,于是如下三要素同时出现时可能振荡甚至发散。

「致命三元组(deadly triad)」:① 自举(bootstrapping,用估计值当目标);② 函数逼近(function approximation);③ 离线策略学习(off-policy,如 Q-learning)。L4 用 Baird 反例说明过这一点。

5.2.2 DQN 的要点回顾

严格定义。DQN(Deep Q-Network)针对「样本相关」与「目标非平稳」两大问题,引入两项机制:

  • 经验回放(experience replay):把 $(s_t,a_t,r_t,s_{t+1})$ 存入回放缓冲区 $\mathcal{D}$,更新时从 $\mathcal{D}$ 中随机采样小批量 $(s,a,r,s^{\prime})\sim\mathcal{D}$,再算 target $r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w)$ 并做 SGD。
  • 固定 Q 目标(fixed Q-targets):另设一组目标网络权重 $w^-$,target 用 $r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w^-)$;每隔 $C$ 步令 $w^-\leftarrow w$。
\[\Delta w=\alpha\big(r+\gamma\max_{a^{\prime}}\hat Q(s^{\prime},a^{\prime};w^-)-\hat Q(s,a;w)\big)\nabla_w\hat Q(s,a;w)\]

直观解释。回放把「连续时间上高度相关的样本」打散成近似独立同分布的小批量,同时让一条经验被反复使用(数据效率);固定目标则把「追着自己尾巴跑」的目标变成一个短期静止的目标,稳定训练。讲义 p20 的消融表显示:回放的作用远大于固定目标

具体示例(讲义 p20 消融实验,各游戏得分):

游戏线性深层网络DQN + 固定 QDQN + 回放DQN + 回放 + 固定 Q
Breakout3310241317
Enduro62291418311006
River Raid23451453286841027447
Seaquest65627510038232894
Space Invaders3013023738261089

与前序方法对比。DQN 仍是值方法:策略由 $\epsilon$-greedy 作用在 $\hat Q$ 上隐式得到,本身没有参数、无法直接优化。

DQN 伪代码(讲义 p13)

算法 Deep Q-Learning(DQN,Mnih et al. 2015)
------------------------------------------------------------
1:  Input: 目标网络更新周期 C, 学习率 α, 回放缓冲区 D = {}
2:  初始化网络权重 w, 目标权重 w⁻ = w, 时间步 t = 0
3:  取初始状态 s_0
4:  loop
5:      用当前 Q̂(s_t, a; w) 的 ε-greedy 策略采样动作 a_t
6:      执行 a_t, 观测奖励 r_t 与下一状态 s_{t+1}
7:      把转移 (s_t, a_t, r_t, s_{t+1}) 存入回放缓冲区 D
8:      从 D 中随机采样一个小批量 (s_i, a_i, r_i, s_{i+1})
9:      for 小批量中的每个 j do
10:         if 第 i+1 步回合终止 then  y_i = r_i
11:         else                       y_i = r_i + γ max_a' Q̂(s_{i+1}, a'; w⁻)
12:         对参数 w 做一步梯度下降: Δw = α (y_i - Q̂(s_i, a_i; w)) ∇_w Q̂(s_i, a_i; w)
13:     end for
14:     t = t + 1
15:     if t mod C == 0 then  w⁻ ← w
16: end loop
------------------------------------------------------------

需注意 DQN 有若干超参数与设计选择:网络结构、学习率、目标网络更新周期 $C$、回放缓冲区大小,以及缓冲区如何填充。

Check Your Understanding(讲义 p14–p15,固定目标):问「用独立的目标权重 $w^-$ 会翻倍计算时间 / 翻倍内存吗?」——答案:只翻倍内存(要额外存一份权重),不翻倍计算时间(每个更新仍只做一次前向与一次反传;目标网络只做前向)。这一题在 5.8 节还会作为误区复现。

「DQN 中哪些部分对成功最关键?」(讲义 p20):消融实验显示经验回放的作用远大于固定目标(见下方表格)。除「打散样本相关性」外,回放还让同一条经验被多次复用,从而显著提升数据效率。

5.2.3 模型无关 RL 阶段总结

讲义 p21 给出「本阶段你应掌握」的清单:能实现策略评估上的 TD(0) 与 MC;能实现 Q-learning 与 MC 控制;能定性说明函数逼近、自举、离线策略三者为何导致不稳定;知道 DQN 的关键组件(经验回放、固定目标)。

5.2.4 为什么需要策略搜索

严格定义。基于值的方法学 $\hat V_w(s)\approx V^\pi(s)$ 或 $\hat Q_w(s,a)\approx Q^\pi(s,a)$,再由值函数导出策略(如 $\epsilon$-greedy);基于策略的方法直接参数化 $\pi_\theta(s,a)=P[a\vert s;\theta]$,目标是最大化 $V^\pi$。二者与 Actor-Critic 的关系(讲义 p25):

类别学值函数?学策略?策略如何产生
基于值(Value Based)隐式($\epsilon$-greedy / greedy)
基于策略(Policy Based)直接参数化并优化
Actor-CriticActor 输出策略,Critic 估计值

直观解释。值方法像「先给每个选项打分,再挑最高的」;策略方法像「直接调旋钮,让好动作更容易被选中」。当动作无限多时,「给每个动作打分再取 max」根本无从下手。

具体示例:别名网格世界(aliased gridworld,讲义 p27–p29)。走廊两端各有一格,特征只有 $\phi(s,a)=\mathbf{1}(\text{北面是墙},a=\text{向东走})$,因此智能体无法区分两个「灰色状态」。此时:

  • 最优确定性策略只能选择「两处都向西」或「两处都向东」,任一选择都会在走廊里来回振荡、永远到不了金币
  • 最优随机策略取 $\pi_\theta(\text{南北皆墙},\text{向东})=0.5$ 且 $\pi_\theta(\text{南北皆墙},\text{向西})=0.5$,则几step内即可高概率抵达目标

与前序方法对比(值方法的四项局限)

  1. 连续/高维动作空间:$\max_a$ 或 $\arg\max_a$ 每步都要解一个优化问题,动作连续时不可行;策略方法直接输出动作分布,天然支持连续控制。
  2. 随机最优策略:值方法学出的是近乎确定的映射(greedy/$\epsilon$-greedy),在部分可观测或特征别名下表达不出最优随机策略(上例);策略方法可表示任意随机策略。
  3. 收敛性:值方法「值函数的微小变化」可能引起策略突变,导致不收敛或振荡;策略方法对 $\theta$ 连续更新,策略平滑变化。
  4. 直接优化目标:值方法优化的是值误差的均方,与「策略性能」并不等价;策略方法直接对 $J(\theta)$ 做梯度上升,优化目标即最终关心的量。

行动空间类型的经验选择:离散小动作空间值方法通常更省样本;连续/高维动作、需要随机策略、或奖励不可微但可采样时,策略方法更合适。

5.3 算法伪代码与完整推导

5.3.1 策略优化目标 $J(\theta)$ 的三种形式

设轨迹(trajectory)$\tau=(s_0,a_0,r_0,\dots,s_{T-1},a_{T-1},r_{T-1},s_T)$,轨迹回报为 $R(\tau)=\sum_{t=0}^{T}R(s_t,a_t)$。可以证明(并不假定 $V^\pi(s_0)=\sum_a\pi_\theta(a\vert s_0)Q(s_0,a,\theta)$)下述三种目标准则的梯度形式相同

\[J_1(\theta)=V^{\pi_\theta}(s_0)=\mathbb{E}_{\tau\sim\pi_\theta}\Big[\sum_{t=0}^{T}\gamma^t r_t\Big]\quad(\text{episodic reward,固定初始状态 } s_0)\] \[J_{avR}(\theta)=\lim_{h\to\infty}\frac{1}{h}\sum_{t=1}^{h}\mathbb{E}[r_t]\quad(\text{average reward per time step})\] \[\frac{1}{1-\gamma}J_{avV}(\theta)=\frac{1}{1-\gamma}\sum_s d^{\pi_\theta}(s)\sum_a\pi_\theta(a\vert s)R(s,a)\quad(\text{average value})\]

其中 $d^{\pi_\theta}(s)=\sum_{t=0}^{\infty}\gamma^t P(s_t=s)$ 是折扣状态访问分布(discounted state visitation distribution)。三者统记为 $J(\theta)$。

直观解释。$J_1$ 关心「从 $s_0$ 出发能拿多少」;$J_{avR}$ 关心「长期稳态下平均每步拿多少」;$J_{avV}$ 是前者的归一化版本。选哪个取决于任务是否跳出「只在 $s_0$ 评估」。

具体示例。在 4×4 网格世界上(起点左上、每步 $-0.04$、目标 $+1$、$\gamma=0.95$),用均匀随机策略时精确计算得 $J_1(\theta)=V^{\pi}(s_0)=-0.4655$;最优策略(有模型值迭代)为 $J^=V^(s_0)=0.5540$。这两个数正是 5.4 节实验的对照基准。

与监督学习对比。监督学习的目标 $\sum_i\log p(y_i\vert x_i;\theta)$ 中数据分布与 $\theta$ 无关;RL 中 $P(\tau;\theta)$ 本身依赖 $\theta$(动作改变、后续状态分布随之改变),这正是梯度难求的根源。

5.3.2 似然比 / 得分函数技巧

把目标写成对轨迹求和的形式,并做恒等变形:

\[\nabla_\theta V(\theta)=\nabla_\theta\sum_\tau P(\tau;\theta)R(\tau)=\sum_\tau P(\tau;\theta)\underbrace{\frac{\nabla_\theta P(\tau;\theta)}{P(\tau;\theta)}}_{\text{likelihood ratio}}R(\tau)=\mathbb{E}_{\tau\sim P}\big[R(\tau)\nabla_\theta\log P(\tau;\theta)\big]\]

关键恒等式为

\[\boxed{\nabla_\theta\pi_\theta(a\vert s)=\pi_\theta(a\vert s)\nabla_\theta\log\pi_\theta(a\vert s)}\]

直观解释。$\nabla_\theta\log p(x;\theta)$ 称为得分函数(score function)——它是「参数化概率/似然取对数后的导数」。它衡量「怎样调 $\theta$ 才能让样本 $x$ 更可能出现」。把样本的「好坏」$R(\tau)$ 乘上去,就等于按质量比例抬高好样本的对数概率

具体示例(得分函数的直觉,讲义 p49)。一般形式 $\hat g_i=f(x_i)\nabla_\theta\log p(x_i\vert \theta)$,其中 $f(x)$ 度量样本 $x$ 有多好。沿 $\hat g_i$ 方向走,会把 $x_i$ 的对数概率按其优劣程度顶上去。该做法不要求 $f(x)$ 可微,$f(x)$ 甚至未知,样本空间也可以是离散集合——这正是策略梯度能直接吃「标量奖励」的原因。

5.3.3 轨迹分解与策略梯度定理(完整推导)

把轨迹概率拆开:

\[P(\tau;\theta)=\underbrace{\mu(s_0)}_{\text{初始状态分布}}\prod_{t=0}^{T-1}\underbrace{\pi_\theta(a_t\vert s_t)}_{\text{策略}}\underbrace{P(s_{t+1}\vert s_t,a_t)}_{\text{动力学模型}}\]

取对数后求梯度,初始分布与动力学项都不含 $\theta$,其导数为零

\[\nabla_\theta\log P(\tau;\theta)=\nabla_\theta\Big[\log\mu(s_0)+\sum_{t=0}^{T-1}\log\pi_\theta(a_t\vert s_t)+\sum_{t=0}^{T-1}\log P(s_{t+1}\vert s_t,a_t)\Big]=\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t)\]

这一步的意义:$\nabla_\theta\log P(\tau;\theta)$ 只留下策略项,不含模型项——因此不需要知道动力学模型。

现在给出策略梯度定理(Policy Gradient Theorem)的讲义版推导。设 $\mu(s_0)$ 为起始分布,$d^{\pi_\theta}(s)$ 为折扣状态访问分布。因为 $J(\theta)=\sum_s d^{\pi_\theta}(s)\sum_a\pi_\theta(a\vert s)Q^{\pi_\theta}(s,a)$ 中访问分布本身依赖 $\theta$,求导会出现麻烦的 $\nabla_\theta d^{\pi_\theta}(s)$ 项:

\[\nabla_\theta J(\theta)=\sum_s\nabla_\theta d^{\pi_\theta}(s)\sum_a\pi_\theta(a\vert s)Q^{\pi_\theta}(s,a)+\sum_s d^{\pi_\theta}(s)\sum_a\nabla_\theta\pi_\theta(a\vert s)Q^{\pi_\theta}(s,a)\]

讲义的处理技巧——对第一项「递归展开」:由 $d^{\pi_\theta}(s^{\prime})=\mu(s^{\prime})+\gamma\sum_s d^{\pi_\theta}(s)\sum_a\pi_\theta(a\vert s)P(s^{\prime}\vert s,a)$,

\[\sum_s\nabla_\theta d^{\pi_\theta}(s)\,v(s)=\gamma\sum_s d^{\pi_\theta}(s)\sum_a\nabla_\theta\pi_\theta(a\vert s)\sum_{s^{\prime}}P(s^{\prime}\vert s,a)\,v(s^{\prime})\]

把这一项代回并利用 $Q^{\pi_\theta}(s,a)=R(s,a)+\gamma\sum_{s^{\prime}}P(s^{\prime}\vert s,a)V^{\pi_\theta}(s^{\prime})$,$\nabla_\theta d$ 项恰好被「吸收」,最终得到不含 $\nabla_\theta d$ 的干净形式

\[\boxed{\ \nabla_\theta J(\theta)=\mathbb{E}_{\pi_\theta}\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t)\,Q^{\pi_\theta}(s_t,a_t)\Big]\ }\]

等价地写作对 $(s,a)$ 的单步期望形式:$\nabla_\theta J(\theta)=\mathbb{E}{\pi\theta}\big[\nabla_\theta\log\pi_\theta(s,a)Q^{\pi_\theta}(s,a)\big]$。定理对 $J_1$、$J_{avR}$、$\frac{1}{1-\gamma}J_{avV}$ 三者中任一个都成立(讲义 p50)。

推导的物理解读:$\nabla_\theta\log\pi_\theta(a\vert s)$ 指出「让 $a$ 更容易被选」的方向,$Q^{\pi_\theta}(s,a)$ 是该动作的真实价值作为权重——沿能提升价值的动作方向前进,与访问分布无关,故不需求 $\nabla_\theta d$。

5.3.4 利用时序结构:从 $R(\tau)$ 到 $G_t$

朴素估计量对整条轨迹用同一个 $R(\tau)$,但 $t$ 时刻的动作不该为「$t$ 之前已发生的奖励」负责。对单个奖励项 $r_{t^{\prime}}$ 重复同样的推导可得(讲义 p53–p55)

\[\nabla_\theta\mathbb{E}[r_{t^{\prime}}]=\mathbb{E}\Big[r_{t^{\prime}}\sum_{t=0}^{t^{\prime}}\nabla_\theta\log\pi_\theta(a_t\vert s_t)\Big]\]

对所有 $t^{\prime}$ 求和并交换求和次序($\sum_{t^{\prime}=0}^{T-1}r_{t^{\prime}}\sum_{t=0}^{t^{\prime}}=\sum_{t=0}^{T-1}\sum_{t^{\prime}=t}^{T-1}r_{t^{\prime}}$),得到

\[\nabla_\theta J(\theta)=\mathbb{E}\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t)\underbrace{\sum_{t^{\prime}=t}^{T-1}r_{t^{\prime}}}_{G_t}\Big]\]

结论:$t$ 时刻的权重从「整条轨迹回报 $R(\tau)$」收紧为「从 $t$ 起的回报 $G_t$」。这不改变期望(仍无偏),但显著降低方差——因为去掉了与 $\nabla_\theta\log\pi_\theta(a_t\vert s_t)$ 无关的过去奖励噪声。

5.3.5 REINFORCE(蒙特卡洛策略梯度)伪代码

算法 REINFORCE(Monte-Carlo Policy Gradient,讲义 p57)
------------------------------------------------------------
输入: 可微策略 π_θ(a|s),步长 α > 0,折扣 γ
输出: 学到的策略参数 θ
1:  任意初始化策略参数 θ
2:  for 每个回合 {s_1,a_1,r_2, ..., s_{T-1},a_{T-1},r_T} ~ π_θ do
3:      计算回报 G_t = Σ_{t'=t}^{T-1} r_{t'}        (或折扣形式 Σ γ^{t'-t} r_{t'})
4:      for t = 1 to T-1 do
5:          θ ← θ + α ∇_θ log π_θ(s_t,a_t) · G_t
6:      end for
7:  end for
8:  return θ
------------------------------------------------------------

算法逻辑解说。① 用当前策略采样一整条回合(on-policy,必须用当前策略产生的数据);② 算每步回报 $G_t$;③ 用 $\alpha\nabla_\theta\log\pi_\theta(a_t\vert s_t)G_t$ 更新。若 $G_t>0$,就抬高 $a_t$ 的对数概率;若 $G_t<0$,就压低。

为什么无偏。因 $\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(a_t\vert s_t)G_t]=\nabla_\theta J(\theta)$(由 5.3.3–5.3.4 的推导),$G_t$ 是 $Q^{\pi_\theta}(s_t,a_t)$ 的无偏蒙特卡洛估计,故整体无偏。代价是方差很大:$G_t$ 是单条轨迹的随机回报,且策略梯度本身就是高方差估计。

$\gamma^t$ 权重的作用。讲义 p57 的更新写作 $\Delta\theta_t=\alpha\nabla_\theta\log\pi_\theta(s_t,a_t)G_t$;在折扣目标下应为 $\theta\leftarrow\theta+\alpha\,\gamma^t\,\nabla_\theta\log\pi_\theta(a_t\vert s_t)G_t$。这个 $\gamma^t$ 不是装饰:它使「早期动作」获得更大权重,因为早期动作影响了后续所有奖励,且与策略梯度定理中 $d^{\pi_\theta}(s)$ 的 $\gamma^t$ 因子对应。5.4 节实验量化了它的作用。

5.3.6 具体策略类的得分函数(讲义 p42–p45)

Softmax 策略(离散动作):用特征线性组合给动作打分,$\phi(s,a)$ 为特征、$\theta$ 为参数,

\[\pi_\theta(s,a)=\frac{e^{\phi(s,a)^\mathsf{T}\theta}}{\sum_{a^{\prime}}e^{\phi(s,a^{\prime})^\mathsf{T}\theta}}\]

其得分函数为(推导见讲义 p43 的 6 步)

\[\nabla_\theta\log\pi_\theta(s,a)=\phi(s,a)-\mathbb{E}_{\pi_\theta}[\phi(s,\cdot)]=\phi(s,a)-\sum_{a^{\prime}}\pi_\theta(a^{\prime}\vert s)\phi(s,a^{\prime})\]

示例。若 $A=3$、$\pi_\theta(\cdot\vert s)=[0.5,0.3,0.2]$,特征 $\phi(s,a_1)=[1,0]$、$\phi(s,a_2)=[0,1]$、$\phi(s,a_3)=[0,0]$,则 $\mathbb{E}{\pi\theta}[\phi(s,\cdot)]=[0.5,0.3]$,于是 $\nabla_\theta\log\pi_\theta(a_1\vert s)=[1,0]-[0.5,0.3]=[0.5,-0.3]$。

Gaussian 策略(连续动作):均值取状态特征的线性组合,方差固定为 $\sigma^2$(也可参数化),

\[a\sim\mathcal{N}(\mu(s),\sigma^2),\qquad \mu(s)=\phi(s)^\mathsf{T}\theta,\qquad \nabla_\theta\log\pi_\theta(s,a)=\frac{(a-\mu(s))\,\phi(s)}{\sigma^2}\]

示例。$\mu(s)=0.18$、$\sigma=0.7$、采样得 $a=0.8$、$\phi(s)=[1,0.1,-0.05,0.4]$,则 $(a-\mu)/\sigma^2=0.62/0.49=1.2653$,得分函数为 $[1.2653,0.1265,-0.0633,0.5061]$。$a$ 比均值大得越多,就越要把 $\mu(s)$ 朝 $a$ 的方向推。

与前序方法对比。连续控制里 Gaussian 策略是自然选择(无界、可微、易采样);深度网络(或其他可微模型)同样可用来表示策略,只需能算 $\nabla_\theta\log\pi_\theta$。

Check Your Understanding(讲义 p47–p48,得分函数):似然比/得分函数策略梯度「(a) 要求奖励函数可微?(b) 只能用于 MDP?(c) 主要用于无限时域任务?」——答案:None of the above(以上皆非)。理由:① 奖励只需是标量,不需可微(见 5.3.2 直觉);② 推导未用到马尔可夫性,POMDP 同样适用;③ 对分段式(episodic)与无限时域都适用。

5.3.7 理想策略梯度算法应有的性质

讲义 p59:目标是尽快收敛到局部最优;由于执行策略本身就在消耗奖励/成本,因此要最小化「达到好策略所需的迭代次数/时间步数」。这直接引出后面两大工程改进:用基线降方差用 critic 替代 MC 回报

Vanilla 策略梯度算法(讲义 p76,含基线)

算法 "Vanilla" Policy Gradient(讲义 p64/p76)
------------------------------------------------------------
输入: 步长,初始策略参数 θ,基线 b
1:  初始化策略参数 θ 与基线 b
2:  for iteration = 1,2,... do
3:      用当前策略执行,收集一组轨迹 {τ^i}
4:      对每条轨迹每个时刻 t: 算回报 G_t^i = Σ_{t'=t}^{T-1} r_{t'}^i
5:         及优势估计 Â_t^i = R_t^(n),i - b(s_t)      (n 步自举,见下)
6:      重新拟合基线: 最小化 Σ_i Σ_t ||b(s_t) - G_t^i||^2
7:      用梯度估计 ĝ = Σ_i Σ_t ∇_θ log π_θ(a_t|s_t) Â_t^i 更新策略
8:        (把 ĝ 交给 SGD 或 Adam)
9:  end for
------------------------------------------------------------

5.3.8 基线:无偏性证明与值函数基线

严格定义。基线(baseline)$b(s)$ 是只依赖状态的函数,用于替换 $G_t$:

\[\nabla_\theta J(\theta)=\mathbb{E}\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t;\theta)\big(G_t-b(s_t)\big)\Big]\]

无偏性证明(讲义 p62–p63)。只要 $b$ 不依赖动作 $a$,就有 $\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(a_t\vert s_t)b(s_t)]=0$:

\[\mathbb{E}_\tau\big[\nabla_\theta\log\pi_\theta(a_t\vert s_t)b(s_t)\big]=\mathbb{E}_{s_0,\dots,s_t}\Big[b(s_t)\sum_a\pi_\theta(a\vert s_t)\frac{\nabla_\theta\pi_\theta(a\vert s_t)}{\pi_\theta(a\vert s_t)}\Big]\] \[=\mathbb{E}_{s_{0:t}}\Big[b(s_t)\sum_a\nabla_\theta\pi_\theta(a\vert s_t)\Big]=\mathbb{E}_{s_{0:t}}\big[b(s_t)\nabla_\theta\underbrace{\textstyle\sum_a\pi_\theta(a\vert s_t)}_{=1}\big]=\mathbb{E}[b(s_t)\cdot 0]=0\]

因此减去任意 $b(s)$ 都不引入偏差

直观解释。$b(s)$ 是「这个状态下我本来预期能拿多少」。减去它后,权重变成「实际回报比预期好多少」:高于预期就抬高概率,低于预期就压低概率。以$b$ 为参照系做「相对比较」,比用绝对回报更稳定。

具体示例。在 4×4 网格世界上用均匀策略,采样回报 $G_0=-0.4513\pm0.3695$(平均是亏的)。若不减基线,几乎所有 $G_t$ 都是负数,于是策略倾向于把所有采样动作都压低——这是「大的共同偏移」。取 $b=\mathbb{E}[G_0]=-0.4513$ 后,权重变成相对量,正负分明。

值函数基线。$V^\pi(s)$ 是很好的基线:

\[Q^\pi(s,a)=\mathbb{E}_\pi[r_0+\gamma r_1+\gamma^2r_2+\cdots\mid s_0=s,a_0=a],\qquad V^\pi(s)=\mathbb{E}_{a\sim\pi}[Q^\pi(s,a)]\]

代入后即得优势函数(advantage function)

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

于是 $\nabla_\theta J(\theta)=\mathbb{E}{\pi\theta}[\sum_t\nabla_\theta\log\pi_\theta(a_t\vert s_t)\hat A^\pi(s_t,a_t)]$,其中 $\hat A$ 由 $G_t-b(s_t)$ 或 $\hat Q(s,a;w)-b(s)$ 估计。

说明:本讲只写到「无偏性 + 值函数基线 + 直觉」。最优基线的完整论证与方差缩减的严格推导留给 L6(讲义 p14–p15 有专门论证)。

5.3.9 Actor-Critic 与目标的选择

严格定义。$G_t$ 是 $V^{\pi_\theta}(s_t)$ 的单次采样估计,无偏但高方差;用自举与函数逼近换入偏差以降低方差(正如 TD 之于 MC)。Actor-Critic 就是「Actor(策略)+ Critic(值函数)」同时维护并更新的方法(如 A3C,Mnih et al. ICML 2016)。讲义 p71 给出把梯度写成优势形式:

\[\nabla_\theta\mathbb{E}_\tau[R]\approx\mathbb{E}_\tau\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t;\theta)\big(Q(s_t,a_t;w)-b(s_t)\big)\Big]\]

n 步目标(讲义 p72–p73)。critic 可在 TD 与 MC 之间任选混合:

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

减去基线即得优势估计器:$\hat A_t^{(1)}=r_t+\gamma V(s_{t+1})-V(s_t)$,$\hat A_t^{(\infty)}=r_t+\gamma r_{t+1}+\gamma^2r_{t+2}+\cdots-V(s_t)$。

Check Your Understanding(讲义 p74–p75,混合优势估计器):$\hat A_t^{(1)}$ 与 $\hat A_t^{(\infty)}$ 的偏差-方差如何?讲义 p74 给出四个选项:(1) $\hat A_t^{(1)}$ 低方差&低偏差;(2) $\hat A_t^{(1)}$ 高方差&低偏差;(3) $\hat A_t^{(\infty)}$ 低方差&高偏差;(4) $\hat A_t^{(\infty)}$ 高方差&低偏差。

正确答案是 (1) 与 (4)。 推导:在 critic 精确($V=V^{\pi_\theta}$)时

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

即 $\hat A_t^{(1)}$ 无偏;而 $\hat A_t^{(\infty)}=G_t-V(s_t)$ 同样无偏。所以两者都是低偏差,(2)、(3) 立即排除。剩下的差别在方差:$\hat A_t^{(1)}$ 只用一步真实奖励加一次自举,方差;$\hat A_t^{(\infty)}$ 是整条轨迹的随机回报之和,方差。故 (1)、(4) 成立。

本讲 5.4 节实验 1 提供数值证据(配对 4000 条轨迹):标准差从 $n=1$ 的 $0.0445$ 单调增到 $n=\infty$ 的 $0.3790$(约 $8.5$ 倍)——方差随 $n$ 单调增大是这张表的硬结论,也正是「$\hat A_t^{(1)}$ 方差低」的直接证据。

重要限定:上面「低偏差」的前提是 critic 精确。一旦 critic 有系统误差,$\hat A_t^{(1)}$ 会通过自举把那一步的 $V$ 误差直接搬进估计里,于是产生偏差——这正是实验 1 中 critic 故意不准($\hat V(s_0)=-0.6177$ vs 精确 $-0.4655$)时偏差随 $n$ 变化的原因。所以「$\hat A_t^{(1)}$ 低方差」在所有情形下都成立,而「低偏差 vs 高偏差」取决于 critic 质量——这是本讲最容易被选项字面误导的一题。

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

折扣一致性(discount factor 与 actor/critic 一致性)。策略梯度定理中的 $Q^{\pi_\theta}$ 与目标 $J$ 必须共享同一个 $\gamma$;若 actor 用 $\gamma=0.95$ 而 critic 目标用 $\gamma_c=0.50$,critic 估计的就不是策略真正在优化的那个 $Q$,梯度方向会系统性偏斜。5.4 节实验 2 给出数值证据:$\gamma_c=0.50$ 时 $J$ 从 $0.35$ 崩到 $0.012$。

n 步目标与基线的关系:n 步目标 $\hat R_t^{(n)}$ 本身是无偏的(只要 critic 准确),减去 $b(s_t)=V(s_t)$ 不改变期望,但能大幅压低梯度更新的量级与方差。

5.3.10 策略方法的收益总结(讲义 p77)

优点:① 更好的收敛性质;② 在高维或连续动作空间有效;③ 能学随机策略缺点:① 通常收敛到局部最优而非全局最优;② 策略评估效率低、方差大(基线与时序结构可缓解)。

5.4 代码实现与实验分析

以下两个代码块均可独立复制运行(纯 NumPy + 标准库;无 torch/gym/scipy;实测分别约 7 秒与 23 秒)。共用环境为 4×4 网格世界:起点左上、目标右下、每步 $-0.04$、到达 $+1$、10% 滑步、$\gamma=0.95$、无截断(最大 200 步)。有模型精确评估给出两个基准:$J^=V^(s_0)=0.5540$(值迭代)与 $J(\text{random})=-0.4655$(均匀随机策略)。

工作目录另附两个更完整的实验脚本:cs234/code/L05_reinforce.py(含第 5.4.1 节全部实验:无偏性 $z$ 值检验、$\gamma^t$ 作用、基线质量消融、单次更新演示、12 种子训练)与 cs234/code/L05_actor_critic.py(含 5.4.2 节全部实验:高斯得分函数有限差分检验、偏差-方差表、折扣一致性、基线梯度量级)。本节各表数据均由这两个脚本真实运行得到;嵌入式代码块是它们的最小自包含复现,关键数值与完整脚本一致。

5.4.1 Softmax 策略的 REINFORCE:无偏性、$\gamma^t$、基线与 Actor-Critic

"""代码块 A:GridWorld 上的 REINFORCE(无基线 / 常数基线 / V(s) 基线)——完整可运行。"""
import numpy as np

np.random.seed(0)

class GridWorld:
    ACTIONS = [(-1, 0), (0, 1), (1, 0), (0, -1)]     # 上, 右, 下, 左

    def __init__(self, n=4, slip=0.1, step_reward=-0.04,
                 goal_reward=1.0, gamma=0.95, max_steps=200):
        self.n, self.slip = n, slip
        self.step_reward, self.goal_reward = step_reward, goal_reward
        self.gamma, self.max_steps = gamma, max_steps
        self.start, self.goal = (0, 0), (n - 1, n - 1)
        self.S, self.A, self.goal_idx = n * n, 4, n * n - 1

    def reset(self):
        self.rc, self.t = self.start, 0
        return self.rc[0] * self.n + self.rc[1]

    def step(self, a):
        if np.random.rand() < self.slip:
            a = np.random.randint(self.A)
        dr, dc = self.ACTIONS[a]
        self.rc = (min(max(self.rc[0] + dr, 0), self.n - 1),
                   min(max(self.rc[1] + dc, 0), self.n - 1))
        self.t += 1
        s = self.rc[0] * self.n + self.rc[1]
        if self.rc == self.goal:
            return s, self.goal_reward, True
        return s, self.step_reward, self.t >= self.max_steps

    def trans(self, s, a):
        rc = (s // self.n, s % self.n)
        out = {}
        for a2 in range(self.A):
            w = (1.0 - self.slip if a2 == a else 0.0) + self.slip / self.A
            dr, dc = self.ACTIONS[a2]
            nr = min(max(rc[0] + dr, 0), self.n - 1)
            nc = min(max(rc[1] + dc, 0), self.n - 1)
            ns = nr * self.n + nc
            r = self.goal_reward if ns == self.goal_idx else self.step_reward
            out[ns] = (out.get(ns, (0.0, 0.0))[0] + w, r)
        return [(ns, w, r) for ns, (w, r) in out.items()]


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


def score(theta, s, a):
    """score function: grad_theta log pi_theta(a|s) = e_a - pi(.|s)"""
    p = softmax(theta[s])
    g = -p.copy()
    g[a] += 1.0
    return g


def rollout(env, theta):
    s, done = env.reset(), False
    S, A, R = [], [], []
    while not done:
        a = np.random.choice(env.A, p=softmax(theta[s]))
        ns, r, done = env.step(a)
        S.append(s); A.append(a); R.append(r); s = ns
    return np.array(S), np.array(A), np.array(R)


def returns_to_go(R, gamma):
    G, acc = np.zeros(len(R)), 0.0
    for t in range(len(R) - 1, -1, -1):          # G_t = r_t + gamma * G_{t+1}
        acc = R[t] + gamma * acc
        G[t] = acc
    return G


def train(method, n_episodes=300, alpha=0.5, alpha_v=0.4, seed=0):
    """method: 'none'=无基线, 'const'=常数基线 E[G_0], 'Vs'=逐状态 V(s) 基线。"""
    np.random.seed(seed)
    env = GridWorld()
    theta = np.zeros((env.S, env.A))
    V = np.zeros(env.S)
    b_const = 0.0
    for ep in range(n_episodes):
        S, A, R = rollout(env, theta)
        G = returns_to_go(R, env.gamma)
        w = env.gamma ** np.arange(len(R))                # gamma^t 权重
        if method == "none":
            b = np.zeros(env.S)
        elif method == "const":
            b = np.full(env.S, b_const)
        else:
            b = V
        for t in range(len(R)):
            theta[S[t]] += alpha * w[t] * (G[t] - b[S[t]]) * score(theta, S[t], A[t])
        if method == "const":
            b_const += 0.05 * (G[0] - b_const)            # 滑动估计 E[G_0]
        if method == "Vs":
            for t in range(len(R)):
                V[S[t]] += alpha_v * (G[t] - V[S[t]])
    return theta, env


def policy_value(env, theta):
    """有模型精确策略评估:V^{pi} = (I - gamma P_pi)^{-1} r_pi,返回 V(s0)。"""
    pi = softmax(theta)
    P, r = np.zeros((env.S, env.S)), np.zeros(env.S)
    for s in range(env.S):
        if s == env.goal_idx:
            continue
        for a in range(env.A):
            for ns, w, rr in env.trans(s, a):
                P[s, ns] += pi[s, a] * w
                r[s] += pi[s, a] * w * rr
    return np.linalg.solve(np.eye(env.S) - env.gamma * P, r)[0]


if __name__ == "__main__":
    # 梯度估计方差(theta=0 均匀策略);b 由同一批样本的回报均值估出
    env = GridWorld()
    theta0 = np.zeros((env.S, env.A))
    np.random.seed(5)
    rets = []
    for _ in range(600):
        _, _, R = rollout(env, theta0)
        rets.append(sum(env.gamma ** t * r for t, r in enumerate(R)))
    b_const = float(np.mean(rets))
    print("样本回报 G_0 = %.4f +- %.4f" % (np.mean(rets), np.std(rets)))
    for tag, bval in [("无基线 b=0", 0.0), ("常数基线 b=E[G_0]", b_const)]:
        np.random.seed(5)                             # 两次用同一批 600 条轨迹
        gs = []
        for _ in range(600):
            S, A, R = rollout(env, theta0)
            G = returns_to_go(R, env.gamma)
            g = np.zeros((env.S, env.A))
            for t in range(len(R)):
                g[S[t]] += (env.gamma ** t) * (G[t] - bval) * score(theta0, S[t], A[t])
            gs.append(g.ravel())
        gs = np.array(gs)
        print("%-20s 方差=%.5f  ||E[g]||=%.5f" % (
            tag, np.mean(((gs - gs.mean(0)) ** 2).sum(1)), np.linalg.norm(gs.mean(0))))
    # 12 种子训练
    for m, tag in [("none", "REINFORCE 无基线"), ("const", "REINFORCE 常数基线"),
                   ("Vs", "REINFORCE V(s) 基线")]:
        Js = [policy_value(env, train(m, seed=sd)[0]) for sd in range(12)]
        print("%-20s J = %.4f +- %.4f" % (tag, np.mean(Js), np.std(Js)))

代码做什么GridWorld 给出带滑步的 4×4 环境与只用于评估的转移模型 transsoftmax/score 实现讲义 p43 的 softmax 策略得分函数;returns_to_go 反向累加得 $G_t$;train 用四种变体更新 theta(表格状的 $\theta\in\mathbb{R}^{16\times4}$,等价于每个状态一组动作特征);policy_value 用线性方程组 $(I-\gamma P_\pi)V=r_\pi$ 精确求 $V^{\pi_\theta}(s_0)$,避免用训练回报当评价指标(训练回报本身有采样噪声)。末尾对每个变体跑 12 个随机种子并报告均值与标准差。

RL 机制透视。① 这是纯 on-policy 算法:每回合数据用完即弃,$\theta$ 一变,旧数据就不再反映当前策略;② 梯度权重 $G_t-b(s_t)$ 的符号决定 $\pi(a_t\vert s_t)$ 上升还是下降,只有相对比较才有意义;③ Actor-Critic 用 $r+\gamma V(s^{\prime})-V(s)$ 这一 bootstrap 优势替代 $G_t-b$,用偏差换方差;④ 「精确评估」与「训练回报」的差别,正是「策略性能 $J(\theta)$」与「单条轨迹回报」的差别。

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

  • 无偏性(实验 A):$\theta=0$ 处精确梯度范数 $\vert \nabla J\vert =0.18409$,$s_0$ 行梯度为 $[-0.013457,+0.013457,+0.013457,-0.013457]$;折扣访问分布 $d(s_0)=3.5757$,$\sum_s d(s)=16.6453$(即期望有效步数 $1/(1-\gamma)$ 量级)。MC 估计 $N=1500$ 时最大 $\vert z\vert =2.17$、$N=4000$ 时最大 $\vert z\vert =2.43$(均 $<3$,且随 $N$ 不增大)→ 确认无偏
  • $\gamma^t$ 权重:最大标准误 $0.00681$(带)vs $0.01129$(不带),即方差降至原来的 36.4%(降低约 63.6%)。
  • 基线降方差:无基线方差 $2.47743$,常数基线 $b=\mathbb{E}[G_0]=-0.4513$ 方差 $1.58384$(降 36.1%);两者 $\vert \mathbb{E}[\hat g]\vert $ 几乎相同($0.19888$ vs $0.19562$)→ 无偏性未被破坏
  • 基线质量消融:无基线 $2.47743$ > 欠拟合 $\hat V(800)$ 的 $1.68766$ > 常数基线 $1.58384$ > 学到 $\hat V(1500)$ 的 $1.49406$ > 精确 $V$ 的 $1.28996$(相对无基线降 47.9%)。→ 基线越好方差越低;拟合不准的 $V$ 可能还不如一个常数基线
  • 一次更新(实验 D):首动作 $a_0=0$、回报 $G_0=-0.3257$(负)→ 其概率 $0.2500\to0.2408$;另一条 $G_0=-0.6813$ 时 $0.2500\to0.1582$。负回报压低被采样动作的概率,且越负压得越狠。
  • 多随机种子(实验 E,300 回合 × 12 种子):REINFORCE($\gamma^tG_t$) $J=0.5019\pm0.0129$;去掉 $\gamma^t$ 仅 $0.2488\pm0.0148$(几乎腰斩);REINFORCE+V(s) 基线 $0.5036\pm0.0065$、单步 Actor-Critic $0.4939\pm0.0065$——两者的种子间标准差都约为无基线 REINFORCE 的一半($0.0065$ vs $0.0129$),且均值都高于无基线版本。对照 $J^*=0.5540$、$J(\text{random})=-0.4655$。

5.4.2 Actor-Critic:critic 目标的偏差-方差与折扣一致性

"""代码块 B:Actor-Critic 的 n 步 critic 目标(偏差-方差)与 actor/critic 折扣一致性。"""
import numpy as np

np.random.seed(0)

class GridWorld:
    ACTIONS = [(-1, 0), (0, 1), (1, 0), (0, -1)]

    def __init__(self, n=4, slip=0.1, step_reward=-0.04,
                 goal_reward=1.0, gamma=0.95, max_steps=200):
        self.n, self.slip = n, slip
        self.step_reward, self.goal_reward = step_reward, goal_reward
        self.gamma, self.max_steps = gamma, max_steps
        self.goal = (n - 1, n - 1)
        self.S, self.A, self.goal_idx = n * n, 4, n * n - 1

    def reset(self):
        self.rc, self.t = (0, 0), 0
        return 0

    def step(self, a):
        if np.random.rand() < self.slip:
            a = np.random.randint(self.A)
        dr, dc = self.ACTIONS[a]
        self.rc = (min(max(self.rc[0] + dr, 0), self.n - 1),
                   min(max(self.rc[1] + dc, 0), self.n - 1))
        self.t += 1
        s = self.rc[0] * self.n + self.rc[1]
        if self.rc == self.goal:
            return s, self.goal_reward, True
        return s, self.step_reward, self.t >= self.max_steps

    def trans(self, s, a):
        rc = (s // self.n, s % self.n)
        out = {}
        for a2 in range(self.A):
            w = (1.0 - self.slip if a2 == a else 0.0) + self.slip / self.A
            dr, dc = self.ACTIONS[a2]
            nr = min(max(rc[0] + dr, 0), self.n - 1)
            nc = min(max(rc[1] + dc, 0), self.n - 1)
            ns = nr * self.n + nc
            r = self.goal_reward if ns == self.goal_idx else self.step_reward
            out[ns] = (out.get(ns, (0.0, 0.0))[0] + w, r)
        return [(ns, w, r) for ns, (w, r) in out.items()]


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


def score(theta, s, a):
    p = softmax(theta[s])
    g = -p.copy()
    g[a] += 1.0
    return g


def rollout(env, theta):
    s, done = env.reset(), False
    S, A, R = [s], [], []
    while not done:
        a = np.random.choice(env.A, p=softmax(theta[s]))
        ns, r, done = env.step(a)
        A.append(a); R.append(r); S.append(ns); s = ns
    return S, A, R


def exact_V_Q(env, theta):
    """精确 V^{pi}(s), Q^{pi}(s,a)(只用 trans 提供的模型,不参与学习)。"""
    pi = softmax(theta)
    P, r = np.zeros((env.S, env.S)), np.zeros(env.S)
    for s in range(env.S):
        if s == env.goal_idx:
            continue
        for a in range(env.A):
            for ns, w, rr in env.trans(s, a):
                P[s, ns] += pi[s, a] * w
                r[s] += pi[s, a] * w * rr
    V = np.linalg.solve(np.eye(env.S) - env.gamma * P, r)
    Q = np.zeros((env.S, env.A))
    for s in range(env.S):
        if s == env.goal_idx:
            continue
        for a in range(env.A):
            Q[s, a] = sum(w * (rr + env.gamma * V[ns]) for ns, w, rr in env.trans(s, a))
    return V, Q


def policy_value(env, theta):
    return exact_V_Q(env, theta)[0][0]


def run_ac(n_step=1, n_episodes=400, alpha=0.1, alpha_v=0.1,
           gamma=0.95, gamma_critic=None, seed=0, baseline=True):
    """Actor-Critic:critic 目标 R_t^(n),actor 用优势 Ahat = R_t^(n) - V(s_t)。"""
    np.random.seed(seed)
    if gamma_critic is None:
        gamma_critic = gamma
    env = GridWorld()
    theta = np.zeros((env.S, env.A))
    V = np.zeros(env.S)
    gvar = []
    for _ in range(n_episodes):
        S, A, R = rollout(env, theta)
        T = len(R)
        Vt = np.array([V[si] for si in S[:T]])
        target = np.zeros(T)
        for t in range(T):
            if n_step is None:                       # 纯 MC
                target[t] = sum(gamma_critic ** k * R[t + k] for k in range(T - t))
            else:
                j = min(t + n_step, T)
                g = sum(gamma_critic ** (k - t) * R[k] for k in range(t, j))
                target[t] = g + (0.0 if j >= T else gamma_critic ** (j - t) * V[S[j]])
        gsum = 0.0
        for t in range(T):
            adv = (target[t] - Vt[t]) if baseline else target[t]
            gvec = (gamma ** t) * adv * score(theta, S[t], A[t])
            gsum += float(gvec @ gvec)                # ||单步梯度贡献||^2
            theta[S[t]] += alpha * gvec
            V[S[t]] += alpha_v * (target[t] - Vt[t])
        gvar.append(gsum)
    return theta, V, np.array(gvar)


def advantage_bias_variance(n_list=(1, 4, 16, None), n_traj=4000, seed=7):
    """配对测量 Ahat_0^(n) 的偏差与标准差;真值取精确 A^pi(s0,东)。"""
    env = GridWorld(); g = env.gamma; s0 = 0
    theta = np.zeros((env.S, env.A))                  # 均匀随机策略
    np.random.seed(0); V = np.zeros(env.S)            # 故意不完美的 critic
    for _ in range(300):
        S, A, R = rollout(env, theta)
        G = 0.0
        for t in range(len(R) - 1, -1, -1):
            G = R[t] + g * G
            V[S[t]] += 0.05 * (G - V[S[t]])
    Vex, Qex = exact_V_Q(env, theta)
    np.random.seed(seed)
    data = {n: [] for n in n_list}; acts = []
    for _ in range(n_traj):
        S, A, R = rollout(env, theta)
        T = len(R); acts.append(A[0])
        for n in n_list:                              # 同一轨迹上同时算所有 n(配对)
            if n is None:
                tgt = sum(g ** k * R[k] for k in range(T))
            else:
                j = min(n, T)
                tgt = sum(g ** k * R[k] for k in range(j))
                tgt += 0.0 if j >= T else g ** j * V[S[j]]
            data[n].append(tgt - V[s0])
    return env, s0, V, Vex, Qex, data, np.array(acts)


if __name__ == "__main__":
    env, s0, Vhat, Vex, Qex, data, acts = advantage_bias_variance()
    trueA = Qex[s0, 1] - Vex[s0]
    print("真值 A^pi(s0,东)=%.4f  Vhat(s0)=%.4f  精确 V(s0)=%.4f"
          % (trueA, Vhat[s0], Vex[s0]))
    for n in (1, 4, 16, None):
        d = np.array(data[n])[acts == 1]              # 条件在首动作=东 上
        print("  n=%-5s 偏差=%+.4f  标准差=%.4f" % (str(n), d.mean() - trueA, d.std()))
    for gc in (0.5, 0.8, 0.95, 0.99):                 # actor/critic 折扣一致性
        Js = [policy_value(env, run_ac(n_step=1, gamma_critic=gc, seed=sd)[0])
              for sd in range(8)]
        print("  gamma_critic=%.2f  J=%.4f +- %.4f" % (gc, np.mean(Js), np.std(Js)))
    for bl in (True, False):                          # 基线
        out = [run_ac(n_step=4, baseline=bl, seed=sd) for sd in range(8)]
        Js = np.array([policy_value(env, o[0]) for o in out])
        print("  基线=%-5s J=%.4f +- %.4f  末100回合 sum||grad||^2=%.3f"
              % (str(bl), Js.mean(), Js.std(), np.mean([o[2][-100:].mean() for o in out])))

代码做什么run_ac 先采一整条轨迹,再对每个 $t$ 构造 $n$ 步目标 $\hat R_t^{(n)}$(n_step=None 即纯 MC),用 $\hat A_t=\hat R_t^{(n)}-V(s_t)$ 更新 actor,同时用同样的目标更新 critic;gvar 记录每回合 $\sum_t\vert \gamma^t\hat A_t\nabla\log\pi\vert ^2$ 作为梯度更新量级的代理。advantage_bias_variance固定均匀策略下用配对采样(同一条轨迹同时计算所有 $n$ 的估计量,消除采样差异),并以精确 $A^\pi(s_0,a)$ 为真值,直接测出偏差与标准差。exact_V_Q 用转移模型解线性方程组得到精确的 $V^\pi$、$Q^\pi$,只用于评估。完整脚本另含 gaussian_score_check,用有限差分验证讲义 p45 的高斯策略得分函数(见下方实验观察)。

RL 机制透视。① 配对采样是把「偏差-方差」从「策略在变」的干扰中剥离出来的关键手法——若让每种 $n$ 各自训练,比较的是不同策略,而非不同估计量;② 这里的 critic 故意不完美(只学 300 回合),才能暴露「自举把 critic 误差带入目标」这一机制;③ 折扣不一致实验中,actor 固定在 $\gamma=0.95$,只改 critic 目标的 $\gamma_c$,精确对应当讲义的「一致性」讨论;④ $\sum\vert \text{grad}\vert ^2$ 是方差的直接代理,比只看最终 $J$ 更能说明基线的工作方式。

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

  • 高斯得分函数检验(完整脚本 L05_actor_critic.py):解析式 $(a-\mu)\phi/\sigma^2=[1.265306,0.126531,-0.063265,0.506122]$,与有限差分逐位相同,最大绝对误差 $9.36\times10^{-11}$ → 公式正确。
  • 实验 1(偏差-方差,配对 4000 条轨迹):真值 $A^\pi(s_0,\text{E})=0.0151$;critic 自身有偏差($\hat V(s_0)=-0.6177$ vs 精确 $-0.4655$,差 $\approx0.152$)。

    critic 目标$\mathbb{E}[\hat A]$偏差标准差
    $n=1$(TD)$-0.0638$$-0.0788$0.0445
    $n=4$$0.0893$$0.0742$$0.1449$
    $n=16$$0.1636$$0.1485$$0.3384$
    $n=\infty$(MC)$0.1843$$0.1692$$0.3790$

    方差随 $n$ 单调增大($0.0445\to0.3790$,约 8.5 倍)。但偏差的方向与此相反:偏差的绝对值随 $n$ 单调增大($0.0788\to0.1692$),$n=1$ 最小、$n=\infty$ 最大——这不是「$n=1$ 高偏差」的证据,恰恰相反。原因是本例 critic 的误差近似常数 $e\approx-0.152$,而 $\hat A^{(n)}t-\hat A^\pi_t=\gamma^n e(s{t+n})-e(s_t)$,故 $\vert \text{bias}\vert $ 随 $n$ 增大并饱和于 $\vert e(s_t)\vert $:实测 $n=\infty$ 的 $0.1692\approx\vert e\vert $ 与之吻合。所以本表只支持一条结论:要小方差就用 $n=1$;而偏差的方向取决于 critic 误差的结构(详见 5.9 题 4)。

  • 实验 2(折扣一致性,400 回合 × 8 种子):$\gamma_c=0.50\to J=0.0120\pm0.0064$;$0.80\to0.2692\pm0.0084$;$0.95\to0.3520\pm0.0061$(与 actor 一致);$0.99\to0.3596\pm0.0093$。严重不匹配(0.5)时性能崩塌到近随机水平
  • 实验 3(基线):有基线 $J=0.3365\pm0.0129$、末 100 回合 $\sum\vert \text{grad}\vert ^2=0.163$;无基线 $J=0.3420\pm0.0126$、$\sum\vert \text{grad}\vert ^2=0.977$。梯度更新量级相差约 6 倍($0.977/0.163$),而最终性能相近——说明基线主要通过稳定/缩小更新步长起作用。

5.5 评估指标与理论保证

评估指标

  • 策略性能 $J(\theta)$:本讲实验中用有模型精确策略评估得到 $V^{\pi_\theta}(s_0)$(解 $(I-\gamma P_\pi)V=r_\pi$),而非采样回报,从而把「算法优劣」与「采样噪声」分离。
  • 梯度估计方差 $\mathrm{trace}(\mathrm{Cov}(\hat g))$:直接度量单条轨迹梯度估计的噪声量级;本讲实验测得无基线 $2.47743$、常数基线 $1.58384$、精确 $V$ 基线 $1.28996$。
  • 偏差-方差:对 target 估计量分别测 $\mathbb{E}[\hat A]-A^\pi$(偏差)与 $\mathrm{std}(\hat A)$(方差),见表 5.4.2。
  • 样本复杂度/迭代数:讲义 p59 强调「达到好策略所需的迭代数/时间步数」,因为执行策略本身就在消耗奖励。
  • 收敛速度与经验性能:多随机种子的 $J$ 均值±标准差(本讲用 12 种子/8 种子)。

理论保证

  • 无偏性:$\mathbb{E}{\pi\theta}[\sum_t\nabla_\theta\log\pi_\theta(a_t\vert s_t)G_t]=\nabla_\theta J(\theta)$,且对任意 $b(s)$ 有 $\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(a_t\vert s_t)b(s_t)]=0$,故 $\mathbb{E}[\hat g]$ 与 $b$ 无关。
  • 策略梯度定理:对 $J_1$、$J_{avR}$、$\frac{1}{1-\gamma}J_{avV}$ 三者均有 $\nabla_\theta J(\theta)=\mathbb{E}{\pi\theta}[\nabla_\theta\log\pi_\theta(s,a)Q^{\pi_\theta}(s,a)]$,且不含 $\nabla_\theta d^{\pi_\theta}$ 与动力学模型
  • 收敛性(只到局部最优):在步长满足 $\sum_t\alpha_t=\infty$、$\sum_t\alpha_t^2<\infty$ 且 $J$ 平滑的常规随机逼近条件下,策略梯度上升收敛到 $J$ 的局部极大值附近(非全局最优,因 $J(\theta)$ 一般非凸)。这与基于值的方法「收敛到 $Q^*$(表格或满足条件时)」形成对比。
  • 方差缩减的形式:减去基线不改变期望,但可降低方差;本讲实验测得 $\gamma^t$ 权重使最大标准误从 $0.01129$ 降到 $0.00681$(方差 $36.4\%$)。

条件依赖分析

条件影响本讲证据
探索策略REINFORCE 必须 on-policy;数据必须由当前 $\pi_\theta$ 产生实验 E 中策略每回合变,旧数据不可复用
函数逼近策略类需可微且能算 $\nabla_\theta\log\pi_\theta$softmax 与 Gaussian 的得分函数均可解析
在线/离线离线策略需重要性采样(本讲未涉及,L6 讨论)全部实验均为在线采样
折扣一致性critic 的 $\gamma_c$ 须与 $J$ 的 $\gamma$ 一致$\gamma_c=0.5$ 时 $J$ 从 $0.35$ 崩到 $0.012$
基线质量基线越准方差越低,但不影响无偏性$\hat V$ 欠拟合时方差反不如常数基线

5.6 与其他讲次的关联

  • 与 L3、L4(模型无关评估与控制、DQN):L3–L4 建立 TD/MC 评估与 Q-learning、SARSA、DQN。本讲开头(5.2.1–5.2.2)统一了它们的 $\Delta w$ 形式并回顾 DQN;DQN 的策略是 $\epsilon$-greedy 隐式导出,本讲改成直接参数化
  • 与 L6(策略梯度 II):本讲已给出基线的无偏性证明值函数基线/优势函数最优基线的完整推导、方差缩减的严格论证以及 PPO、KL 约束、性能界、重要性采样留给 L6。本讲的 $\hat R_t^{(n)}$ 是 L6 的重要铺垫。
  • 与 L7(策略梯度 III / GAE / 单调改进):本讲给出优势函数 $A^\pi=Q^\pi-V^\pi$ 与 n 步优势估计;GAE(广义优势估计)与单调改进定理在 L7 展开,其中 n 步 Blended 估计器正是本讲 p73 的直接推广。
  • 与 L8(模仿学习 / RLHF / DPO):策略梯度(尤其 PPO)是 RLHF 的优化核心;本讲提到的「ChatGPT 与 PPO」即该链条起点。
  • 与 L2(有模型规划):本讲用值迭代算 $V^*$ 只作为评估基准,不参与学习;策略方法本身不需要模型。

5.7 关键要点

  • 范式切换:基于值 = 学值 + 隐式策略;基于策略 = 直接优化 $J(\theta)$;Actor-Critic = 两者兼有。策略方法在连续/高维动作、需要随机策略、要求平滑收敛时占优。
  • 似然比/得分函数是全部推导的引擎:$\nabla_\theta\pi_\theta(a\vert s)=\pi_\theta(a\vert s)\nabla_\theta\log\pi_\theta(a\vert s)$ 把「对概率求导」变成「对对数概率求导」,同时消掉动力学模型
  • 策略梯度定理:$\nabla_\theta J(\theta)=\mathbb{E}{\pi\theta}[\sum_t\nabla_\theta\log\pi_\theta(a_t\vert s_t)Q^{\pi_\theta}(s_t,a_t)]$,对 $J_1$、$J_{avR}$、$J_{avV}$ 均成立,且不含访问分布的导数。
  • REINFORCE = 得分函数 + 时序结构:用无偏的 $G_t$ 替代 $Q^{\pi_\theta}$,$\Delta\theta_t=\alpha\gamma^t\nabla_\theta\log\pi_\theta(s_t,a_t)G_t$;简单、无偏,但方差大。
  • 基线:减去只依赖状态的 $b(s)$ 不引入偏差($\mathbb{E}[\nabla\log\pi\,b(s)]=0$);$V^\pi(s)$ 是好的基线,$A^\pi=Q^\pi-V^\pi$ 是最终的工作形式。
  • Actor-Critic:critic 在 TD 与 MC 之间用 $n$ 步目标做连续混合,用偏差换方差;critic 与 actor 的折扣必须一致。
  • $\gamma^t$ 权重不可省:实验中去掉后 $J$ 从 $0.5019$ 掉到 $0.2488$,接近腰斩。

5.8 常见误区与注意事项

  1. 误区:策略梯度必须知道环境模型。正确认识:恰好相反。轨迹概率中 $\mu(s_0)$ 与 $P(s_{t+1}\vert s_t,a_t)$ 都不含 $\theta$,求导后为零,只剩 $\sum_t\nabla_\theta\log\pi_\theta(a_t\vert s_t)$。这正是「model-free」的来源。
  2. 误区:基线 $b(s)$ 会引入偏差,所以为了无偏不能用基线。正确认识:$b$ 不依赖动作时 $\mathbb{E}[\nabla_\theta\log\pi_\theta(a\vert s)b(s)]=0$ 恒成立(5.3.8 的推导),$\mathbb{E}[\hat g]$ 与 $b$ 无关。实验验证:$\vert \mathbb{E}[\hat g]\vert $ 在 $0.19888$(无基线)与 $0.19562$(有基线)间几乎不变,而方差从 $2.47743$ 降到 $1.58384$。
  3. 误区:只要用 $V(s)$ 当基线,方差就一定比常数基线小。正确认识:基线越接近真实值函数方差越低,但拟合不准的 $\hat V$ 反而可能更差。实验里欠拟合 $\hat V$(800 回合)方差 $1.68766$ 就高于常数基线的 $1.58384$;精确 $V$ 才是最低的 $1.28996$。
  4. 误区:REINFORCE 的 $\gamma^t$ 只是个无关紧要的常数。正确认识:它是折扣目标下策略梯度定理的必要组成(对应 $d^{\pi_\theta}(s)$ 中的 $\gamma^t$),让早期动作获得更大权重。去掉后最大标准误从 $0.00681$ 升到 $0.01129$,训练后 $J$ 从 $0.5019$ 掉到 $0.2488$。
  5. 误区:REINFORCE 像 Q-learning 一样可以离线复用旧数据。正确认识:$\hat g$ 的期望是在当前 $\pi_\theta$ 的分布下取的,换策略后期望就不再是 $\nabla_\theta J(\theta)$。REINFORCE 是严格 on-policy 的;要用旧数据必须做重要性采样(L6)。
  6. 误区(讲义 p14–p15):固定 Q 目标会让计算时间翻倍。正确认识:只翻倍内存(多存一份 $w^-$),不翻倍计算时间(每个更新仍是一次前向 + 一次反传)。这是「Check Your Understanding: Fixed Targets」的答案。
  7. 误区(讲义 p47–p48):似然比策略梯度要求奖励可微 / 只能用于 MDP / 只适合无限时域。正确认识:三者皆非(None of the above)。奖励只需是标量(不可微甚至未知都行)、推导未用马尔可夫性、分段式与无限时域都适用。
  8. 误区:策略梯度会收敛到全局最优。正确认识:$J(\theta)$ 一般非凸,只保证收敛到局部最优(讲义 p77 明确列为缺点)。这与表格 Q-learning 收敛到 $Q^*$ 不同。

5.9 思考题(带答案)

题 1(推导,基线无偏性)。设 $b(s)$ 是只依赖状态的任意函数,证明 \(\mathbb{E}_{\tau\sim\pi_\theta}\Big[\sum_{t=0}^{T-1}\nabla_\theta\log\pi_\theta(a_t\vert s_t)b(s_t)\Big]=0,\) 并据此说明为什么「减去基线」不会破坏策略梯度的无偏性。

答案。只需对单个 $t$ 证明(求和即得)。把期望按时刻拆开,先对 $a_t$ 与未来 $(s_{t+1:T},a_{t+1:T})$ 取期望;因为 $b(s_t)$ 不含 $a_t$,可提出(讲义 p63 的「pull baseline term out」):

\[\mathbb{E}\big[\nabla_\theta\log\pi_\theta(a_t\vert s_t)b(s_t)\big]=\mathbb{E}_{s_{0:t},a_{0:t-1}}\Big[b(s_t)\mathbb{E}_{a_t\vert s_t}\big[\nabla_\theta\log\pi_\theta(a_t\vert s_t)\big]\Big]\]

再用似然比 $\pi_\theta(a_t\vert s_t)\nabla_\theta\log\pi_\theta(a_t\vert s_t)=\nabla_\theta\pi_\theta(a_t\vert s_t)$:

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

于是该期望为 $\mathbb{E}{s{0:t},a_{0:t-1}}[b(s_t)\cdot0]=0$。因为 $\hat g$ 中的基线部分是均值为零的项,$\mathbb{E}[\hat g_{\text{baseline}}]=\mathbb{E}[\hat g]-\mathbb{E}[\nabla\log\pi\,b]=0$,故减去任意 $b(s)$ 都不引入偏差——基线只改变方差,不改变梯度估计的期望。

题 2(手算,softmax 策略的梯度更新)。某状态 $s$ 有 3 个动作,当前参数使 $\pi_\theta(\cdot\vert s)=[0.5,0.3,0.2]$。特征为 $\phi(s,a_1)=[1,0]$、$\phi(s,a_2)=[0,1]$、$\phi(s,a_3)=[0,0]$。设学习率 $\alpha=0.1$,采样得到 $(s,a_1)$ 且 $G_t=1.0$(无基线、忽略 $\gamma^t$)。 (a) 写出并算出 $\nabla_\theta\log\pi_\theta(a_1\vert s)$;(b) 更新后 $\pi_\theta(a_1\vert s)$ 是升还是降?(c) 若 $G_t=-1.0$ 呢?

答案。(a) 由讲义 p44 的结论 $\nabla_\theta\log\pi_\theta(s,a)=\phi(s,a)-\sum_{a^{\prime}}\pi_\theta(a^{\prime}\vert s)\phi(s,a^{\prime})$,先算 \(\sum_{a^{\prime}}\pi_\theta(a^{\prime}\vert s)\phi(s,a^{\prime})=0.5[1,0]+0.3[0,1]+0.2[0,0]=[0.5,0.3]\) 故 $\nabla_\theta\log\pi_\theta(a_1\vert s)=[1,0]-[0.5,0.3]=[0.5,-0.3]$。 (b) 更新量 $\Delta\theta=\alpha G_t\nabla_\theta\log\pi_\theta(a_1\vert s)=0.1\times1.0\times[0.5,-0.3]=[0.05,-0.03]$,于是打分变为 $z+\Delta\theta$。

必须先显式选定一组与 $\pi=[0.5,0.3,0.2]$ 一致的打分,否则具体数字没有意义:softmax 对整体平移不变,同一策略有无穷多组等价打分,而不同的等价打分给出不同的更新后概率。取最自然的一组 $z=[\ln(0.5/0.2),\ \ln(0.3/0.2),\ 0]=[0.9163,\ 0.4055,\ 0]$(可验证 $\mathrm{softmax}(z)=[0.5,0.3,0.2]$),则 $z+\Delta\theta=[0.9663,\ 0.3755,\ 0]$,softmax 后 $\pi_\theta(a_1\vert s)$ 上升:$\frac{e^{0.9663}}{e^{0.9663}+e^{0.3755}+e^{0}}\approx0.5170>0.5$。 (c) $G_t=-1.0$ 时更新量为 $[-0.05,0.03]$,$z+\Delta\theta=[0.8663,\ 0.4355,\ 0]$,$\pi_\theta(a_1\vert s)$ 下降到 $\frac{e^{0.8663}}{e^{0.8663}+e^{0.4355}+e^{0}}\approx0.4830<0.5$。方向性结论(升/降)不依赖打分参数化的选择——只要 $\pi=[0.5,0.3,0.2]$ 时 $\nabla_\theta\log\pi_\theta(a_1\vert s)=[0.5,-0.3]$,$G_t>0$ 必然抬升 $\pi(a_1)$、$G_t<0$ 必然压低它;但具体数值 $0.5170/0.4830$ 依赖所取的等价打分,故本题必须写明用的是哪一组 $z$。这也说明:梯度的符号完全由回报的正负决定——好于预期就抬升,差于预期就压低。

为什么具体数值会变:若改用 $z^{\prime}=z+c\mathbf{1}$,由于 $\Delta\theta$ 只加在前两个分量上、第三个分量不变,整体平移不再被 softmax 完全吸收,更新后的概率随之改变。这正是「softmax 策略参数化不可辨识」的表现——评估梯度更新时只能断言方向,不能断言具体概率值,除非固定参数化

题 3(推导 + 计算,REINFORCE 的方差与基线)。设某状态下只有两个动作,$\pi_\theta(a_1\vert s)=\pi_\theta(a_2\vert s)=0.5$,采样回报为 $G=2$(取 $a_1$)或 $G=0$(取 $a_2$),两动作对应概率各 $1/2$。记单步得分函数 $g_1=\nabla_\theta\log\pi_\theta(a_1\vert s)$,且 $\nabla_\theta\log\pi_\theta(a_2\vert s)=-g_1$。 (a) 无基线时 $\hat g=G\nabla_\theta\log\pi_\theta(a\vert s)$ 的期望与方差各是多少(用 $\vert g_1\vert ^2$ 表示)? (b) 取基线 $b=1$($=\mathbb{E}[G]$)后,期望是否改变?方差变为多少? (c) 结合 5.4 节的实测数据,说明为什么「最优基线」近似是 $\mathbb{E}[G]$。

答案。(a) 期望:$\mathbb{E}[\hat g]=\tfrac12\cdot2g_1+\tfrac12\cdot0\cdot(-g_1)=g_1$。二阶矩:$\mathbb{E}[\vert \hat g\vert ^2]=\tfrac12\vert 2g_1\vert ^2+\tfrac12\vert 0\vert ^2=2\vert g_1\vert ^2$,故方差 $=\mathbb{E}[\vert \hat g\vert ^2]-\vert \mathbb{E}[\hat g]\vert ^2=2\vert g_1\vert ^2-\vert g_1\vert ^2=\vert g_1\vert ^2$。 (b) 取 $b=1$:取值变为 $(2-1)g_1=g_1$ 与 $(0-1)(-g_1)=g_1$,即两种结果都等于 $g_1$。期望仍为 $g_1$(无偏性保持),而方差 $=\mathbb{E}[\vert g_1\vert ^2]-\vert g_1\vert ^2=0$。 (c) 因为减去 $\mathbb{E}[G]$ 相当于用「相对预期的超额」加权,本例中它恰好把两种情形的权重都归到同一常数,噪声被完全抵消;一般情况下最优基线在 $\mathbb{E}[G]$ 附近。实验印证:$b=\mathbb{E}[G_0]=-0.4513$ 把方差从 $2.47743$ 降到 $1.58384$($-36.1\%$)而期望几乎不变;用更接近真值的逐状态 $V(s)$ 基线可进一步降到 $1.28996$($-47.9\%$),说明基线越接近真实值函数越好。

题 4(判断题重写,n 步优势估计与折扣一致性)。讲义 p74 给出四个选项:(1) $\hat A_t^{(1)}$ 低方差&低偏差;(2) $\hat A_t^{(1)}$ 高方差&低偏差;(3) $\hat A_t^{(\infty)}$ 低方差&高偏差;(4) $\hat A_t^{(\infty)}$ 高方差&低偏差。哪些正确?并解释本讲实验 1 中「偏差随 $n$ 单调增大」为何不与此矛盾。

答案正确选项是 (1) 与 (4):critic 精确时两者都无偏,所以含「高偏差」的 (3)、以及把 $\hat A_t^{(1)}$ 说成高方差的 (2) 都错;方差方面 $\hat A^{(1)}$ 只依赖一步真实奖励→低方差,$\hat A^{(\infty)}$ 是整条轨迹的 MC 回报→高方差

实验 1 与它并不矛盾,因为实验 1 的 critic 故意不准($\hat V(s_0)=-0.6177$ vs 精确 $-0.4655$,误差 $e\approx-0.152$)。关键在于这个误差的结构,而不是「越大越不准」这种粗略直觉。

把 n 步优势的误差写开(设 $\hat V=V^\pi+e$,$e$ 近似为常数):

\[\hat A^{(n)}_t-\hat A^{\pi}_t=\gamma^n e(s_{t+n})-e(s_t)\;\xrightarrow[\gamma<1]{n\to\infty}\;-e(s_t),\]

即 $\vert \text{bias}\vert $ 随 $n$ 单调增大并饱和于 $\vert e(s_t)\vert $。实验实测偏差绝对值 $0.0788\to0.1692$、标准差 $0.0445\to0.3790$,两者都随 $n$ 增大;$n=\infty$ 的 $0.1692$ 恰与 $\vert e\vert \approx0.152$ 同量级,正是「饱和」形式的数值印证。

因此正确的调和是:选项 (1)/(4) 说的是 critic 精确($e=0$)时的偏差-方差——此时 $\hat A^{(n)}$ 对任意 $n$ 都无偏,$\hat A^{(1)}$ 低方差、$\hat A^{(\infty)}$ 高方差,故 (1)(4) 成立。而实验 1 的 critic 不精确,代入 $e\ne0$ 后 $n$ 越大偏差反而越大——「$n=1$ 低偏差」只在 critic 精确时成立。这也正是 Actor-Critic 要调的旋钮:critic 准就用小的 $n$(省方差),critic 不准就得用大的 $n$(宁可吃方差也不吃偏差),而 GAE 的 $\lambda$ 提供了两者之间的连续插值。

要点方差的方向($n$ 越大方差越大)是无条件的;偏差的方向取决于 critic 质量——critic 精确时 $\hat A^{(1)}$ 低偏差,critic 有错时它变成高偏差。这正是 Actor-Critic 要调的旋钮,也是第 7 讲 GAE 用 $\lambda$ 在两者之间连续插值的动机。