一文讲清大模型中奖励模型的原理及实现
1 LLaMA 2 奖励模型样本构建
1.1 LLaMA 2训练流程
如图1所示便是 LLaMA 2 的整体训练流程,整体包含两部分:基于通用语料的自监督学习过程以及基于有监督学习微调学习过程,而在有监督的微调过程中又分为基于人工标注对话语料的有监督微调(Supervised Fine Tuning, SFT)过程和基于人类反馈的强化学习微调过程。【AI大模型教程】
图 1. LLaMA 2 训练流程图 [1]
在图1中,奖励模型所处的训练流程便是对 "Llama-2-chat" 输出的内容进行评估得到一个分数,然后这个分数将会作为 RLHF 的输入,最后 RLHF 会根据输入的分数对 “Llama-2-chat” 进行优化,整个流程就是图3中过程①②③①的循环迭代。
同时,在文章「到底是谁提出了大模型中的对齐问题?原来并不是出自 OpenAI」中我们提到,通常奖励模型并不是从零开始训练,而是直接使用一个或多个 SFT 过程中的 ChatModel 作为初始化 [1] [3]。这样做的好处是奖励模型可以和 ChatModel 共享在预训练阶段学习到的知识内容(语言理解、事实知识、常识等),从同样的“知识水平”、同一基线出发 [1]。
因此,奖励模型的网络结构整体同预训练模型的架构一致,只是将最后的分类层替换成了一个回归层用于得分的预测。
这里值得一提的是,由于 LLaMA 2 训练策略的实际需要,所以整个主模型训练过程中一共使用到了两个奖励模型,一个用于让模型生成更符合人类偏好的回答,一个用于让模型输出更符合安全的回答,但是整个构建原理都是一样的。
1.2 标注样本构建
为了让最后的 ChatModel 既能够做到输出更符合人类偏好的回答,同时还能够输出更符合安全规范的回答,在 LLaMa 2 的训练过程中 LLaMA 2 团队 一共训练了两个奖励模型。
对于每个奖励模型来说:① 首先让标注人员写出 Prompt;② 然后使用了两个不同版本的 ChatModel( SFT中不同的 Checkpoint 时间点,目的是为了增加输出结果的多样性)再以不同的温度(关于温度对模型的影响可参见文章「起底 DeepSeek 大模型中常用的模型蒸馏技术!从零实现附源代码!」)分别针对同一个 Prompt 生成一个回答;③ 其次,按照标准标注人员必须在两个答案中选择更好的一个;④ 最后人工再标注这个选择相对于另一个的优势程度(显著/中等/略微/几乎没区别)。
按照以上流程,LLaMA 2 团队一共标注了超过 100 万条条数据集,并且还发现这部分的训练数据越多,训练得到的奖励模型效果就越好,最后微调得到的 Llama 2-Chat 效果也就越好。
最后,得到的标注数据格式形如:
| Prompt | Response A | Response B | 标注结果 |
|---|---|---|---|
| 你好! | 你好! | 你是谁? | A 中等好于B |
| 如何制作炸药? | 制作炸药首先需要购买…… | 该问题涉及公共安全…… | B 显著好于 A |
介绍完 LLaMA 2 中奖励模型训练数据的形式以后,我们再来具体看如何构建目标函数。
2 LLaMA 2 奖励模型目标函数构建
2.1 奖励模型目标函数构建
设奖励模型为 ,其中 表示奖励模型对应的参数, 表示 Prompt , 表示 Response, 共同作为奖励模型的输入。进一步,我们假设对于同一个 Prompt ,根据两个不同版本生成的 Response 分别为 和 ,其中 表示更受人类偏好选择的回答, 则表示被拒绝的回答。
由此可得, 为奖励模型对回答 的打分, 为奖励模型对 的打分。
现在光有了打分,我们如何来训练奖励模型呢?换句话说怎么来根据打分构建目标函数?
由于不同的标注人员对于分数尺度的把控不一样,很有可能同一个样本不同的人标注出的分数会相差很远,所以就需要换一个角度来考虑这个问题。
什么角度呢?
那就是 “我比你好” 这样一个角度。
此时,定义模型认为 优于 的概率为 [2] [3]
其中 为 sigmoid 函数,即
此时,根据式(1)可知
① 当 时, 接近于1;
② 当 时, 接近于0.5;
③ 当 时, 接近于0。
所以,我们希望人类偏好选择回答 的打分比拒绝的回答 要高,即为 优于 的概率 约接近于1越好。
进一步,因为 的输出在 之间,如果直接最大化这个概率那么将会因为差异太小而导致训练不稳定,同时 sigmoid 在两侧的梯度较小,所以进一步会去负对数,即 [1] [2] [3]
根据式(3)可知,因为 的值域为 ,因此概率值越接近于1,那么损失将会趋近于0,而最小化排序损失 就等价于最大化 优于 的概率,这其实也是 Bradley-Terry 模型。这样,便可以放大错误预测的惩罚,让模型更快学习。
因此,如果有 个样本,则式(3)可改写为
此时你会不会已经开始疑惑了?
明明说奖励模型是一个打分模型,怎么最后却是通过交叉熵来构建目标函数?
关于以上整个目标函数的由来的详细过程可以参见文章「OpenAI的这三篇论文告诉你大模型中奖励模型的变迁过程」
2.2 训练样本构建
不过还有一点就是,大家有没有好奇在目标函数(4)中,标签是如何体现的?
为了回答这个问题我们先来看下样本的构建过程。
在第1节中我们介绍了样本标注的4个步骤,下面以三个样本为例进行说明。
-
Prompt 1: "请解释一下量子纠缠。"
模型生成两个回答:A1 和 B1 ;人类标注: A1 显著优于B1。
-
Prompt 2: "请解释一下勾股定理。"
模型生成两个回答:A2 和 B2 ; 人类标注: B2 略微优于 A2。
-
Prompt 3: "请解释一下大模型。"
模型生成两个回答:A3 和 B3 ; 人类标注: A3 和 B3 几乎没区别。
在得到如上所示的三个标注样本以后,我们会直接去掉第三种”几乎没区别“这样的样本;其次,对于”显著“、”中等“和”略微“这样的情况会一视同仁,都直接看成一个答案比另一个号;最后,将好的答案定义为 ,将另一个定义为 来构建样本,如下所示
To train the reward model, we convert our collected pairwise human preference data into a binary ranking label format (i.e., chosen & rejected) and enforce the chosen response to have a higher score than its counterpart [1].
① 为”请解释一下量子纠缠。“, 为 A1, 为 B1;
② 为”请解释一下勾股定理。“, 为 B2, 为 A2;
也就是说,我们在对 和 进行定义排序的时候,这就是标注正确标签的过程,所以它不是数值,而是一个偏好顺序(Preference)。
当然,我们也可以在构建目标函数的时候充分利用答案之间的差别来更好的训练模型。
2.3 目标函数优化改进
为了在训练奖励模型的过程中得到一个更好的效果,让它更好的区分 和 ,在式(3)的基础上通常还会再加上一个边际(margin)值,即
其中 是一个离散的状态函数,随状态 的变化而变化,表示边际值(margin)。
从式子(5)可以看出,在获得同样的置信概率 的时候,相较于没有施加边际值的情况,加入边际值以后 和 将会有更大的区分度。
下面我们简单说一下 。
直白说就是 不是一个固定值,而是对于不同的情况(显著/中等/略微/几乎没区别)给出不同的边际值。例如
其中 是一个基础的边际值,可以理解为“默认的间隔”; 是一个调节因子,决定在不同的状态下边际值要不要放大、保持不变、缩小,甚至去掉。例如它是离散取值可以是 ,这意味着边际值为
- A 显著好于 B 时,放大边际,;
- A 中等好于 B 时,保持边际,;
- A 略微好于 B 时,减半边际,;
- A 几乎没区别于 B 时,无边际,。
那为什么要这么设定呢?
因为对于不同的样本难度或者类别之间的关系不同,需要动态边际才能更稳定地收敛,即
- 对难样本 给大的边际值,强制拉开更大距离。
- 对简单样本 给小的边际值,避免过拟合。
所以 其实是“自适应的间隔”,不是一刀切。
当然, 也可以是一个固定的值,保持所有情况下使用同一个边际值。
说到这里大家有没有发现式(5)中的边际值和我们之前介绍过的哪个式子中的值很类似?
想起来了吗?
……