©PaperWeekly 原创 · 作者 | 张逸骅
单位 | 密歇根州立大学博士生
研究方向 | 可信人工智能
如果你对大语言模型(LLM)的强化学习(RLHF)感兴趣,又想从最基础的策略梯度优化一路了解、推导出 PPO、GAE,再深入探讨 DPO,那你就来对地方了。
本文将从最基础的 Gradient Policy Optimization 开始,逐步介绍经典的 REINFORCE 算法,再讲解如何利用剪切目标实现近端策略优化(PPO),并通过广义优势估计(GAE)在偏差与方差之间找到最佳平衡。之后,我们还会从头推导、讨论离线训练方法,如 DPO,帮助你了解不同训练路线的优势与挑战。
在线(On-Policy)和离线(Off-Policy)强化学习
如今,LLM 中主流的 RLHF 方向分为两大路线:
以 PPO 为代表的 On-Policy 路线
以 DPO 为代表的 Off-Policy 路线
那么,什么是 On-Policy,什么是 Off-Policy 呢?可以用一个简洁的判定方法:
On-Policy:训练过程中,需要模型亲自参与“生成”来收集新的数据样本。
Off-Policy:训练过程中,不需要“在线”生成,更多依赖事先收集到的(或由别的策略产生的)数据进行离线学习。
一般来说,On-Policy 的方法在训练时会更“耗卡”、更耗时——最大的开销主要是源自“模型生成”这一步,因为对一个生成式任务而言,模型需要逐 token 地输出,这个过程极其耗费算力。
不过,尽管速度较慢,On-Policy 在理论上拥有更高的效果上限,因为它能够不断根据当前模型状态进行探索和更新,这一点将在后续讨论 PPO 时更加凸显。
我们首先来谈谈 On-Policy 路线。On-Policy 的核心思路是:让模型自己产出答案,然后依据答案的优劣来打分,以此指导下一步的参数更新。简而言之,最关键的一点是让模型“亲自下场”。
假设你是一个需要学会下象棋的模型,现在有两种训练方式:
方式一:让你真刀真枪地下棋,每一步都有教练跟在你身边打分。当你吃掉对手棋子时,教练会鼓励你;当你因为冲动失误被对面反杀时,教练会及时提醒你改进。
方式二:给你一堆职业选手的比赛录像和一堆臭棋篓子的对局,用标注告诉你哪些操作是好招,哪些操作是坏招,然后你被动地学这些好操作、避免坏操作。
这两种方式最大的区别就在于:你有没有亲自去“下棋”。方式一就是 On-Policy,需要模型自己产出行为,然后学习;方式二就是 Off-Policy,只需根据已有对局数据进行模仿式学习。
Off-Policy 在训练时通常更快,因为它用现成的数据就可以了,不需要模型时时在线生成并等待打分,但也很依赖这批数据与当前模型能力的“匹配度”。如果数据中操作难度和模型水平相差太大(过高或过低),学习效果就可能大打折扣;On-Policy 则可以避免这一问题,因为它所得到的训练样本 100% 来自于自己当前的水平和行动。
在语言模型场景中,一个典型的 On-Policy 算法往往包含以下组件:
Actor:负责“生成”句子的模型(就像正在对弈的你)。
Critic:类似于“教练”,为每个生成结果提供即时指导;它本身也在训练过程中随 Actor 的能力变化而调整。
Reward Model:相当于“裁判”,给出最终分数或偏好评估。通常在训练过程中是固定不动的。
Reference Model:PPO 在大模型里的“独有角色”,用来防止 Actor 过度偏离原有预训练分布,缓解 reward hacking 等问题。
由于在大型 LLM 上,这四个部分的参数量都可能非常庞大(往往需要同时加载多个 70B 参数规模的模型),所以 On-Policy 训练往往带来极高的算力需求,这也是为什么人们通常说 PPO“非常耗卡”的原因。
下一步,我们将把目光聚焦在当前 On-Policy 路线最具代表性的方法——PPO 上,看看它究竟如何在实践中平衡训练开销与学习效率。
PPO(近端策略优化)
2.1 从策略梯度优化(Policy Gradient Optimization)谈起
想象一下,你是一名刚开始学习下象棋的新手。你的目标是通过不断调整你的下棋策略(记作 ,其中 表示你的策略参数),来提高在一局棋中获得胜利的概率,也就是最大化你的期望回报。我们可以将每一盘棋看作是一条轨迹 ,而你要做的,就是通过不断优化你的策略来获得更高的回报。
更一般得,强化学习的目标就是去优化一个策略,使得回报的期望最大:
形式上, 这个策略的回报被定义在所有可能的轨迹上:
所谓的轨迹,就是一连串状态和对应动作的组合(state,action):
在下棋这个例子中,状态 可以理解为当前棋盘落子的状态,而动作 即为下一次落子的地方。而当前时间点的下一个状态,则服从某种概率分布,可以被看作是随机的、不确定的(即对手落子):
那么一个轨迹 的概率则为:
在强化学习中,我们会不断提到回报会随着时间不断打折 (discount reward) 的概念:未来的回报总是不如当下的回报那么重要。所以一个策略 的总回报可以被视作:
其中 是时间上的折扣因子,而 是 时刻的实际回报。
在深度学习中,我们通常采用最小化损失函数来更新参数,这正是随机梯度下降(Stochastic Gradient Descent)的做法。但在这里,我们的目标是最大化回报,因此我们使用随机梯度上升(Stochastic Gradient Ascent)来更新策略:
这里的 就被称为策略梯度(policy gradient)。换句话说,就好比每盘棋结束后,你会复盘,评估自己每一步走法对最终胜负的贡献,然后调整下一盘棋的策略。这样的更新方法统称为策略梯度算法(policy gradient algorithms)。
然而,正如在下棋时要考虑所有可能的走法和局面一样,精确计算这个梯度需要对所有可能棋局(轨迹)进行求和或积分,而这在实际中(除非棋盘极其简单)是计算上不可行的,因为即使你拥有可导的 ,由于轨迹的步数太多,在使用 auto-differentiation 求导过程中会因为 memory 太大而使用非常受限。因此,我们需要仔细思考一下怎么求这个策略梯度。
策略梯度的推导
为了得到一个可操作的策略梯度公式,就像在复盘中总结经验一样,我们从目标函数的梯度开始推导。将每盘棋视为一条轨迹 ,目标函数梯度为:
第1步:展开期望(Expand the Expectation)
这一步相当于考虑所有可能的棋局,我们将期望展开为对所有轨迹的积分:
第2步:交换梯度与积分(Interchange Gradient and Integral)
就像把每一步棋的影响拆分出来,我们将梯度操作符移入积分内部:
第3步:使用对数导数技巧(Apply Log-Derivative Trick)
利用一个数学技巧(对数导数),类似于在复盘中分解每一步的重要性,我们有:
第4步:回到期望形式(Return to Expectation Form)
最终,我们可以把上面的积分重新写成期望的形式:
分解
在下棋的过程中,每盘棋的走法取决于你每一步的决策。假设一盘棋的轨迹 可表示为:
这里 就是你在棋局某一时刻(状态 )下选择某一步棋(动作 )的概率。取对数后求梯度,我们得到:
(注意:棋局中对手的反应 由规则决定,与 无关,因此其梯度为零。也就是说,当 给定时, 也就定下来了。)
2.2 最终策略梯度公式(Final Policy Gradient Formula)
把上面的结果代入期望,我们最终得到的公式是:
在这条公式中,每一步棋的决策()决定了整盘棋的表现,而不依赖于对手的固定规则。实际操作中,我们通常使用蒙特卡洛抽样来近似这个期望,就好比你通过大量实战积累经验来提升下棋水平。最后,基于采样的策略梯度可以由以下式子近似:
如果你仔细观察这个式子,你会发现很有意思的两个地方。首先 直接出现在策略参数的梯度里边。
2.3 REINFORCE 算法流程与实现步骤
下面介绍经典的策略梯度方法——REINFORCE 算法,它就像你通过不断下棋、复盘总结经验来不断改进你的棋艺:
1. 策略网络构建
搭建一个神经网络来定义你的下棋策略 :
输入:当前棋局状态
输出:根据当前棋局生成下一步棋的概率分布
2. 轨迹采样
用当前策略进行对局(采样轨迹 ),并记录每步棋得到的奖励(例如赢棋后的奖励分数)。
你可以设定每盘棋固定步数(比如 100 步),或直到比赛结束。
3. 梯度计算
根据收集到的对局数据集 计算梯度估计,就像总结每盘棋中各步对胜负的贡献:
4. 参数更新
使用随机梯度上升法更新你的策略参数,就好像根据复盘结果调整你的下棋风格: