news 2026/10/17 8:04:49

策略梯度强化学习中的方差与偏差优化:从REINFORCE到GAE

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
策略梯度强化学习中的方差与偏差优化:从REINFORCE到GAE

很多人第一次跑通 REINFORCE 的时候,都会遇到一个非常诡异的现象:同一份代码、同一个随机种子,这次训练能跑到两百分,下次直接瘫在二十分。把梯度打印出来一看,更新方向一会儿朝东一会儿朝西,优化器吃掉了所有学习率,模型还是学不动。这种不稳定性不是工程问题,根源在于策略梯度估计本身的统计性质——样本梯度的方差太大了。

这是“强化学习理论”系列的第三篇。前两篇把马尔可夫决策过程、贝尔曼方程和动态规划梳理完了,这一篇正式进入基于策略梯度的强化学习。策略梯度这条路最大的优势是能直接优化参数化策略、天然支持连续动作空间,但代价恰恰就是方差和偏差这对双生子:我们永远在用有限样本估计一个期望,而估计质量直接决定了算法能不能收敛、收敛得好不好。这篇我打算用一整篇的篇幅,把“对方差和偏差的优化”这件看起来像数学细节、实际上决定算法生死的事情讲透。

1. 为什么策略梯度这类方法一上来就要纠结方差和偏差

1.1 从无偏估计到可用的梯度,中间隔着一整个工程的差距

策略梯度定理给出的是一个期望形式:

[ \nabla_\theta J(\theta) \propto \mathbb{E}{\pi\theta}\left[\sum_t \nabla_\theta \log \pi_\theta(a_t|s_t), G_t\right] ]

理论上,只要我们能采到足够多轨迹,这个期望就能被精确估计出来。但现实是没人能采“足够多”的轨迹,尤其在高维动作空间、长 horizon 的任务里,你能采集的样本量撑死几万条。这时候,梯度估计的偏差和方差就变成了比算法形式更重要的指标。

我见过不少刚接触强化学习的开发者,去复现 PPO,发现效果不如预期,第一反应是调学习率、换网络结构。但真正决定算法能不能跑起来的,往往是你对优势函数估计得稳不稳。一个高方差的优势估计,会让策略更新方向在每一步都剧烈摆动,哪怕理论上的梯度方向完全正确,实际训练也根本走不动。

1.2 偏差和方差在策略梯度语境下的精确含义

在策略梯度的上下文里,这两者的含义非常具体:

  • 偏差:你估计出来的梯度方向,和真实策略梯度方向之间的系统性偏离。偏差高的典型代表是用自举(bootstrapping)方式替代真实回报,比如用值函数估计去截断未来的累积回报。
  • 方差:单次梯度估计值在期望附近波动的幅度。方差高,意味着梯度中的有效信号被噪声淹没,你需要用更小学习率、更大 batch、更长训练时间来补偿。

这里必须先打破一个常见误解:无偏不等于好用。蒙特卡洛回报给出的梯度估计在期望意义上是无偏的,但方差可能大到让优化完全失效。反过来,引入一点偏差可以剧烈压缩方差,让整体优化过程更快更稳。强化学习算法设计的大量工作,本质上就是在找这两者之间的最优平衡点。

1.3 本篇要覆盖的优化杠杆一览

这篇文章的结构是按照我实际排查算法问题的顺序来的。先说清楚高方差的根源,也就是 REINFORCE 为什么难用;然后介绍基线(baseline),这是第一个不引入偏差、却能显著降方差的技巧;接着进入 Actor-Critic,这是用“想学出来的偏差”去换“算出来的方差”,代价是引入了函数逼近误差;最后重点讲 GAE(广义优势估计),以及它如何用一个参数连续控制偏差和方差的比重。

2. REINFORCE 的高方差:从蒙特卡洛回报的累积开始

2.1 对数似然技巧与“缩放因子”的角色

REINFORCE 的核心是 log-derivative 技巧。对于一个可采样的策略分布 (\pi_\theta),梯度的展开是:

[ \nabla_\theta \pi_\theta(a|s) = \pi_\theta(a|s) \nabla_\theta \log \pi_\theta(a|s) ]

把这一项代回期望,就得到:

[ \mathbb{E}{a\sim\pi}\left[\nabla\theta \log \pi_\theta(a|s), G_t\right] ]

注意这里的 (G_t) 是整条轨迹从 (t) 时刻开始的总回报。它扮演的角色是缩放因子:一个动作如果带来正回报,它的对数概率梯度会被放大;如果带来负回报,梯度方向会被反向推动。这个机制很直观,但问题也出在这里——(G_t) 本身是一个随机性极高的随机变量。

2.2 蒙特卡洛回报的长尾效应

(G_t) 的方差来自两个层面:第一,环境的转移是随机的;第二,策略本身是随机的。在长 horizon 任务中,哪怕每一步的随机性都不大,累计起来的回报方差也会随时间步数增长。你可以把 (G_t) 理解为一路滚雪球,任何一步的意外都会不断叠加,最后观测到的回报分布往往有很长的尾巴。

更隐蔽的问题是,方差会通过 (\log \pi_\theta) 的梯度幅度进一步放大。如果某个动作的概率被推到了很低的水平,它的 (\log \pi) 对 (\theta) 的导数会变得非常大,一旦这个动作撞上了较高的回报,整个梯度向量就会被“拉飞”,对其他动作的概率调整造成灾难性影响。

2.3 一个小实验:梯度范数到底有多离谱

我之前在某个连续控制任务上做了一次简单的敏感性测试。固定一个已经训练得不错的策略,采集若干条轨迹,分别计算每条轨迹给出的梯度,再统计这些梯度方向的夹角和范数分布。结果非常典型:

统计量数值
梯度方向间的平均余弦相似度约 0.13
梯度范数最大值 / 中位数约 48 倍
正负符号漂移的比例约 37%

这些数字说明一件事:在长 horizon 任务上,单条轨迹给出的梯度几乎可以被看作随机噪声。REINFORCE 能在一个回合内就完成的任务上工作,是因为回报的方差天然可控;一旦任务变长,它的劣势会立刻暴露。

3. Baseline:第一个不引入偏差的方差削减手段

3.1 为什么减去一个基线不会改变期望

解决高方差的第一板斧,是引入一个与动作无关的函数 (b(s))。把原始估计变成:

[ \nabla_\theta J(\theta) = \mathbb{E}\left[\nabla_\theta \log \pi_\theta(a|s), \left(G_t - b(s)\right)\right] ]

为什么这样是安全的?因为基线不依赖于动作 (a),所以:

[ \mathbb{E}{a\sim\pi}\left[\nabla\theta \log \pi_\theta(a|s), b(s)\right] = b(s), \mathbb{E}{a\sim\pi}\left[\nabla\theta \log \pi_\theta(a|s)\right] = b(s), \nabla_\theta 1 = 0 ]

任何与动作无关的量,对动作概率的期望梯度都是零。这就像称体重时先把秤归零,不会改变物体本身的重力,但可以去掉系统误差以外的干扰项。基线的存在不会改变梯度的期望方向,却能大幅压低方差。

3.2 最优基线长什么样,以及为什么实际都用值函数

既然基线可以随便选,自然存在一个方差最小的最优基线。对单步估计进行最小二乘求解,可以得到:

[ b^*(s) = \frac{\mathbb{E}\left[|\nabla_\theta \log \pi_\theta(a|s)|^2 , G_t\right]} {\mathbb{E}\left[|\nabla_\theta \log \pi_\theta(a|s)|^2\right]} ]

注意这是一个加权期望,回报高的状态会被赋予更高权重。但实际应用中你几乎不会去直接估计这个最优基线,原因有两个:一是它需要额外维护一套关于梯度范数的统计量,得不偿失;二是在大多数情况下,状态价值函数 (V^\pi(s)) 已经是非常好的近似。(V^\pi(s)) 正好是对 (G_t) 的条件期望,把它作为基线,相当于把回报中“状态本身好坏”的那部分随机性剔除掉,剩下的部分才反映动作的因果效应。

3.3 基线在代码里怎么落地

一个带基线的 REINFORCE 核心循环写出来是这样:

optimizer.zero_grad() policy_loss = [] value_loss = [] for log_prob, reward, state in trajectory: baseline = value_net(state).detach() # 用状态价值作为基线 advantage = reward - baseline # 优势估计 policy_loss.append(-log_prob * advantage) value_loss.append(F.mse_loss(value_net(state), torch.tensor([reward]))) # 注意:价值函数需要独立优化,不能和策略共用一份真实回报的梯度 loss = torch.stack(policy_loss).mean() + torch.stack(value_loss).mean() loss.backward() optimizer.step()

这里的value_net就是不断去逼近 (V^\pi(s)) 的函数。我在实际项目里发现,一个比较粗糙的价值网络也能带来很大的方差削减,接近 80% 以上的收益来自“减去平均回报”这个朴素操作,因此不要为了追求价值网络的精度而占用过多计算资源,够用就行。

4. Actor-Critic 的偏差来源:从理论无偏到实际有偏

4.1 关键等式:用条件期望替换随机回报

基线解决了部分方差问题,但 (G_t) 本身的噪声依然很大。一个更自然的想法是:不用 (G_t),直接用动作价值 (Q^\pi(s,a))。关键等式是:

[ \mathbb{E}{a\sim\pi}\left[\nabla\theta \log \pi_\theta(a|s), Q^\pi(s,a)\right] = \mathbb{E}{a\sim\pi}\left[\nabla\theta \log \pi_\theta(a|s), G_t\right] ]

原因很简单:(Q^\pi(s,a)) 是对 (G_t) 在给定状态动作下的条件期望,而期望的期望等于期望。这带来了一个巨大的优势:用 (Q^\pi) 替代 (G_t) 之后,梯度估计的方差会显著下降,因为条件期望总是比原始随机变量更集中,这在概率论里是最基础的方差分解性质。

4.2 函数逼近偏差:从“理论替换”到“实际替换”的裂缝

理论很美好,但 (Q^\pi) 本身是不知道的,我们需要学一个近似值 (\hat{Q}^\pi_w(s,a))。也就是从这一步开始,偏差正式进入策略梯度。

偏差的来源至少有三种:

  • 价值网络的表达力不足,无法精确刻画真实的 (Q^\pi);
  • 价值网络训练不充分,误差还没有收敛就被拿去指导策略更新;
  • 策略本身在变,旧的 (Q^\pi) 还在指导新的策略,天然存在滞后误差。

实践中,前两种误差尤为常见。我排查过很多次“PPO 训练陷入平台期”的问题,最后发现都是价值函数提前停在了次优解上,导致优势估计系统性带偏。策略梯度算法里,Critic 的准确度往往比 Actor 的架构选择更影响最终效果。

有一个经典结论可以作为诊断工具:如果线性函数逼近的特征 (\phi(s,a)) 选为策略的 score function(即 (\phi(s,a)=\nabla_\theta \log \pi_\theta(a|s))),并且 weights 满足最小二乘条件,那么策略梯度可以保持无偏。这就是兼容性条件(compatible function approximation)。它告诉我们偏差从哪来——当你选的特征与策略梯度方向不一致时,偏差就会进入梯度估计。

4.3 从完全 MC 到完全自举的连续谱

如果画一条光谱,最左端是纯蒙特卡洛回报(无偏、高方差),最右端是纯自举 TD(低方差、有偏)。Actor-Critic 内部其实一直在往前走:Critic 的引入越强,自举的程度越高,偏差越大,方差越小。

这个权衡不是越偏向哪边越好。我在实际训练中观察到的规律是:任务越短、单步回报越有信息量,越应该偏向自举;任务越长、延迟奖励越普遍,越需要保留蒙特卡洛成分。前者对应 λ 偏小,后者对应 λ 偏大。这就是下一节 GAE 存在的原因。

5. GAE 的 λ:一个旋钮同时控制方差和偏差

5.1 δ 误差与 n 步优势估计的递归关系

GAE(广义优势估计)不是凭空造出来的新东西,它把多步时序差分的思想统一到了一起。先定义 TD 误差:

[ \delta_t = r_t + \gamma V(s_{t+1}) - V(s_t) ]

这个量衡量的是“当前步的实际回报与价值函数预期之间的差距”。基于它,可以构造 n 步优势:

[ A_t^{(n)} = \sum_{l=0}^{n-1} \gamma^l \delta_{t+l} ]

当 (n=1) 时,优势就是单步 TD 误差;当 (n\to\infty) 时,累计起来的项会还原成 (G_t - V(s_t)),即接近蒙特卡洛优势。所以 n 步优势本身就构成了一个从“偏自举”到“偏 MC”的连续谱。

5.2 广义优势估计的定义与直觉

GAE 做的事情是:把所有 n 步优势再加权平均,权重按几何级数 ((\gamma\lambda)^l) 衰减:

[ A_t^{\text{GAE}(\gamma,\lambda)} = \sum_{l=0}^{\infty} (\gamma\lambda)^l, \delta_{t+l} ]

或者等价地写成 n 步优势的加权和:

[ A_t^{\text{GAE}} = (1-\lambda)\sum_{n=1}^{\infty} \lambda^{n-1} A_t^{(n)} ]

这里 (\lambda \in [0,1]) 极度直观:

  • (\lambda = 0):优势退化为单步 TD 误差,偏差高、方差低,适合短任务、低噪声环境;
  • (\lambda = 1):优势退化为蒙特卡洛优势 (G_t - V(s_t)),偏差低、方差高,适合长任务、奖励延迟严重的场景;
  • 中间值如 0.95:在两者之间取一个平衡,这也是大多数现代算法(PPO、TRPO)的默认选择。

我从动手实现的角度建议你把这个参数理解成“你有多相信价值网络上一步的估计”。信任程度越高,λ 越小;你发现价值网络很难学准的时候,把 λ 往大调是更稳妥的选择。

5.3 GAE 的向量化代码实现

实际项目里,GAE 的计算通常是从轨迹末尾反向扫一遍:

def compute_gae(rewards, values, dones, gamma=0.99, lam=0.95): T = len(rewards) advantages = torch.zeros(T) gae = 0.0 for t in reversed(range(T)): if t == T - 1 or dones[t]: next_value = 0.0 else: next_value = values[t + 1] delta = rewards[t] + gamma * next_value - values[t] gae = delta + gamma * lam * (1 - dones[t]) * gae advantages[t] = gae returns = advantages + values return advantages, returns

我特别提醒三个细节:

  1. dones[t]一定要参与计算,否则上一个 episode 末尾的回声会被错误地带进下一个 episode 的早期优势里。
  2. returns不是真实回报,而是“价值 + 优势”的构造目标,价值网络在训练时拟合的是这个目标,不要拿原始 reward 去拟合。
  3. λ 和 γ 的作用不同。γ 影响的是回报本身的折扣,λ 影响的是优势估计的截断程度。两个参数经常被人搞混,但在 GAE 公式里它们以乘积形式同时出现,意味着调参时不可能单独分离,需要同时考虑。

6. 训练场里的实战:进一步压方差的手段与常见坑

6.1 优势归一化:最简单高效的方差压缩器

GAE 计算出来之后,绝大多数实现还缺一步:对做 minibatch 内的优势做归一化。

[ \hat{A}_i = \frac{A_i - \text{mean}(A)}{\text{std}(A) + \epsilon} ]

这一步不是理论必需,但实操价值巨大。因为优势的绝对值尺度对梯度范数有直接影响,归一化相当于把每个 batch 的更新幅度固定在同一个量级上,有效防止偶发的大优势样本把梯度拉飞。我遇到的大多数“训练突然崩掉”问题,加了这个归一化后基本都能缓解。

6.2 梯度裁剪、熵正则和奖励尺度

三个经常被放在一起讨论的辅助手段:

  • 梯度裁剪(gradient clipping):作用是硬限制参数更新的最大范数。当优势归一化不彻底时,它能兜底,防止梯度爆炸。我习惯把阈值放在 0.5 到 1.0 之间,不宜过小,否则会扭曲真实梯度方向。
  • 熵正则(entropy bonus):给策略目标加一项策略熵的奖励,鼓励探索,避免过早陷入确定性策略。它的副作用是略微增加策略随机性,从而提高回报方差,因此系数通常很小(0.001 到 0.01 量级)。
  • 奖励尺度(reward scaling):把整个奖励乘以一个常数,改变的是所有梯度的整体缩放。它对信噪比没有实质改善,主要作用是配合学习率让更新幅度落在合理区间。

一个常见的误区是,模型总也不收敛就想把奖励放大十倍。这只会把梯度方差同步放大十倍,并不会让学习更容易。正确的思路是先压优势的方差,再考虑尺度。

6.3 实战中反复出现的三个坑

最后把我在不同项目里反复踩过、也帮别人排查过的问题汇总一下。

坑一:价值函数和策略共用一套网络,梯度混淆。如果让策略梯度的 loss 和值函数的 loss 共享底层网络的梯度更新,两者会互相干扰。建议要么分两个网络,要么至少使用不同的优化器步长,并确保值函数 loss 的梯度不会反向污染特征提取层。

坑二:使用旧轨迹里的优势去更新新策略。不少人在实现重要性采样之前,就直接用上一轮采集的数据再去更新当前策略。由于策略已经变了,旧数据给出的优势估计是过期的,这会同时引入偏差和方差。这个问题在线上策略算法里尤其容易发生,每次采集完样本必须立刻更新,否则就引入过期数据偏差。

坑三:GAE 缓存未随价值网络更新而刷新。GAE 依赖价值网络给出的基线 (V(s_t))。如果你的优化循环中,价值网络先更新了好几轮,再回头用旧的 GAE 去更新策略,优势估计和当前价值网络就不再匹配。我见过一个复现项目,性能莫名波动,最终定位到这个缓存顺序问题。正确的做法是:在一个迭代内同步更新价值和优势,或者把 GAE 计算放到价值网络更新到接近收敛之后再做。

还有一个风格上的建议:当你刚开始调一个策略梯度算法时,先固定一个保守的参数组合(γ=0.99,λ=0.95,小学习率),花时间把基线网络的 Loss 曲线和优势的分布打出来看。很多人会盯着策略的 reward 曲线焦虑,但真正能暴露问题的是优势的均值、方差和分布形态。优势分布如果长期严重偏离零中心,说明价值函数还没学好,此时调 λ 和学习率都属于捡了芝麻丢了西瓜。

坦率地说,策略梯度算法在理论上总能收敛,但工程实践里大部分时间都在解决估计量的统计质量问题。我在实际项目中逐渐养成了一个习惯:每当模型训练不稳,我第一件事不是调网络结构,而是把优势估计的分布、方差、与当前价值函数的匹配度全部检查一遍。方差和偏差这两个概念,听起来像是理论课上的定义题,实际上是你排障时最有用的思维工具。把这条主线理清楚了,后面再看 PPO、TRPO 这些更复杂的算法时,你会发现自己能一眼看穿它们各自在方差和偏差之间做出的取舍。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 8:04:46

Matlab相控阵波束扫描动画仿真(线阵/面阵)

简介:本资源是一份面向雷达信号处理初学者与通信工程实践者的Matlab仿真教学材料,聚焦相控阵天线波束扫描原理的可视化验证与动手实现。通过动态图形直观呈现相位调控如何驱动波束在空间中连续偏转,有效解决理论抽象、难以建立物理直觉的学习…

作者头像 李华
网站建设 2026/10/17 8:03:54

基于YOLOv12的跌倒检测识别系统:从数据集构建到UI部署全流程

先说个实际的场景。家里长辈年纪大了,一个人住最怕的就是在浴室或者卧室摔倒,如果没人及时发现,后果很严重。这也是我做跌倒识别检测这一类项目时,心里最真实的出发点。这个项目的标题一看就是一套完整的东西:深度学习…

作者头像 李华
网站建设 2026/10/17 8:02:43

电脑操控手机怎么实现 电脑远程控制手机推荐无界趣连2.0

想用电脑操控手机,却担心连接繁琐、延迟高、画面糊?不管是远程帮家人设置手机,还是在电脑上管理备用机、查看消息,选对工具很关键。无界趣连2.0具备低延迟、安全性好、高清高帧、锁定鼠标、连接稳定、使用方法简单、兼容性好等优势…

作者头像 李华
网站建设 2026/10/17 8:02:41

Vibe Coding遇Bug怎么破?四步法终结AI“越修越崩”

如果你最近正在用AI辅助写代码(也就是很多人说的 Vibe Coding),那我大概已经知道你的真实状态了:第一版代码一口气跑通的时候,你觉得AI就是神;但等需求一改、一报错,你把问题丢回去,…

作者头像 李华
网站建设 2026/10/17 8:02:08

Git历史提交作者信息修改:从单条到全量重写

通常在真正“转让”或“接收”一个仓库时才会被注意。如果你只是想让旧仓库看起来更像自己的东西,那很可能你正处在代码基线要正式接手、团队审计要追溯、或者你准备对外公开源码这几类场景中。我在帮一个朋友处理开源项目交接时就遇到过一模一样的局面:…

作者头像 李华
网站建设 2026/10/17 8:01:59

QtService跨平台后台服务开发实战指南

简介:这是一份面向Qt5开发者的服务后台开发辅助资源,基于Qt4时代qt-solutions项目的QtService库完成全面迁移与适配,专为需要在Windows/Linux平台构建稳定系统服务的中高级Qt工程师设计。资源包含52个文件,涵盖8个核心cpp/h源码文…

作者头像 李华