PPO经验碎片

PPO的过程就像所有的强化学习一样,从原始的采样分布出发,不断循环3个步骤:采样、奖励、优化(policy gradient)。结合提前训练好的人类偏好模型得到奖励信号,从而实现与人类偏好对齐的目的。

ppo算法提出是在2017年,应用在语言模型上的相关工作最早发表于2019、2020年(Fine-Tuning Language Models from Human PreferencesLearning to summarize with human feedback),并且后续相关的多个开源代码并未有大改动。然而后来者仍然在使用ppo实现对齐偏好的效果上挣扎,由此可以猜测该技术的应用难度要高于技术难度,而公开的论文中只给出一些实验性质的浅层说明,真正的核心隐藏在只言片语中,需要后来者结合实践慢慢发掘。因此本文尝试将实践中获取到的一些认知记录下来,给后续的技术应用作为参考。

PPO训练的条件

从ppo的流程来看,一共分为3个阶段:采样、奖励、优化。优化阶段主要是算法的事情,比如说一些trick和参数调整,在个别任务中可能参数调节非常的敏感,但总的来看一个稳定的版本在大多数情况下是够用的。这些trick和参数在开源的工作中都可以见多,基本上都是大同小异。反而是在ppo看来2个固定的环节:采样和奖励,对最终的效果影响最大。采样的模型来自于sft的训练结果,奖励来自于训练好的偏好模型,前者决定了ppo的理论上限,后者决定了ppo的实际训练上限。

总的来说,想要通过ppo提升模型的能力,需要保证2个条件:

  1. 足够的采样空间;
    • 考虑一个极端的情况,如果每次采样的结果相差都不大,那么很快critic-actor会收敛到稳态(critic预测的value接近真实的q-value,advantage接近于0,actor loss接近于0);
    • 如果把ppo理解成在sft的采样空间里做熵减,那么采样空间的范围就决定了ppo可以达到的上限;
    • 另外,如果sft的熵足够低,那么意味着采样会非常集中,从效率的角度其实是不利于强化学习训练的,因为agent探索的效率很低,导致模型难以收敛。
  2. 在采样空间上保证一定的准确率;
    • ppo根据奖励和KL散度惩罚来调整对应生成字符的概率分布,所以准确率很重要;
    • reward model的泛化性很重要,因为随着ppo的训练,采样分布一直在变;
    • KL惩罚因子一定程度上保证了rm在采样空间上的准确率。

SFT采样空间衡量

因为ppo是从sft开始训练的,并且其过程依赖于采样的多样性,所以衡量采样空间的大小能从感官上预测ppo模型的训练效果。

实践中可用的指标包括以下5个:

  • entropy of next token probability; 下一个字符概率分布的熵
  • distribution of reward score; 采样分布上奖励值的分布
  • maximum next token probability; 下一个字符的最大概率值
  • sampled token probability; 采样token的概率值
  • number of possible token; 可采样token的数量

正则化reward score

上图中记录了一次ppo训练过程中的多个reward score分布,几乎看不到有任何的变化。

因为reward score分布其实是2个变量的叠加分布,即:不同case上得到的reward score的分布 + 同一case上生成不同case的reward分布。我们希望用同一case上生成不同case的reward分布来反应采样空间的大小,所以采用以下正则方法。

正则方法:reward norm = reward - mean reward from same prompt + global mean reward

正则后的reward score分布一定程度上可以反应出模型采样空间大小,且同一case上的reward范围直接影响ppo的学习效果,因此是一个比较重要的指标。

影响因素

生成参数

在ppo采样过程中主要用到的生成参数是temperature、top_k、top_p,整体来说影响不大的是temperature,但是增大到1以上会引起模型性能急剧下降,其余参数top_p, top_k影响比较小。

不同epoch的sft模型

在SFT过程中,随着训练epoch的增加,sft的训练数据上的生成概率分布熵会不断的减小,并且不断的接近熵的下限,即 model collapse模式塌陷。

一般我会用模型生成的答案对应的reward的分布密度图去衡量不同epoch之间的差异,选好sft的epoch是非常重要的一步。因为我们要保证ppo过程中的生成多样性,所以要保证初始化模型在ppo训练数据上的熵足够大。

下图有一个密度图。

当然,sft的熵降低的程度也取决于训练数据的分布。

RM准确率

reward model的准确率,指的是rm打分的偏序关系和人工标注相同的概率。因为ppo依赖于正确的reward奖励进行训练,所以rm在ppo训练过程中的准确率决定了其在人工标注上提升的上限。

从实践出发,一方面要在不同版本的sft采样空间上保持高准确率;另一方面在ppo训练过程中保持准确率。前者在sft上不断采样,并且通过rm的自测,应该是可以保证的;而后者是比较难实现的,因为rm对ppo采样的数据占比比较少;另外,在ppo训练过程中有没有有效的手段能够检测reward模型的准确率呢?

一个简单的方法就是尽量多的从ppo模型上采样,并且持续迭代RM的训练数据。ppo的采样至少要提到和sft一样多的比例,这样才能保证训练过程中reward有一个比较稳定的准确率。

那么在ppo训练过程中,有没有办法能够检测当前PPO采样空间下rm的准确率呢?

  1. reward score的分布的方差;

    是ppo-max的论文里首先提出来的。

在实际中我并没有发现这种大范围的长尾分布,但是确实在一些常见的失效模式上发现了分布方差的变化。下面几个图记录了几组不同的ppo训练过程中,reward 分布的变化。

这种检验方式不太敏感,只能发现一些比较大的失效模式,比如说rm的漏洞、kl散度过大,对于rm准确率下降无明显反应,如上图左1所示。

  1. GPT4打分;

    因为目前reward model训练数据的打分也来自于gpt4,所以用gpt4去监测reward model在当前ppo采样空间上的偏序关系准确率,也是比较可行的一种方案。

  2. 标注偏好数据测试集上的logp对比;

    标注过的偏好数据可以和人类偏好对齐,通过logp的对比可以得出choice和reject答案对应的概率,如果choice的概率更高则认为是正确,通过logp可以得到一个准确率。

ppo收益比较小的原因

原因一:采样空间太小

ppo如果要提升模型在reward model上的分数,那么依赖于在采样空间内做熵减。但是如果采样空间本来已经很小,那么ppo的上限就被确定了。

对于一个固定大小的模型,我们观察到的是它是有熵的下限的,也就是不管用sft或者ppo,只要达到了这个下限,就很难去继续做熵减了。这可以解释一种普遍的认知,大量的标注数据+sft可以一定程度代替RLHF。

单从熵减的角度,目前看来sft和ppo的效果是一样的,也就是说,在固定的数据范围内,如果sft已经把熵推到了极限,那么ppo很难在上面做到效果,不管算法细节怎么变。

原因二:数据集选择

我认为相对于sft,ppo很重要的一点优势就是可以在更大的范围上优化。因为ppo从采样中学习,即使拿到的sft在某类数据上没有学习的很好,只要它可以在采样中有个别比较好的答案,都可以学习优化。这点虽然sft也可以通过采样数据质检得到,但是效率的上限一定弱于ppo。

而目前ppo在做数据上关注的是维度对齐,但是我们使用的数据范围仍然在sft的数据范围里面。sft在自己训练数据上采样的平均熵是0.12 ,在ppo的训练数据上采样的平均熵是0.19,差距非常小。通过这个数据,可以说明sft在ppo的训练数据上也拟合的很好了。

也就是说,本来ppo有更快实现泛化的能力。

如何解决

我们可以想一个问题:为什么OpenAI和Anthropic可以用ppo去不断迭代模型呢?

最重要的一点,这2个工作中ppo用的指令数据都是来自线上用户,意味着每次新的训练指令中都用之前没有见过的指令(至少在相当长的一段时间,新指令的占比是比较高的)。预训练模型在经过sft后可以解决一个小范围的问题,随着迭代这个范围的圈子不断增加。与sft差别较大的指令数据集上,模型的采样空间会增大,从而保证了ppo继续训练的上限。

另外,选用ppo迭代侧面说明,ppo有比sft更高的迭代效率。支持这点的要素有:

  1. RM模型规模更小,意味着RM过拟合的风险低,泛化性更好;
  2. 因为泛化性好,所以有更长的迭代周期;
  3. 众所周知,PPO不需要答案数据进行训练,数据利用率更高;

总而言之,解决思路就是 先找到ppo可以学习的范围,然后发挥ppo的迭代效率。这里面核心观点是要改变ppo初始化sft的采样空间,以下是几个具体的点:

数据集

在sft的基础上要扩大ppo数据范围,对于sft已经拟合比较好的场景,数据需求少一点,其他未拟合场景上需求多一点。这里说的数据范围,包括大的维度,也包括指令格式和内容等。

初始化sft

就算是在sft的训练数据上,训练过度也会导致过拟合,降低在训练数据范围上的泛化性,所以ppo选择的sft版本应该应该在一个平衡点上。

如何选择这个点,可以类比强化学习里的探索和利用,如果ppo学习的范围是不同于sft的,我们希望agent可以更多去探索,选靠前的epoch;反之亦然。

感想

PPO算法的作用就是,降低采样分布中低分区域的概率密度,增大高分区域的概率密度,以最大化可以获得的奖励。从这个角度理解,PPO的本质就是在agent的采样空间上面做熵减的过程。

当一项新的技术提出来以后,往往人们对它的效果会过度的预估,而真正在应用过程中一些工程细节往往才是制约它发挥的决定性因素,比如:工程实现、针对业务的调整、甚至高效的分工。但是,我依然认为技术没有好坏,只有合不合适。

相关推荐
蓑 羽1 分钟前
力扣438 找到字符串中所有字母异位词 Java版本
java·算法·leetcode
源代码:趴菜4 分钟前
LeetCode63:不同路径II
算法·leetcode·职场和发展
儿创社ErChaungClub19 分钟前
解锁编程新境界:GitHub Copilot 让效率翻倍
人工智能·算法
前端西瓜哥23 分钟前
贝塞尔曲线算法:求贝塞尔曲线和直线的交点
前端·算法
小灰灰爱代码31 分钟前
C++——求3个数中最大的数(分别考虑整数、双精度数、长整数的情况),用函数模板来实现。
开发语言·c++·算法
南加第一划水34 分钟前
Leetcode 每日一题:Evaluate Division
算法·leetcode·职场和发展
逝去的秋风1 小时前
【代码随想录训练营第42期 Day61打卡 - 图论Part11 - Floyd 算法与A * 算法
算法·图论·floyd 算法·a -star算法
zero_one_Machel1 小时前
leetcode73矩阵置零
算法·leetcode·矩阵
青椒大仙KI112 小时前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^2 小时前
lodash中_.difference如何过滤数组
javascript·数据结构·算法