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

发布时间:2026/10/17 8:05:04

策略梯度强化学习中的方差与偏差优化:从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_{t1}) - V(s_t) ]这个量衡量的是“当前步的实际回报与价值函数预期之间的差距”。基于它可以构造 n 步优势[ A_t^{(n)} \sum_{l0}^{n-1} \gamma^l \delta_{tl} ]当 (n1) 时优势就是单步 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_{l0}^{\infty} (\gamma\lambda)^l, \delta_{tl} ]或者等价地写成 n 步优势的加权和[ A_t^{\text{GAE}} (1-\lambda)\sum_{n1}^{\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, gamma0.99, lam0.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我特别提醒三个细节dones[t]一定要参与计算否则上一个 episode 末尾的回声会被错误地带进下一个 episode 的早期优势里。returns不是真实回报而是“价值 优势”的构造目标价值网络在训练时拟合的是这个目标不要拿原始 reward 去拟合。λ 和 γ 的作用不同。γ 影响的是回报本身的折扣λ 影响的是优势估计的截断程度。两个参数经常被人搞混但在 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 这些更复杂的算法时你会发现自己能一眼看穿它们各自在方差和偏差之间做出的取舍。
延伸阅读

更多相关文章

2026/10/17 8:05:04

端口镜像与链路聚合:原理、配置与实战避坑指南

1. 为什么我要把端口镜像和链路聚合放在一起讲刚入行那会儿,我一直觉得端口镜像和链路聚合是两码事:一个用来抓包分析,一个用来增加带宽和冗余,八竿子打不着。直到有一次在机房里排查一个"时通时断"的故障,我…

2026/10/17 8:05:04

用Kotlin+XML复现微信界面:RecyclerView与Fragment实战指南

简介:一份基于Android Studio打造的仿微信界面完整工程,面向Android入门与中级开发者,通过实战项目演示如何搭建类似微信的社交应用UI,帮助解决界面设计不知从何下手的问题。资源共1041个文件、压缩包约24.25MB,涵盖XM…

2026/10/17 8:05:04

批量下载IEEE论文:Python脚本自动化文献整理的完整方案

简介:这是一款针对科研人员与高校学生的IEEE论文批量下载工具,基于Python开发,可借助DOI号或搜索关键词,从IEEE Xplore数字图书馆自动获取论文并保存为PDF,大幅节省文献调研和综述撰写时间,尤其适合综述写作…

2026/10/17 9:25:09

从零手推BP神经网络:Iris分类实战与PyCharm单步调试指南

简介:本资源是一份面向机器学习初学者与高校课程实践者的BP神经网络入门级实战项目,聚焦Iris数据集的三分类任务,完整呈现从理论理解、代码实现到实验分析的全流程。压缩包共4个文件(2个Python源码、1份Word实验报告、1个CSV格式数…

2026/10/17 9:25:09

AutoJs中用Shell操作SQLite的完整实践指南

简介:一份面向安卓自动化脚本开发者的源码资源,主题是使用系统命令行操作本地数据库。压缩包内只包含1个JavaScript脚本文件,整体大小约775字节,体积极其精简,下载后导入自动化脚本工具即可运行,也适合直接…

2026/10/17 9:25:09

.chess申请背后的新顶级域名技术竞争与基础设施重构

顶级域名不只是网址后缀。当国际棋联(FIDE)和世界国际象棋(World Chess)联手申请 .chess 这个新顶级域名时,很多人第一反应是“又多了一个网址后缀”,但这件事真正值得技术人关注的,是它背后代表…

2026/10/17 9:25:09

用claude-code-templates解决AI编程输出不稳定问题

上个季度给一个微服务项目补单元测试,我对着同一个终端里的Claude Code连续问了三次“给这个模块写测试”,三次回答风格完全不一样:第一次用了JUnit 5的ParameterizedTest,第二次用的是Mockito原生写法,第三次把断言库…

2026/10/17 9:20:09

SQL空值处理实战:COALESCE函数原理、用法与避坑指南

在数据库里跑 SQL 时,最让人又爱又恨的东西应该就是 NULL 了。你说它是空值吧,它又不等于空字符串,也不等于 0;你说它没有值吧,它在聚合、连接、排序里又无处不在,稍不留神就给你惹一堆麻烦。COALESCE 这个…

2026/10/16 5:33:43

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/16 4:03:48

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/15 13:42:16

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/17 0:04:32

PlanarSLAM:面向曼哈顿世界的点线面联合SLAM系统

简介:本资源是面向机器人视觉与SLAM研究者的C开源RGB-D SLAM系统实现,专为结构化室内场景(如办公室、走廊)设计,通过融合点、线、平面三类几何特征并引入“曼哈顿世界”假设,显著提升位姿跟踪鲁棒性与稠密地…

2026/10/17 0:04:32

TDH Workflow调度实战:从DAG依赖驱动到任务编排与故障排查

1. 从一个调度脚本说起:TDH Workflow到底在解决什么问题第一次接触TDH的Workflow,是在一个数据清洗项目里。当时团队每天要跑几十个ETL任务,任务之间有严格的先后依赖——A表清洗完才能跑B表的关联,B表跑完才能触发C表的聚合。最开…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑