ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

PPO不靠轨迹总分靠优势:GAE如何驱动策略向高分轨迹靠拢

PPO不靠轨迹总分靠优势:GAE如何驱动策略向高分轨迹靠拢

看到这个问题我就觉得,你应该是真在调PPO调出疑惑了。自己跑出来的轨迹,有的动作序列能拿70分,有的能拿100分,那模型凭什么不朝100分那边靠?如果一直往70分那边蹭,是不是GAE算错了,还是PPO更新机制有问题?这个问题看起来很朴素,但我见过不少刚接触强化学习的人在群里问。答案其实不是简单的一句“会靠”或“不会靠”,因为PPO和GAE决定“往哪靠”的逻辑,和你脑子里的直觉有一点微妙差异。这篇文章我就从GAE和PPO的更新机制出发,把这个“往高奖励靠”的问题彻底掰开揉碎,然后附上我实际调参过程中遇到的相关问题和排查经验。

1. 轨迹奖励差异的本质:70分和100分到底差在哪儿

1.1 奖励只是结果,原因在于状态动作序列

先退一步看这个问题。你手里的70分轨迹和100分轨迹,本质上是两条不同的状态动作序列。奖励是执行完一整条轨迹后,环境给你的反馈。这两条轨迹之所以分数不同,不是因为环境随机发了很多分数,而是因为策略在某些状态下选择了不同的动作,导致后续的回报出现了差距。

所以你在比较“70分轨迹”和“100分轨迹”时,比较的不是奖励本身,而是两条轨迹背后那一串动作的长期效果。100分的轨迹大概率是策略在关键状态下做出了更优的动作,或者刚好避开了某些拖累得分的状态;70分的轨迹则是那些关键节点上动作选择差了一些。PPO要做的,就是利用这两类轨迹的差异,把策略参数往“更容易拿到100分”的方向调整。

但这里有个容易误解的地方:很多人以为PPO会直接对比整条轨迹的总分,哪条总分高就把哪条的动作概率全部抬高。实际上PPO和GAE并不是这么工作的。它们是逐状态、逐动作计算“优势”,然后根据优势的符号和大小去调整对应动作的概率。总分只是一个宏观结果,真正驱动策略更新的是每一个状态动作对的“优势值”。

1.2 高分和低分轨迹,在PPO眼里长什么样

如果把一条轨迹拆开,它是由无数个(state, action, reward, next_state)组成的序列。每个状态动作对都会算出一个advantage,也就是“在这个状态下,执行这个动作比平均水平好多少”。

拿70分轨迹来说,它里面某些状态动作对的advantage可能确实是正的,比如某一步很关键,虽然整条轨迹只有70分,但这一步执行得不错,那PPO不但不会降低它,反而会提高它的概率。反过来,100分轨迹里也可能存在个别不理想的动作,那些动作的advantage为负,照样会被压低。

所以,如果你脑子里想的是“100分的轨迹里所有动作都是好的,70分轨迹里所有动作都是坏的”,那就把强化学习想得过于简单了。轨迹总分比较适合用来判断一个策略的整体水平,但不适合用来逐动作指导更新。真正指导更新的,是最小时间尺度上的优势信号。

这一节还想强调一个训练中特别常见的情况:如果你的环境中,高分轨迹和低分轨迹之间的差距纯粹来自随机性或初始状态好坏,而不是来自策略选择的动作差异,那么PPO理论上无法稳定地把策略推向100分。因为它学不到“哪个动作导致了100分”这条因果链,只能学到一些随机相关性,训练很容易出现原地打转或过拟合某一条幸运轨迹的情况。这一点在后面的常见问题里会展开说。

2. PPO和GAE的更新逻辑:谁在控制“往哪靠”

2.1 策略梯度里最核心的一句人话

PPO说到底是一个策略梯度算法。策略梯度的更新公式可以用一句人话概括:如果一个状态动作对的优势是正的,就提高这个动作的概率;如果优势是负的,就降低这个动作的概率。

用符号写就是:

策略梯度 ∝ E[∇ log π(a|s) × A(s,a)]

这里的A(s,a)就是优势函数。它表示“在状态s下选择动作a,相比平均水平好多少”。如果A是+10,那更新就倾向于让π(a|s)变大;如果A是-5,更新就把这个动作概率压小。

PPO本身并没有改变这个核心方向,它只是在策略梯度外面加了两层保险:一是用重要性采样的比例来控制更新步长,二是用clip限幅防止一次更新太猛导致策略崩坏。所以,真正决定“往哪靠”的,其实是优势函数的值,而不是最终的轨迹得分。

这时候你就明白GAE为什么重要了。GAE的作用,正是把一条轨迹里每个状态动作对的优势计算出来。它考虑的不只是当前这一步的即时奖励,还考虑了后续所有时刻的回报,让每个动作都能获得“长远眼光”的评估。

2.2 GAE把“优势”算成什么样

GAE的全称是Generalized Advantage Estimation,广义优势估计。它先算一个单步的时间差分误差,记作δ:

δ_t = r_t + γV(s_{t+1}) - V(s_t)

这个式子的意思是:当前动作拿到了即时奖励r_t,然后未来状态的预估价值是γV(s_{t+1}),再减去当前状态的价值估计V(s_t)。如果δ_t大于0,说明执行这个动作后得到的实际结果比价值网络的预期要好,这个动作值得鼓励;如果小于0,说明比预期差,应该抑制。

有了单步的δ之后,GAE再把未来很多步的δ按指数衰减累加起来:

A_t = δ_t + γλδ_{t+1} + (γλ)²δ_{t+2} + ...

这里出现了两个关键参数:γ是折扣因子,λ是GAE的衰减系数。λ越接近1,优势估计就越多地考虑未来长远的回报,偏差更低但方差更高;λ越接近0,则更偏重短期估计,方差低但偏差可能更高。

我见过不少人只盯着最终轨迹得分,以为PPO是靠“轨迹奖励高低”来更新。实际上不是。PPO更新是看你每个状态动作对的优势值,而GAE给的正是这个值。评分70和100会先转化为一系列δ_t,再转化成一堆advantage,然后才能指导策略。

2.3 clip限幅:不能一次靠太猛

有了优势值之后,PPO还要用一个比例来控制更新幅度。它先计算新旧策略在同一个状态动作上的概率比例:

r_t(θ) = π_θ(a|s) / π_old(a|s)

如果优势A为正,我们希望r_t(θ)变大,即新策略选这个动作的概率比旧策略高;如果优势为负,我们希望r_t(θ)变小。

但概率不能无限变大,所以PPO引入了clip限幅:

L = E[min(r_t(θ) × A, clip(r_t(θ), 1-ε, 1+ε) × A)]

这个公式里,ε一般取0.2。通俗理解就是:即便某个动作的优势非常大,单次更新也不允许把它的概率比例推到超过1.2倍。这个机制可以防止策略在一次更新中剧烈偏转,避免因优势估计噪声过大导致的训练崩溃。

所以你现在应该有一种感觉:PPO对“往100分轨迹靠”这件事是有限速的。更新方向确实指着高分轨迹,但每一步都走得比较谨慎,既要看优势,又要被clip卡住,还要受学习率影响。这样训练才不会一上来就锁死某一条轨迹。

3. 数值例子:从70和100出发,到底会发生什么

3.1 假设一个最简单的两动作环境

为了把这个问题讲透,我构造一个极简场景。假设环境只有一步:从状态s出发,有两个动作a和b。执行a之后整条轨迹得70分,执行b之后得100分。我们跑了两条轨迹,一条选了a,一条选了b,现在要用这两个样本更新策略。

再假设γ=0.99,λ=0.95,价值网络V刚开始随机初始化,对s的预测值大约是0。那么两条轨迹的advantage分别是:

  • 动作a的优势:A_a ≈ 70 - 0 = 70
  • 动作b的优势:A_b ≈ 100 - 0 = 100

在第一步更新中,由于两个advantage都是正的,PPO会同时提高a和b的概率,只不过b的概率升幅更大。这是因为价值网络还很"懵",它对所有状态都预测低价值,所以任何拿到正常奖励的动作看起来都像是"超预期的好"。于是第一轮更新后,策略并不会立刻放弃动作a,只是稍微偏向b。

这个现象在真实训练中非常常见:刚开跑的前几轮,所有动作都因为价值网络低估而被推高,策略看起来没什么章法,熵也比较高。这不一定是坏事,关键要看后续价值网络能不能及时调整过来。

3.2 第二步之后:价值函数开始区分好坏

继续上面这个例子。随着价值网络不断更新,它开始用实际回报作为回归目标。两条轨迹的平均回报是85,于是V(s)会逐渐逼近85。这时你再算优势:

  • 动作a的优势:A_a ≈ 70 - 85 = -15
  • 动作b的优势:A_b ≈ 100 - 85 = 15

形势就完全反过来了。a的优势变成负数,PPO开始压低a的概率;b的优势保持为正,b的概率继续上升。这个动态过程才是“会往100靠”的正确打开方式:先是高优势把动作区分开,然后价值网络学到平均水平,再把低于平均的动作逐步淘汰。

这也是为什么有些人发现训练初期策略会“乱一阵子”,甚至有时感觉模型在鼓励一些明明是低分的动作。因为价值网络还没拟合好,advantage的符号可能暂时不准。等价值网络逐步收敛,advantage才会真正反映出“哪个动作更好”。所以,判断PPO是否在往高分靠,不能只看前几千步,要给价值网络一些时间。

3.3 所以“会往100靠吗”的完整答案是

基于上面这个例子,我可以给一个比较完整的回答:

会,而且一定会,但靠的是逐步挤出低分动作、抬高高分动作的过程。这个过程需要满足几个前提:

第一,100分轨迹和70分轨迹的差异确实来自动作选择的不同,而不是纯环境随机性。如果是纯随机,优势函数会把这种随机性也当作信号,策略可能会去追一个根本不可控的“伪规律”。

第二,100分轨迹的样本量不能过于稀少。如果100分轨迹在buffer里占比很低,对梯度的贡献即便大,也可能被大量70分样本淹没。可以通过调整收集策略,或者增加总轨迹数来解决。

第三,价值网络要有足够的拟合能力去学到状态的真实平均回报。如果V本身根本拟合不动,那么advantage就会长期充满噪声,策略更新也难以稳定地朝100分靠。

这三点其实是你在调PPO时最容易出问题的地方。很多人盯着reward曲线问“为什么我的PPO不往高分靠”,最后排查下来,往往是这三个前提之一没满足。

4. 实操中让PPO稳定向高分轨迹靠齐的几个调节旋钮

4.1 先处理好reward的绝对尺度

你是不是看到过很多PPO实现里都有一个“normalize advantage”的步骤?这不是画蛇添足,而是对付“有的轨迹70,有的轨迹100”这类情况的关键操作。advantage的绝对数值会影响梯度大小,如果不做归一化,当奖励普遍比较大时,策略更新步长会直接被放大,导致训练很不稳定。

我自己的习惯是,在每次采样完一个batch的轨迹并计算好GAE后,把整个batch的advantage做标准化:减均值、除以标准差。这样即使奖励分布在70到100之间,梯度幅度也能保持在合理范围内。很多成熟框架默认就带这个处理,但我见过有人自己写训练脚本时忘了加,结果学习率调得再小也稳不住。

另外,reward本身也可以做归一化。比如用滑动平均估计奖励的均值和标准差,在训练前先把reward转换成标准分数。但这会改变奖励的绝对语义,需要谨慎使用。如果只是70和100这样的量级差异,通常做advantage标准化就够了。

4.2 GAE里的γ和λ怎么选

很多人在调PPO时会把注意力全放在learning rate上,反而忽略了γ和λ这两个直接决定优势质量的关键参数。在“有70分轨迹也有100分轨迹”的场景里,γ和λ的选择会影响你到底有多信任长期回报。

  • γ是折扣因子,控制“未来奖励”在当前时刻值多少钱。γ越接近1,agent越看重长远回报。如果你的任务是那种早期一个关键动作会决定最终100分的任务,γ建议尽量高,比如0.99或者0.995。
  • λ是GAE的衰减系数,控制优势估计到底看多远。λ偏大(0.98以上)意味着优势会跨很多步传播,适合长程信用分配;λ偏小(0.9左右)意味着agent主要依赖单步TD信号,方差更小但容易短视。

我个人的默认配置是γ=0.99、λ=0.95。如果发现策略老是只盯着局部奖励,拿不到高分,会尝试把λ提到0.98;如果发现训练方差太大、曲线抖得厉害,则把λ降到0.92左右。参数选择没有一个绝对正确答案,最好的办法是拿一两组对照跑一下,看谁的返回值更稳地往高分靠。

4.3 多个epoch更新时,控制靠的节奏

PPO一个典型的特点是,同一批采样轨迹会被用来更新多个epoch。这在样本效率上是好事,但也带来了一个隐患:如果更新步数过多,策略可能会在较旧的轨迹上过拟合,尤其是当高分轨迹比例很少时,策略可能反复咀嚼那几条100分轨迹,把自己锁死在一个局部区域。

为了控制这个“靠”的节奏,我会关注两个东西:一个是clip参数ε,一般设为0.2,如果梯度更新频繁触发clip,说明步长偏大,可以适当调小ε;另一个是更新epoch数,我常用的是5到10个epoch,如果发现策略多样性掉得太快,就减少epoch或者增大mini-batch size。

另外,学习率也不宜太大。PPO本身有clip保护,但学习率过大仍然可能让策略在几次更新内剧烈抖动。特别是在训练初期,价值网络还不准的时候,大学习率会把一些噪声信号也放大,导致策略在那个阶段做出很多与高分路径完全无关的更新。我的经验是,先用较小的学习率把价值网络训练得稍微靠谱一点,再让策略开始大规模朝高分轨迹偏移。

5. 常见问题与排查实录

5.1 策略根本不动,不向100靠

这种情况我遇到时,第一步先看advantage的分布。如果绝大部分advantage都在0附近徘徊,那策略当然没有动力往高分靠。原因通常是价值网络过于强大,已经能准确预测每条轨迹的回报,导致“超预期部分”几乎为0。

解决办法有几个方向:一是提高γ或λ,让优势信号看更长远;二是检查奖励是否被过度平滑,如果奖励本身没有区分度,优势自然趋近于零;三是减弱价值网络的正则化,或者调整价值网络学习率,让它不要拟合得那么快。

还有一种很隐蔽的情况:100分的轨迹在当前策略采样中占比太低。比如采样100条轨迹,只有1条是100分,那它对整体梯度的贡献就很有限。这时候可以考虑在收集轨迹时使用更好的探索机制,或者调整初始策略,让高分轨迹先多出现一些。

5.2 一靠近100奖励就崩溃

这个现象也很典型:策略一开始还正常,后来好像找到了高分轨迹,但没高兴多久,奖励曲线就急剧下滑,甚至比原来70分还低。我这个坑踩过不少次。

出现这种问题的核心原因,是把“个别高分轨迹”当成了“普遍高分路径”。举个例子,你的100分轨迹可能只是环境随机出了一些有利条件,比如初始位置特别好,或者某些随机事件没有发生。策略一旦把概率集中到这种特定条件对应的动作上,后面遇到正常条件时反而拿不到分,整体rewards就崩了。

排查时可以看看高分轨迹的数量占比和高分轨迹对应的初始状态分布。如果高分轨迹全都来自同一种初始状态,那说明策略可能是在“背题”,而不是学会解决任务。这时候需要增加熵正则,鼓励策略继续探索其他状态,而不是过早把概率集中到少数几条路径上。

5.3 70和100来回跳,熵一直降不下去

还有一种情况是策略在70和100之间反复横跳,训练曲线高一下低一下,让人非常难受。这通常不是因为PPO不知道该往哪靠,而是因为优势估计的方差太大。

我遇到时会检查两件事:一个是λ是不是设得太高,因为λ接近1会引入更大的方差;另一个是reward本身是不是存在高频噪声,比如同样的动作有时候给70有时候给100。如果是环境奖励本身不稳定,那再调PPO的超参数也压不住,只能考虑对奖励做平滑或者进行reward shaping。

另外,有些时候增大batch size能显著缓解这种抖动。大batch意味着优势估计用了更多的轨迹样本,平均值更稳定,策略更新方向也就不那么容易被一两条极端轨迹牵着走。我一般会把batch size从默认的2048提到4096甚至8192再对比一下,稳定性往往有明显改善。

最后一点体会

我自己做了不少PPO相关的项目之后,最深的感受是:不要用轨迹总分去直接解释策略行为,而要用advantage去理解策略行为。70和100之间,真正驱动更新的是“超出平均的部分”,而不是那个绝对分数。所以,当你问“会不会往100靠”,正确的做法是去检查那个状态动作对在GAE下算出来的优势是不是为正,以及那个100分轨迹背后的动作模式是否稳定可复现。找到这两点的答案,你就能预判策略会怎么走,也能在它走偏的时候及时抓住原因。实际训练时,我还会把每条轨迹的优势均值和奖励一起打点观察,看到高分轨迹的优势明显为正时,就说明PPO确实在朝正确方向努力了。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进