:Policy Gradient,PPO及PPG
那一天,我被Policy Gradient狠狠揍了一顿
五年前,我第一次碰强化学习。
不是在学校实验室,不是在刷LeetCode,而是在一个机械臂抓取的项目里。Team里大佬开会拍板:“先上Policy Gradient。”
我说好,干就完事了。
结果呢?写完了REINFORCE,一跑——天啊,直接原地爆炸。训练两小时,奖励曲线纹丝不动,偶尔抽风跳上去一点点,下一个step就狠狠摔回谷底。
我还天真地以为是参数没调对。后来才知道——不是我菜,是这个算法它真的会崩。
你敢信?一个号称“革命性”的算法,跑十万个episode,动作还是乱的,跟喝醉了酒似的东倒西歪。
从那以后,我算是跟策略梯度杠上了。从REINFORCE一路折腾到PPO,中间踩的坑排成队,能绕办公室两圈。
今天这篇,不跟你扯那些天花乱坠的公式推导。就想跟你聊聊,实战里这些算法到底是怎么回事,哪里会翻车,哪里你得绕着走。
一、原始PG:双刃剑,剑刃还对着你
说到Policy Gradient,网上一堆教程上来就甩公式。
∇J(θ) ∝ Σ ∇logπθ(a|s) · Gt
字面意思很好懂:这一局回报高,就把所有动作概率往上推;回报低,就往下压。
听起来没毛病,对吧?
但实际操作起来——我给你讲,坑死你。
最大的问题是什么?方差高到离谱。你同一组参数跑十局游戏,奖励能从-200飘到+200。你都不知道是策略变好了,还是随机种子开了个极品挂。
我当时拿Pong验证,batch size设32,跑了一整晚,策略就是学不会接球。
你说挫败不挫败?
后来换成A2C,半天就出效果了。
所以,要我说,原始PG不加baseline等于白送。
几乎所有教程都会提一句“减个baseline能降方差”,但很少有人拍着桌子告诉你:不加上去,这玩意儿就是废的。
我那个机械臂项目,试过不加baseline的版本。十万个episode啊!动作还是乱的,像一只不知道自己在干嘛的手。加了状态价值V(s)之后,终于看见那条曲线慢慢抬头了。
所以你要玩PG,第一条铁律:用优势函数A(s,a)代替Gt。
A(s,a) = Q(s,a) - V(s)
翻译成大白话就是说:“你这个动作比平均好多少?”
比baseline高的,提概率;低的,反向压制。
这才是现代PG能用的唯一原因。
二、PPO为什么能火?因为它怂得有道理
你想想,PG更新步长这事有多烦。
调小了,学不动;调大了,直接崩。Adam算个屁,学习率一高,送你个“梯度爆炸全家桶”。
后来TRPO出来了,用KL散度做约束,理论上稳得像泰山。
但问题来了——你自己写一遍试试?
要算二阶导,要搞共轭梯度,还得做线搜索。我试过一次TRPO,光配环境就配了两天。跑起来还巨慢。
谁在生产里用这个?不是给自己找罪受吗?
然后PPO就来了。
2017年,Schulman那篇paper发出来。我读完第一反应是:啊?这么简单也能发文章?
核心就一个clip操作,把更新权重限制在[1-ε, 1+ε]之间。说白了,就是不让一次更新太猛。
就这么一个小动作,效果直接爆炸。
我用PPO跑过连续控制,也训过文本对话模型。最常用的版本是PPO-clip,配合GAE,设4到8个并行环境,整个训练过程稳得像一条直线。
有个细节我特别想告诉你:Actor和Critic的loss权重,别直接用1:1。
为什么?因为Critic学得太慢,Advantage的估计就不准,Actor更新就容易偏。
我的习惯是设成0.5:1,然后再把Critic的学习率提一倍。效果明显改善。
而且PPO的实现真的很简单。你去翻Stable Baselines3的源码,核心代码也就几十行。用PyTorch跑Atari,默认超参(clip=0.2,lr=3e-4,gae_lambda=0.95)就已经能吊打大部分内置AI。
我之前做人脸表情控制器项目,同样算力预算下,PPO比A2C快了将近一倍达到同等奖励。
说到这儿你可能会问:PPO这么强,它的秘诀到底是什么?
我告诉你——不是数学多漂亮,是它容错率高。
你参数稍微偏一点,不会暴毙;代码乱改几行,也不会立马崩溃。
对工程人员来说,这就是天大的福音。
三、PPG:拆开策略和价值,各玩各的
你可能会想:PPO都这么强了,还有必要折腾PPG吗?
我认真回答你:看场景。
PPG是2019年出来的,全名叫Phasic Policy Gradient。它干的事很简单——把PPO里Actor和Critic的同步更新拆开了。
分成两个阶段:
1. 策略阶段:正常做PPO更新,只优化Actor,不管Critic。
2. 辅助阶段:固定Actor,用off-policy的方式去优化Critic,还能混入额外目标。
这思路在当时挺新鲜的。因为PPO里你有平衡Actor和Critic的共轭关系。经常是你Actor已经改了,Critic还停在原地,导致Advantage跟不上了。
PPG直接说:别绑在一起了,各学各的,互不干扰。
就像一段婚姻,天天绑在一起反而容易吵。适当有点空间,各自成长,反而更健康。
我在Atari Pong上试过PPG的实现。效果和PPO差不多,甚至略好那么一丢丢。但样本利用率上,PPG明显更胜一筹——它可以在更少的交互里学到更好的Critic。
不过我踩了一个坑:如果辅助阶段更新次数太多,Critic被训得太好,Actor反而跟不上了。
你需要调一个叫E_pi的超参,控制两阶段的比例。我试了好几轮才找到合适的,最后设在2。也就是说每N步策略更新后,做一次Critic辅助更新。
现在很多人说PPG被PPO淘汰了。
我不这么看。
至少在分布式训练场景下,PPG的设计更灵活。你看Rlib的APPO,说白了就是借鉴了PPG的思想——把策略和价值网络分开存,异步更新。
我自己搭过一个基于Ray的上千环境并行系统,底层用的就是APPO。训练速度比同步PPO快了不止一个量级。
四、从PPO到RLHF:你以为的万能药,有时候是毒药
最后聊一个最近特别火的话题——RLHF。
OpenAI在InstructGPT里用的就是PPO来对齐语言模型,这让PPO的名气直接破圈。
很多人以为PPO是RLHF的唯一解。
不是的。
我实际复现过LLaMA的PPO训练。跟你说几个真实问题:
第一,reward模型训得不好,PPO直接废掉。
第二,语言模型的softmax分布极其敏感。clip值设0.2?经常KL过大,然后崩盘。
我在文本生成任务里把clip降到0.1,KL惩罚系数设为0.04,才勉强稳住。
第三,效率太低了。PPO需要同时维护策略网络、价值网络和reward网络。显存消耗大得惊人。我用单卡A100,只能训7B模型。再大?得上模型并行。
更有意思的是——研究者发现,Vanilla Policy Gradient(REINFORCE)在LLM上反而表现更好。
你说讽刺不讽刺?
一个被原始PG伤害过的人,兜兜转转回来,发现伤害你的那个算法,换了个场景居然成了最优解。
仔细想想也不难理解。LLM的输出是序列,每个token的reward都不好定义。用GAE估计Advantage?完全是玄学。
而REINFORCE呢?直接用整条序列的reward。虽然方差高,但你采样个32条轨迹取平均,再配合baseline,结果居然比PPO更稳定。
所以千万别迷信PPO万能。
我遇到过一个场景——王者荣耀出装推荐。离线数据巨多,完全不适合on-policy。最后用SAC,把PPO按在地上摩擦。
每个算法都有自己的舒适区。你要做的,是帮它找到对的地方。
五、往后三年,我赌PPO仍然是工程基线
新算法再花哨,也要先在PPO的baseline上比一比。
但我看到两个趋势正在发生:
第一,PPG类的分离式训练会渗透到更多框架里。尤其是在大规模分布式场景,异步、分离的价值网络几乎成了标配。
第二,离线策略结合采样高效方法(比如SAC、Dreamer)会跟PPO抢饭碗。尤其是在数据贵的场景下——因为你不可能什么都得上机器人跑一圈。
另外,多模态大模型的Alignment可能会催生新的策略梯度变种。on-policy的成本实在太高了。
你看最近出来的GRPO、DPO,本质上都是想法设法绕开显式的value function和reward model。理论上没脱离PG的框架,但实操上已经简化了太多。
实话实说,现在入强化学习的新手,我给你的建议就是:
把PPO吃透。看懂原理,手写代码,跑一个完整的项目。
之后再去理解PPG、SAC、DPO。
千万别一上来就怼TRPO。
你会配环境配到怀疑人生的。
说到这儿,我想起当年那个机械臂项目。
导师后来对我说了一句话,我现在都记得特别清楚:
“你要学的不是算法本身,是它什么时候该用,什么时候别用。”
哎,这行咱们都是一路踩坑过来的。踩多了,自然就懂了。
不过你猜怎么着?
踩坑最大的收获,不是学会了怎么避开坑。
而是当你有一天终于跑通的时候,那种从谷底爬上来、拍拍土咧嘴一笑的感觉——
比什么公式都值。
说到底,算法哪有什么对错,只有适合不适合。
而你,就是那个帮它找到对的地方的人。
读者评论 3