51c大模型~合集23
我自己的原文哦~ https://blog.51cto.com/whaosoft/11656919
#第一性解释
可解释性终极追问,什么才是第一性解释?20篇CCF-A+ICLR论文给你答案
本文作者为张俊鹏、任启涵、张拳石,其中张俊鹏是张拳石老师的准入学博士生,任启涵是张拳石老师的博士生。
本文首先简单回顾了『等效交互可解释性理论体系』(20 篇 CCF-A 及 ICLR 论文),并在此基础上,严格推导并预测出神经网络在训练过程中其概念表征及其泛化性的动力学变化,即在某种程度上,我们可以解释在训练过程中神经网络在任意时间点的泛化性及其内在根因。
一、前言
长期以来,我们团队一直在思考可解释性领域的一个终极问题,即什么才是解释性领域的第一性原理?所谓第一性原理,目前没有一个被广泛接受的框架,世上本无路,我们需要逐渐去定义这样一个路。我们需要在一个新的理论体系中,提出大量的公理性要求,得出一个可以从不同的角度全方位精确严谨解释神经网络内在机理的理论。一套理论系统能严谨解释神经网络的方方面面才叫 “第一性原理”。
如果你真的在严谨地做 “科学”,那么第一性原理一定不是想象中简单,而是一个复杂的体系,需要研究照顾到深度学习中方方面面纷繁复杂的现象。当然,如果你主观上不愿意或者不信一个理论需要足够严谨,那么研究会变得简单千万倍。就像物理学的标准模型一定比牛顿定律复杂,取决于你希望走哪条路。
沿着这个方向,我们团队独立从头构建了『等效交互可解释性理论体系』,并基于此理论,从三个角度来解释神经网络的内在机理。
1. 语义解释的理论基础:数学证明神经网络的决策逻辑是否可以被少量符号化逻辑所充分覆盖(充分解释)。『证明神经网络的决策逻辑是否可以被有限符号化逻辑解释清楚』这一命题是解释神经网络的根本命题。如果此命题被证伪,则从根本上讲,神经网络的可解释性将是无望的,所有的解释性算法只能提供近似的解读,而无法精确地覆盖所有的决策逻辑。幸运的是,我们找到了在大部分应用中神经网络都可以满足的面向遮挡鲁棒性的三个常见的条件,并且数学证明了满足这三个条件的神经网络的决策逻辑可以被写成符号化的交互概念。
参见 https://zhuanlan.zhihu.com/p/693747946
2. 寻找性能指标背后的可证明、可验证的根因:将神经网络泛化性和鲁棒性等终极性能指标的根因拆分具体少数细节逻辑。对神经网络性能(鲁棒性、泛化性)的解释是神经网络可解释性领域的另一个重大问题。然而,目前人们普遍认为神经网络性能是对神经网络整体的描述,而神经网络无法像人类一样将自己的分类判断拆解成具象化的、少量的决策逻辑。在这方面,我们给出了不一样的观点 —— 将性能指标与具象化的交互之间建立起数学关系。我们证明了 1. 等效交互的复杂度可以直接决定神经网络的对抗鲁棒性 / 迁移性,2. 交互的复杂度决定了神经网络的表征能力,3. 并解释神经网络的泛化能力 [1],和 4. 解释神经网络的表征瓶颈。
- 参见1:https://zhuanlan.zhihu.com/p/369883667
- 参见2:https://zhuanlan.zhihu.com/p/361686461
- 参见3:https://zhuanlan.zhihu.com/p/704760363
- 参见4:https://zhuanlan.zhihu.com/p/468569001
3. 统一工程性深度学习算法。由于缺少基础理论的支撑,目前深度学习算法大都是经验性的、工程性的。可解释性领域的第一性原理应该可以承担起将前人的大量工程性经验总结为科学规律的任务。在等效交互可解释性理论体系下,我们团队既证明了 14 种不同的输入重要性归因算法的计算本质在数学上都可以统一写成对交互作用的再分配形式。此外,我们还统一了 12 种提升对抗迁移性的算法,证明了所有提升对抗迁移性算法的一个公共机理是降低对抗扰动之间的交互效用,实现了对神经网络可解释性方向大部分工程性算法的理论凝练。
- 参见1:https://zhuanlan.zhihu.com/p/610774894
- 参见2:https://zhuanlan.zhihu.com/p/546433296
在等效交互可解释性理论体系下,我们的团队在之前的研究中已经成功发表了 20 篇 CCF-A 类和机器学习顶级会议 ICLR 论文,我们已经从理论和实验上充分解答了上述问题。
二、本文研究概述
沿着上述理论框架,在这篇知乎文章中,我们希望精确解释出神经网络训练过程中泛化性的变化规律,具体地涉及两篇论文。
- 1.Junpeng Zhang, Qing Li, Liang Lin, Quanshi Zhang,“Two-Phase Dynamics of Interactions Explains the Starting Point of a DNN Learning Over-Fitted Features”,in arXiv: 2405.10262
- 2.Qihan Ren, Yang Xu, Junpeng Zhang, Yue Xin, Dongrui Liu, Quanshi Zhang,“Towards the Dynamics of a DNN Learning Symbolic Interactions” in arXiv:2407.19198
图 1:两阶段现象的示意图。在第一阶段,神经网络逐渐消除中高阶交互,学习低阶交互;在第二阶段,神经网络逐渐建模阶数不断增大的交互。当神经网络训练过程中测试损失和训练损失之间的 loss gap 开始增大时,神经网络恰好也进入训练的第二阶段。
我们希望在等效交互框架里提出新的理论,精确预测出神经网络每一个时间点上神经网络所学到的交互概念的数量、复杂度,以及泛化性变化的动力学规律(如图 1 所示)。具体地,我们希望证明出两方面结论。
第一,基于前人的证明(一个神经网络的决策逻辑可以被严格解构表示为几十个交互概念效用的和的形式),进一步严格推导出在整个训练过程中,神经网络所建模的交互效用的变化动力学过程 —— 即理论需精确预测出在不同训练阶段,神经网络所建模的交互概念的分布的变化 —— 推导出哪些交互会在哪个时间点上被学习到。
第二,寻找充分的证据,证明所推导的交互复杂度的变化规律客观反映出神经网络在全训练周期中泛化性变化的规律。
综上两点,我们希望具体彻底解释清楚神经网络的泛化性变化的内在根因。
与前人的关系:当然大家可能第一反应想到神经正切核(NTK)[2],但是神经正切核只是把参数的变化曲线解了出来,而没办法进一步深入到决策逻辑层面进行解释,没有将神经网络建模的概念表征与其泛化性的关系建立起来,对泛化性的分析依然停留在特征空间分析的层面,而没有在【符号化概念逻辑】与【泛化性】之间建立起严格的关系。
三、两大研究背景
误会 1:神经网络的第一性表征是『等效交互』,而不是神经网络的参数和结构。单纯从结构层面分析神经网络是人们对神经网络泛化根本表征的误解。目前大部分神经网络泛化性研究主要着眼于神经网络的结构、特征、以及数据。人们认为不同的神经网络结构就自然对应不同的函数,并自然展现出不同的性能。
但是,事实上,如图 2 所示,结构的区别只是神经网络表征的表面形式。除去有明显缺陷的对性能有明显影响的神经网络,所有其他可以实现 SOTA 性能的具有不同结构的神经网络往往都建模了相似的等效交互表征,即不同结构的高性能神经网络在等效交互表征上往往都是殊途同归的 [3, 4]。虽然神经网络其中层特征内部是复杂的混乱的,虽然不同神经网络所建模的特征向量大相径庭,虽然神经网络中单个神经元往往建模了相对比较混乱的语义(不是严格清晰的语义),但是神经网络作为一个整体,我们从理论上证明神经网络的所建模的交互关系是稀疏的符号化的(而不是特征的稀疏性,具体见 “四、交互的定义” 章节),而且面向相同任务的完全不同的神经网络往往建模了相似的交互关系。
图 2:不同结构的神经网络所建模的等效交互往往是殊途同归的。对于一个相同的输入句子,面向两个相同任务的两个完全不同的神经网络建模往往相似的交互。
由于不同神经网络的参数和训练样本不一样,两个神经网络中没有任何一个神经元在表征上具有严格的一一对应关系,且每一个神经元往往建模着不同语义的混合模式。相比之下,正如上段分析,神经网络所建模的交互表征实际上是不同神经网络表征中的不变量。因此,我们有理由认为神经网络根本表征是等效交互,而不是其载体(参数和训练样本),符号化交互表征可能代表了知识表征的第一性原理(被交互的稀疏性定理、无限拟合性定理、以及殊途同归现象所保证,见 “四、交互的定义” 章节,具体详细研究见下面知乎文章。
参见:https://zhuanlan.zhihu.com/p/633531725
误会 2:神经网络的泛化性问题是一个混合模型问题,而不是一个高维空间的向量。如图 3 所示,传统的泛化性分析总是假设单个样本整体是高维空间的一个点,实际上神经网络对单个样本的表征是 mixture model 的形式 —— 实际上通过大量不同的交互来表达。我们发现简单交互的泛化能力比复杂交互的泛化能力更强,所以不再适合用一个简单标量来笼统表示整个神经网络在不同样本上的泛化能力。相反,同一个神经网络在不同的样本上建模了不同复杂度的交互关系,而不同复杂度的交互往往对应着不同泛化能力。通常情况下,神经网络建模的高阶(复杂)的交互往往难以泛化到测试样本上(测试样本上不会触发相同的交互),代表过拟合表征,而神经网络建模的低阶(简单)交互往往代表泛化性较强的表征,具体详细研究见 [1]。
图 3:(a)传统的泛化性分析总是假设单个样本整体是高维空间的一个点。(b)实际上神经网络对单个样本的表征是 mixture model 的形式,神经网络在单个样本会建模简单交互(可泛化的交互)和复杂交互(不可泛化的交互)。
四、交互的定义
让我们考虑一个深度神经网络
和一个输入样本
,它包含
个输入变量,我们用集合
表示这些输入变量的全集。令
表示 DNN 在样本
上的一个标量输出。对于一个面向分类任务的神经网络,我们可以从不同角度来定义其标量输出。例如,对于多类别分类问题,
可以定义为
,也可以定义为 softmax 层之前该样本真实标签所对应的标量输出。这里,
表示真实标签的分类概率。这样,针对每个子集
,我们可以用下面公式来定义
中所有输入变量之间 “等效与交互” 和 “等效或交互”。
如图 4(a)所示,我们可以这样理解上述与或交互:我们可以认为与等效交互表示神经网络所编码的
内输入变量之间的 “与关系”。例如,给定一个输入句子
,神经网络可能会在
之间建模一个交互,使得
产生一个推动神经网络输出 “倾盆大雨” 的数值效用。如果
中的任何输入变量被遮挡,则该数值效用将从神经网络的输出中移除。类似地,等效或交互
表示神经网络所建模的内输入变量之间的 “或关系”。例如,给定一个输入句子
,只要
中的任意一个词出现,就会推动神经网络的输出负面情感分类。
神经网络所建模的等效交互满足 “理想概念” 的三条公理性准则,即无限拟合性、稀疏性、样本间迁移性。
- 无限拟合性:如图 4,5 所示,对于任意遮挡样本,神经网络在样本上的输出可以用不同交互概念的效用之和来拟合。即,我们可以构造出一个基于交互的 logical model,无论我们如何遮挡输入样本,这个 logical model 依然可精确拟合模型在此输入样本在任意遮挡状态下的输出值。
- 稀疏性:面向分类任务的神经网络往往只建模少量的显著交互概念,而大部分交互概念都是数值效用都接近于 0 的噪声。
- 样本间迁移性:交互在不同样本间是可迁移的,即神经网络在(同一类别的)不同样本上建模的显著交互概念往往有很大的重合。
图 4:神经网络的复杂的推理逻辑可以被基于少量交互的逻辑模型
准确拟合。每个交互都是衡量神经网络建模特定输入变量集合
之间非线性关系的度量指标。当且仅当集合中变量同时出现时才会触发与交互,并为输出贡献数值分数
,集合中任意变量出现时会触发或交互。
图 5:神经网络在任意的遮挡样本上的输出可以用不同交互概念的效用之和来拟合,即我们可以构造出一个基于交互的 logical model,无论我们如何遮挡输入样本,哪怕穷举个输入单元上种完全不同的遮挡方式,这个 logical model 依然可精确拟合模型在此输入样本在任意遮挡状态下的输出值。
五、新的发现与证明
5.1 发现神经网络在训练过程中交互变化的两阶段现象
在这篇知乎文章中,我们关注神经网络解释性领域的一个根本问题,即如何从一个解析分析的角度去严格预测出神经网络在训练过程中泛化能力的变化情况,并且精确的分析神经网络从欠拟合到过拟合的整个动态变化过程及其背后的根本原因。
首先,我们将交互的阶数(复杂度)定义为交互中的输入变量的数量,
。我们团队之前的工作发现神经网络在某个特定样本所建模的 “与或交互” 的复杂度直接决定了神经网络在这个样本的泛化能力 [1],即神经网络建模的高阶的(大量输入单元之间的)“与或交互” 往往有较差的泛化能力,而低阶的(少量输入单元之间的)“与或交互” 具有较强的泛化能力。
因此,本篇研究的第一步是去预测出神经网络在训练过程中不同时间点所建模的不同阶 “与或交互” 的复杂度的一个解析解,即我们可以通过神经网络在不同时间点所建模的不同阶 “与或交互” 的分布去解释神经网络在不同阶段的泛化能力。交互的泛化能力的定义与神经网络整体泛化能力的定义请见 “5.2 神经网络所建模交互的阶数和其泛化能力的关系” 章节。
我们提出两个指标来表示不同阶(复杂度)的交互的强度的分布。具体来说,我们用
来衡量所有阶正显著交互的强度,用
来衡量所有
阶负显著交互的强度,其中
和
表示显著交互的集合,
表示显著交互的阈值。
图 6:从训练不同轮次的神经网络中提取的不同阶交互强度
和
。在不同数据集上、不同任务上训练的不同的神经网络的训练过程都存在两阶段现象。前两个选定时间点属于第一阶段,而后两个时间点属于第二阶段。恰恰在进入神经网络训练过程的第二阶段不久,神经网络的测试损失和训练损失之间的 loss gap 开始显著上升(见最后一列)。这表明神经网络训练的两阶段现象与模型 loss gap 的变化在时间上是 “对齐” 的。更多实验结果请参见论文。
如图 6 所示,神经网络的两阶段现象具体表现为:
- 在神经训练训练之前,初始化的神经网络主要编码中阶交互,很少编码高阶和低阶交互,并且不同阶交互的分布看起来呈现 “纺锤形”。假设具有随机初始化参数的神经网络建模的是纯噪声,我们在 “5.4 理论证明两阶段现象” 章节证明了具有随机初始化参数的神经网络建模的不同阶的交互的分布呈现 “纺锤形”,即仅建模少量的低阶和高阶交互,大量建模中阶交互。
- 在神经网络训练的第一阶段,神经网络编码的高阶和中阶交互的强度逐渐减弱,而低阶交互的强度逐渐增强。最终,高阶和中阶交互逐渐被消除,神经网络只编码低阶交互。
- 在神经网络训练的第二阶段,神经网络在训练过程中编码的交互阶数(复杂度)逐渐增加。在逐渐学习更高复杂度的交互的过程中,神经网络过拟合的风险也在逐渐提高。
上述的两阶段现象广泛存在于不同结构的神经网络训练于不同任务上的不同数据集的训练过程中。我们在图像数据集(CIFAR-10 数据集、MNIST 数据集、CUB200-2011 数据集(使用从图片中裁剪出来的鸟类图像)和 Tiny-ImageNet 数据集)上训练了 VGG-11/13/16 和 AlexNet。我们在 SST-2 数据集上训练了用于情感语义分类 Bert-Medium/Tiny 模型,我们在 ShapeNet 数据集中训练 DGCNN 来分类的 3D 点云数据。上图显示了不同的神经网络在不同训练时期提取的不同阶的显著交互的分布。我们在这些神经网络的训练过程中都发现了两阶段现象,更多实验结果及细节请参考论文。
5.2 神经网络所建模交互的阶数和其泛化能力的关系
我们团队之前的工作已经发现了神经网络所建模交互的阶数和其泛化能力的关系,即高阶交互比低阶交互具有更差的泛化能力 [1]。某个具体交互的泛化性有清晰的定义 —— 如果一个交互同时在训练样本和测试样本中频繁的被神经网络所建模,则这个交互具有较好的泛化能力。在本篇知乎文章中,介绍了两个实验来证明高阶交互具有较差的泛化能力,低阶交互具有较强的泛化能力。
实验一:观察在不同数据集上训练的不同神经网络所建模的交互的泛化性。这里我们用被测试集所触发的交互的分布和被训练集所触发的交互的分布的 Jaccard 相似性来度量交互的泛化性。具体来说,给定一个包含
个输入变量的输入样本
,我们将从输入样本提取到的
阶交互向量化
,其中
表示
个阶交互。然后,我们计算分类任务中所有类别为
的样本中提取到的阶的平均交互向量,表示为
,其中
表示类别为的样本的集合。接下来,我们计算从训练样本中提取的阶的平均交互向量
与从测试样本中提取的阶的平均交互向量
之间的 Jaccard 相似性,以衡量分类任务中类别为的样本的阶交互的泛化能力,即:
其中,
和
将两个
维交互向量投影到两个
维的非负向量上,以便计算 Jaccard 相似性。对于某一阶的交互,如果此阶交互普遍展现出较大的 Jaccard 相似性,则表示这一阶交互具有较强的泛化能力。
我们进行了实验计算不同阶交互
。我们测试了在 MNIST 数据集上训练的 LeNet、在 CIFAR-10 数据集上训练的 VGG-11、在 CUB200-2011 数据集上训练的 VGG-13,以及在 Tiny-ImageNet 数据集上训练的 AlexNet。为了减少计算成本,我们仅计算了前 10 个类别的 Jaccard 相似性的平均值
。如图 7 所示,随着交互阶数的增加,交互的 Jaccard 相似性不断下降。因此,这验证了高阶交互比低阶交互具有更差的泛化能力。
图 7:从训练样本和测试样本中提取的交互之间的 Jaccard 相似性。低阶交互具有相对较高 Jaccard 相似性表明低阶交互具有较强的泛化能力。
实验二:比较神经网络在正常样本和 OOD 样本建模的交互的分布。我们比较了从正常样本中提取的交互与从分布外 (OOD) 样本中提取的交互,以检查神经网络在 OOD 样本上是否建模更多的高阶交互。我们将少量训练样本的分类标签设置为错误标签。这样,数据集中的原始样本可以视为正常样本,而一些带有错误标签的样本则对应于 OOD 样本,这些 OOD 样本可能会导致神经网络的过拟合。我们在 MNIST 数据集和 CIFAR-10 数据集上分别训练了 VGG-11 和 VGG-13。图 8 比较了从正常样本中提取的交互的分布和从 OOD 样本中提取的交互的分布。我们发现,VGG-11 和 VGG-13 在分类 OOD 样本时建模了更多复杂的交互(高阶交互),而在分类正常样本时则使用了较低阶的交互。这验证了高阶交互的泛化能力通常弱于低阶交互。
图 8:比较从正常样本中提取的交互与从分布外 (OOD) 样本中提取的交互。神经网络通常在 OOD 样本上建模的更高阶的交互。
5.3 两阶段现象和神经网络训练过程 loss gap 的变化相对齐
我们发现上述两阶段现象可以充分表示神经网络泛化性动力学。一个很有趣的现象是神经网络训练过程中的两阶段现象和神经网络在测试集和训练集的 loss gap 的变化在时间上是对齐的。训练损失和测试损失之间的 loss gap 是衡量模型过拟合程度的最广泛使用的指标。图 6 显示了不同的神经网络在训练工程的测试损失和训练损失之间的 loss gap 的曲线,还显示了从不同训练时期的神经网络中提取的交互分布。我们发现当神经网络训练过程中测试损失和训练损失之间的 loss gap 开始增大时,神经网络恰好也进入训练的第二阶段。这表明神经网络训练的两阶段现象与模型 loss gap 的变化在时间上是 “对齐” 的。
我们可以这样理解上述现象:在训练过程开始前,初始化的神经网络所建模的交互全部表示随机噪声,并且不同阶交互的分布看起来像 “纺锤形”。在神经网络训练的第一阶段,神经网络逐渐消除中阶和高阶的交互,并学习最简单的(最低阶的)交互。然后,在神经网络训练的第二阶段,神经网络建模了阶数逐渐增大的交互。由于我们在 “5.2 神经网络所建模交互的阶数和其泛化能力的关系” 章节中的两个实验验证了高阶交互通常比低阶交互具有更差的泛化能力,因此我们可以认为在神经网络训练的第二阶段,DNN 首先学习了泛化能力最强的交互,然后逐渐转向更复杂但泛化能力较弱的交互。最终一些神经网络逐渐过拟合,并编码了大量中阶和高阶交互。
5.4 理论证明两阶段现象
理论证明神经网络训练过程的两阶段现象共分为三个部分,第一部分我们需要证明随机初始化的神经网络在训练过程开始之前建模的交互的分布呈现 “纺锤形”,即很少建模高阶和低阶交互,主要建模中阶交互。第二部分证明神经网络在训练的第二阶段在建模阶数逐渐增大的交互。第三部分证明神经网络在训练的第一阶段逐渐消除中阶和高阶交互,学习最低价的交互。
1. 证明初始化神经网络建模的 “纺锤形” 交互分布。
由于随机初始化的随机网络在训练过程开始之前建模的都是噪声,所以我们假设随机初始化的神经网络建模的交互的服从均值为
,方差为
的正态分布。在上述假设下,我们能够证明初始化的神经网络建模的交互的强度和的分布呈现 “纺锤形”,即很少建模高阶和低阶交互,主要建模中阶交互。
2. 证明神经网络训练的第二阶段的交互变化动态过程。
在进入正式的证明之前,我们需要做以下的预备工作。首先,我们参照 [5, 6] 的做法,将神经网络在特定样本上的 inference 改写为不同交互触发函数的加权和:
其中,
为标量权重,满足
。而函数
为交互触发函数,在任意一个遮挡样本
上都满足
。函数的具体形式可以由泰勒展开推导得到,可参考论文,这里不做赘述。
根据上述改写形式,神经网络在特定样本上的学习可近似看成是对交互触发函数的权重
的学习。进一步地,实验室的前期工作 [3] 发现在同一任务上充分训练的不同的神经网络往往会建模相似的交互,所以我们可以将神经网络的学习看成是对一系列潜在的 ground truth 交互的拟合。由此,神经网络在训练到收敛时建模的交互可以看成是最小化下面的目标函数时得到的解:
其中
表示神经网络需要拟合的一系列潜在的 ground truth 交互。
和
则分别表示将所有权重拼起来得到的向量和将所有交互触发函数的值拼起来得到的向量。
可惜的是,上述建模虽然能得到神经网络训练到收敛时的交互,但是无法很好地刻画神经网络训练过程中学习交互的动态过程。这里引入我们的核心假设:我们假设初始化神经网络的参数上包含了大量噪声,而这些噪声的量级在训练过程中逐步变小。而进一步地,参数上的噪声会导致交互触发函数
上的噪声,且该噪声随着交互阶数指数级增长 (在 [5] 中已有实验上的观察和验证) 。我们将有噪声下的神经网络的学习建模如下:
其中噪声
满足
。且随着训练进行,噪声的方差
逐渐变小。
在给定的噪声量级的情况下最小化上述损失函数,可得到最优交互权重的解析解,如下图中的定理所示。
我们发现,随着训练进行(即噪声量级变小),中低阶交互强度和高阶交互强度的比值逐渐减小(如下面的定理所示)。这解释了训练的第二阶段中神经网络逐渐学到更加高阶的交互的现象。
另外,我们对上述结论进一步做了实验验证。给定一个具有 n 个输入单元的样本,指标
,其中
, 可以用来近似测量第 k 阶交互和第 k+1 阶交互强度的比值。在下图中,我们可以发现,在不同的输入单元个数 n 和不同的阶数 k 下,该比值都会随着的减小而逐渐减小。
图 9:在不同的输入单元个数 n 和不同的阶数 k 下,第 k 阶交互和第 k+1 阶交互强度的比值都会随着噪声量级的减小而逐渐减小。这说明随着训练进行(即逐渐变小),低阶交互强度与高阶交互强度的比值逐渐变小,神经网络逐渐学到更加高阶的交互。
最后,我们对比了在不同噪声量级下的理论交互值
在各个阶数上的分布
和实际训练过程中各阶交互的分布
,发现理论交互分布可以很好地预测实际训练中各时间点的交互强度分布。
图 10:比较理论交互分布
(蓝色直方图)和实际交互分布
(橙色直方图)。在训练第二阶段的不同时间点,理论交互分布都可以很好地预测和匹配实际交互的分布。更多结果请参见论文。开发板商城 天皓智联 TB上有视觉设备哦~
3. 证明神经网络训练的第一阶段的交互变化动态过程。
如果说训练的第二阶段中交互的动态变化可以解释为权重的最优解在噪声逐渐减小时的变化,那么第一阶段就可认为是交互从初始化的随机交互逐渐收敛到最优解的过程。
路漫漫其修远兮,我们团队是做神经网络可解释性的第一性原理,我们希望在更多的方面把这个理论做扎实,能够严格证明等效交互是符号化的解释,并且能够解释神经网络的泛化性、鲁棒性,同时证明神经网络表征瓶颈,统一 12 种提升神经网络对抗迁移性的方法和解释 14 种重要性估计方法。我们后面会做出更扎实的工作,进一步完善理论体系。
#Tora
阿里「轨迹可控版Sora」,告别「抽卡」,让视频生成更符合物理规律
你规定路线,Tora 来生成相应轨迹的视频。
目前,扩散模型能够生成多样化且高质量的图像或视频。此前,视频扩散模型采用 U-Net 架构 ,主要侧重于合成有限时长(通常约为两秒)的视频,并且分辨率和纵横比受到固定限制。
Sora 的出现打破了这一限制,其采用 Diffusion Transformer(DiT)架构,不仅擅长制作 10 到 60 秒的高质量视频,而且还因其生成不同分辨率、各种纵横比、且遵守实际物理定律的能力而脱颖而出。
可以说 Sora 是 DiT 架构最有利的证明,然而,基于 Transformer 的扩散模型在有效生成可控动作视频方面还未被充分探索。
针对这一问题,来自阿里的研究者提出了 Tora,这是第一个面向轨迹的 DiT 架构,它将文本、视觉和轨迹条件同时集成在一起以生成视频。
Tora 的设计与 DiT 的可扩展性无缝契合,允许精确控制具有不同持续时间、宽高比和分辨率的视频内容。大量实验证明,Tora 在实现高运动保真度方面表现出色,同时还能细致模拟物理世界的运动。
- 论文地址:https://arxiv.org/pdf/2407.21705
- 论文主页:https://ali-videoai.github.io/tora_video/
- 论文标题:Tora: Trajectory-oriented Diffusion Transformer for Video Generation
一艘老式的木制帆船沿着规定好的路线在迷雾笼罩的河流上平稳地滑行,周围是茂密的绿色森林。
一条鲫鱼优雅地游过火星的红色岩石表面,鱼的轨迹向左,火星的轨迹向右。
热气球沿着不同的轨迹升入夜空,一个沿着规定的斜线,另一个沿着有弯度的轨迹。
两只可爱的小猫并排走在宁静的金色沙滩上。
气泡沿着轨迹轻轻地漂浮在盛开的野花中。
枫叶在清澈的湖面上颤动,映照着秋天的森林。
山间的瀑布倾泻而下,主题、背景的运动都可以按照不同的路线运动。
在 Tora 与其他方法的比较中,可以看出 Tora 生成的视频流畅度更高,更遵循轨迹,且物体不会存在变形的问题,保真度更好。
方法介绍
Tora 采用 OpenSora 作为其 DiT 架构的基础模型,包含一个轨迹提取器 (TE,Trajectory Extractor)、时空 DiT(Spatial-Temporal DiT )和一个运动引导融合器 (MGF,Motion-guidance Fuser) 。TE 使用 3D 视频压缩网络将任意轨迹编码为分层时空运动 patch。MGF 将运动 patch 集成到 DiT 块中,以生成遵循轨迹的一致视频。图 3 概述了 Tora 的工作流程。
时空 DiT(ST-DiT)
ST-DiT 架构包含两种不同的块类型:空间 DiT 块 (S-DiT-B) 和时间 DiT 块 (T-DiT-B),它们交替排列。S-DiT-B 包含两个注意力层,每个层按顺序执行空间自注意力 (SSA) 和交叉注意力,后面跟着一个逐点前馈层,用于连接相邻的 T-DiT-B 块。T-DiT-B 仅通过用时间自注意力 (TSA) 替换 SSA 来修改此架构,从而保持架构一致性。在每个块中,输入在经过规范化后,通过跳跃连接连接回块的输出。通过利用处理可变长度序列的能力,去噪 ST-DiT 可以处理可变持续时间的视频。
轨迹提取器
轨迹已被证明是一种更加用户友好的方法来控制生成视频的运动。然而,DiT 模型采用视频自编码器和 patch 化过程将视频转换为视频 patch。在这里,每个 patch 都是跨多个帧导出,因此直接采用帧间偏移是不合适的。为了解决这个问题,本文提出的 TE 将轨迹转换为运动 patch,运动 patch 与视频 patch 位于相同的潜在空间。
运动引导融合器
为了将基于 DiT 的视频生成与轨迹结合起来,本文探索了三种融合架构变体,将运动 patch 注入每个 ST-DiT 块。这些设计如图 4 所示。
实验结果
在实现细节上,研究者基于 OpenSora v1.2 权重来训练 Tora。训练视频的分辨率由 144p 到 720p 不等。为了平衡训练 FLOP 以及每次迭代不同分辨率和帧数所需的内存,研究者相应地将批大小从 1 调整到 25。
至于训练基础设施,研究者使用了 4 块英伟达 A100 和 Adam 优化器,学习率为 2 × 10^−5。
研究者将 Tora 与流行的运动指导视频生成方法进行了比较。评估中使用了三种设置,分别为 16、64 和 128 帧,所有设置都是 512×512 的分辨率。
结果如下表 1 所示,在 U-Net 方法常用的 16 帧设置下,MotionCtrl 和 DragNUWA 能够更好地与所提供的轨迹实现对齐,但仍弱于 Tora。随着帧数增加,U-Net 方法在某些帧中出现明显偏差,并且错位误差传播会导致后续序列中出现变形、运动模糊或物体消失。
相比之下,得益于集成了 Transformer 的缩放能力,Tora 对帧数变化表现出很高的稳健性。Tora 产生的运动更加流畅,且更符合物理世界。对于 128 帧测试设置下的评估,Tora 的轨迹精度达到其他方法的 3 到 5 倍,展现出了卓越的运动控制能力。
在下图 5 中,研究者对不同分辨率和持续时长的轨迹误差进行分析。结果显示,不同于 U-Net 随时间推移出现明显的轨迹误差,Tora 的轨迹误差随时间推移出现渐进增加。这与 DiT 模型中视频质量随时间增加而下降相一致。Tora 在更长的时间下保持了有效的轨迹控制。
下图 6 展示了 Tora 与主流运动控制方法的比较分析,在包含两人共同运动的场景中,所有方法都能生成相对准确的运动轨迹。不过,Tora 的视觉质量更好,这要归功于更长序列帧的使用,有助于实现更平滑的运动轨迹和更逼真的背景渲染。
可以看到,在 Tora 生成的自行车场景中,人的双腿表现出逼真的踩踏动作,而 DragNUWA 的双腿几乎水平漂浮,违反了物理真实性。此外,DragNUWA 和 MotionCtrl 在视频结尾处都出现了严重的运动模糊。
在另一个生成灯笼的场景中,DragNUWA 随着所提供轨迹的持续升降出现了严重的变形。MotionCtrl 的轨迹虽然相对准确,但生成的视频与两个灯笼的描述不相符。Tora 不仅严格地遵循了轨迹,而且最大程度地减少了物体变形,确保了更高保真度的动作表示。
#让循环语言模型超越Transformer++
小技巧大功效,「仅阅读两次提示」
在当前 AI 领域,大语言模型采用的主流架构是 Transformer。不过,随着 RWKV、Mamba 等架构的陆续问世,出现了一个很明显的趋势:在语言建模困惑度方面与 Transformer 较量的循环大语言模型正在快速进入人们的视线。
令人兴奋的是,这些架构在推理期间使用了恒定量的内存。不过,受制于有限的内存,循环语言模型(LM)无法记忆并使用长上下文中的所有信息,这导致了上下文学习(in-context learning,ICL)质量的不佳。因此,获得高效大语言模型的关键挑战在于选择存储或者丢弃哪些信息。
在最近的论文《Just read twice: closing the recall gap for recurrent language models》中,来自斯坦福大学、布法罗大学的研究者通过简单观察发现,数据在推理期间涌入循环语言模型的排序极大地影响了在有限内存中预测存储哪些信息的难度。
我们假设根据文档 D(比如伽利略・伽利莱的详细维基百科)来提问:伽利略是什么时候搬到的佛罗伦萨?这时,如果提示遵循了 [Q, D] 的排序,则模型只需要记住文档 D 中的一个事实即可。相反,如果提示遵循了 [D, Q] 的排序,则模型需要记住所有事实。如下图 1(左)所示。
因此,本文首先从理论上形式化了数据排序如何影响内存需求,然后提出两种方法来减轻对数据排序的依赖,分别是 Just-read-twice(JRT)提示策略和 JRT 循环架构。本文主要分为以下几个部分展开:
理解数据排序的作用。研究者得出的第一个洞见是:记忆问题的 hardness 要降低到与设置剥离(set disjointness,SD)相同,这是通信复杂度理论中持续数十年的最典型问题。SD 要求一种流算法(比如循环模型)来决定上下文中提供的输入集是否剥离:
理论分析和实验结果表明,第一个集 | A | 掌控了求解 SD 所需的内存。因果模型需要存储 A 中的所有元素以与 B 中的元素进行比较。这表明了,使用上下文中的「正确数据排序」(如将最小 min (|A|, |B|) 的集放在首位)将有助于内存受限的模型。更进一步,观察到上下文非因果逻辑的模型可在空间最小的 (|A|, |B|) 中求解 SD,而无需考虑数据排序。
其次是利用「正确的」排序。本文提出了一种非常简单的 JRT-Prompt 策略,在模型生成答案之前在上下文中将信息重复多次(如上图 1 右所示)。在第二以及更多轮次中,语言模型在决定存储哪些信息时要以完整的上下文为条件,从而有效避免了将数据排序「归正」的问题。
结果表明,JRT-Prompt 在 16 个已有循环语言模型和 6 项 ICL 任务上,实现了平均 11.0 ± 1.3 百分点的提升,而吞吐量是 FlashAttention-2(长度 32k、批大小 16)的 11.9 倍。JRT-Prompt 虽然增加了上下文长度,但渐进来看仍然比注意力更加地计算和内存高效。
超越因果模型。本文提出了 JRT-RNN,它的灵感来源于简单的 Prefix-LM 编码器解码器架构设计。大多数的上下文学习输入包含两部分内容,分别是输入的提示(上下文、指令)和作为输出的模型生成文本。在 Prefix-LM 架构中,LM 并没有遵循因果逻辑地处理提示区域,而对输出进行了因果解码,其中在因果区域仅使用了标准的下一个 token 预测损失,以及非因果区域上的损失。
不过遗憾的是,此前 Prefix-LM 模型的训练方法取得的成功有限,并使用了低效的 Transformer 主干。因此本文通过一些简单的改变来提高质量和效率,包括改进训练损失并使用称之为「Prefix Linear Attention,PLA」 的线性注意力公式。研究者发现,使用他们的 IO 感知实现,JRT-RNN 在 360m 和 1.3b 参数设置下,分别可以提供 13.7 和 6.9 百分点的平均质量改进,吞吐量是 FA2 的 19.2 倍。
- 论文地址:https://arxiv.org/pdf/2407.05483
- 项目主页:https://github.com/HazyResearch/prefix-linear-attention
JRT-Prompt 方法概览
上下文学习任务以 (C, Q, Y) 作为输入,其中 C 为一些上下文来源(如文档或代码存储库),Q 为给定上下文时对模型的一些问题或请求,Y 为答案。对于使用自回归 LM A 的标准上下文学习,研究者输入 C 和 Q,并根据正确的完成情况 Y 来评估生成的输出 Yˆ = A (C, Q)。
JRT-Prompt 是一种极其简单的方法,在提示模型输出答案之前会在上下文中重复提示中的信息(如问题和文档),例如下图 1 右的 Yˆ = A (C, Q, C, Q)。因此,在上下文第二次出现时,模型根据完整的上下文来决定存储哪些信息。
此外,JRT-Prompt 可以与现成的 LLM 一起使用。研究者在零样本提示下,在一系列记忆密集型上下文任务上评估了以下 LM:
- Based 预训练 LM,参数规模为 1.3B,在 Pile 的 10 − 50B 个 token 上进行训练;
- Mamba 预训练的 LM,参数规模为 130M、370M、1.4B 和 2.8B,在 Pile 的 300B 个 token 上进行训练;
- Gated Linear Attention 预训练的 LM,参数规模为 1.3B 和 2.7B,在 SlimPajama 数据集的 100B 个 token 上进行训练;
- Mamba-2 预训练的 LM,参数规模为 130M、370M、1.3B 和 2.7B,在 Pile 的 300B 个 token 上进行训练。
结果如下表 1 所示,通过增加状态(state)大小,研究者发现 JRT-Prompt 方法在各个模型和任务上平均带来了 11.0 ± 1.3 百分点的性能提升,利用该方法的 Based 模型平均优于利用标准提示的 Transformer 模型。
他们还发现,JRT-Prompt 可以使 Transformer 模型受益,并且该方法在一些任务上(附录 2)比少样本学习更加有效。值得注意的是,Springer 等人在论文《Repetition improves language model embeddings》中提出使用自回归 Transformer 模型来重复上下文以实现生成嵌入的目的,本文的研究结果也类似。研究者专注于亚二次架构和上下文学习任务。
JRT-Prompt 虽然由于重复而增加了上下文长度,但是其使用的亚二次循环架构仍比使用二次 Transformer 模型更高效。研究者发现,在序列长度 N = 32768、批大小为 16 时,使用 JRT-Prompt(序列长度 2N)在英伟达 H100 上提供的吞吐量是 FlashAttention-2(序列长度 N)的 11.9 倍。
JRT-RNN:编码器 - 解码器循环架构
JRT-RNN 的灵感来自于 Prefix-LMs,但侧重于扩展质量 - 效率权衡空间的帕累托边界(Pareto frontier)。为了提高质量,JRT-RNN 在编码器端使用了单独的 k_e 和 v_e 映射,在解码器端使用了 k_d 和 v_d 映射。虽然 Prefix LM 模型对编码器和解码器区域使用了共享映射权重,但研究者发现使用两组映射可以提高质量。
为了提高效率,JRT-RNN 为编码器使用了非因果线性注意力,而为解码器使用标准因果线性注意力。研究者称为 Prefix Linear Attention(PLA)(图 1 右),公式如下:
JRT-RNN 训练目标。Prefix LMs 通常不计算非因果区域的损失,而 JRT-RNN 将下一个 token 预测与掩码语言建模(MLM)目标进行了结合。并且对于添加的 MLM 目标,研究者用一个 [MASK] token 替换了来自编码器区域 {u_1, ..., u_M} 的比例为 P 的 tokens,并在预测原始 token 时测量了交叉熵损失。
损失如下:
实验结果
在实验中,研究者评估了 JRT-RNN 在以下三个指标上的质量和效率:
- 上下文学习质量
- 整体语言建模
- 生成
上下文学习质量
如下表 2 所示,研究者发现,JRT-RNN 在参数为 360M(30B tokens)时比仅解码器的基线(Based)平均高出 13.7 个百分点,在参数为 1.3B(50B tokens)时平均高出 6.9 个百分点。
同时,JRT-RNN 在参数为 360M 和 1.3B 时与 Transformer++ 的差距分别缩小到了 0.5 个百分点和 1.9 个百分点之内。
在下表 3 中,研究者比较了当 prefill 长度 l 小于编码器长度 M 时,JRT-RNN 与同类推理策略的表现。
整体自然语言理解
根据以往研究,研究者进一步将困惑度分为了两组:联想记忆「AR slice」包括了被称为「AR hits」的 tokens,它们需要模型按照顺序执行记忆以正确地预测下一个 token;而「Other slice」包含剩余的 tokens(如记忆的知识)。
对于记忆频率,JRT-RNN 在「AR slice」表现出色。对于训练期间不常见的二元组(即不太可能在模型参数中被记住的),JRT-RNN 的困惑度相对于 Based 和 Mamba 这两个强大的因果循环基线有所改善。
对于记忆距离,在「AR slice」中,JRT-RNN 与仅解码器基线之间的差距随着上下文中重复二元组的增加而扩大。这也进一步证明了 JRT-RNN 可以帮助完成更长的上下文记忆任务。
非记忆频率。对于训练期间很少见到的二元组的非记忆「Other slice」,JRT-RNN 的困惑度比仅解码器的 LM 更差。这是意料之中的结果,因为 JRT-RNN 计算了仅解码器 LM 的 65% tokens 的损失。
我们预计这一差距会随着规模和训练时间的延长而缩小(随着二元语法频率的增加而增加)(图 3,左上角)。
生成吞吐量
生成可以分解为提示「prefill 处理」和解码「下一个 token 预测」两步。相较于标准的仅解码器循环模型,JRT-RNN 不会修改解码步骤,因此讨论重点在 prefill 阶段。
使用 Simran Arora 等人论文《Simple linear attention language models balance the recall-throughput tradeof》中提出的 Based CUDAn 内核,JRT-Prompt 在处理 prefill 时吞吐量分别是 FlashAttention-2 和 FLA Triton 内核的 11.9 和 13.7 倍,如下表 5 所示。
当研究者将批大小增加到 64 时,JRT-Prompt 吞吐量分别是 FlashAttention-2 和 FLA Triton 内核的 6.1 倍和 7.2 倍。
接下来他们扩展了 Based 内核以支持 JRT-RNN,并且证明了当将序列长度增加到 32768 时,吞吐量分别是 FlashAttention-2 和 FLA 的 19.2 倍和 22.0 倍。当将批大小增加到 64 时,JRT-RNN 分别又提供了 9.7 倍和 11.5 倍的吞吐量提升。JRT-RNN 所需的时间是 Based prefill 的 1.24 倍,比 JRT-Prompt 更加高效。
#延迟交互模型
为什么是下一代RAG的标配?
张颖峰:英飞流联合创始人,多年搜索、AI、Infra基础设施开发经历,目前正致力于下一代 RAG 核心产品建设。
在 RAG 系统开发中,良好的 Reranker 模型处于必不可少的环节,也总是被拿来放到各类评测当中,这是因为以向量搜索为代表的查询,会面临命中率低的问题,因此需要高级的 Reranker 模型来补救,这样就构成了以向量搜索为粗筛,以 Reranker 模型作精排的两阶段排序架构。
目前排序模型的架构主要有两类:
1. 双编码器。以 BERT 模型为例,它针对查询和文档分别编码,最后再经过一个 Pooling 层,使得输出仅包含一个向量。在查询时的 Ranking 阶段,只需要计算两个向量相似度即可,如下图所示。双编码器既可以用于 Ranking 也可以用于 Reranking 阶段,向量搜索实际上就是这种排序模型。由于双编码器针对查询和文档分别编码,因此无法捕获查询和文档的 Token 之间的复杂交互关系,在语义上会有很多损耗,但由于只需要向量搜索即可完成排序打分计算,因此执行效率非常高。
2. 交叉编码器(Cross Encoder)。Cross-Encoder 使用单编码器模型来同时编码查询和文档,它能够捕捉查询和文档之间的复杂交互关系,因此能够提供更精准的搜索排序结果。Cross-Encoder 并不输出查询和文档的 Token 所对应的向量,而是再添加一个分类器直接输出查询和文档的相似度得分。它的缺点在于,由于需要在查询时对每个文档和查询共同编码,这使得排序的速度非常慢,因此 Cross-Encoder 只能用于最终结果的重排序。例如针对初筛结果的 Top 10 做重排序,仍然需要耗时秒级才可以完成。
今年以来,另一类以 ColBERT【参考文献1】 为代表的工作,在 RAG 开发社区引起了广泛关注,如下图所示,它具备一些显著区分于以上两类排序模型的特点:
其一是相比于 Cross Encoder,ColBERT 仍采用双编码器策略,将查询和文档分别采用独立的编码器编码,因此查询的 Token 和文档的 Token 在编码时互不影响,这种分离使得文档编码可以离线处理,查询时仅针对 Query 编码,因此处理的速度大大高于 Cross Encoder;
其二是相比于双编码器,ColBERT 输出的是多向量而非单向量,这是从 Transformer 的最后输出层直接获得的,而双编码器则通过一个 Pooling 层把多个向量转成一个向量输出,因此丢失了部分语义。
在排序计算时,ColBERT 引入了延迟交互计算相似度函数,并将其命名为最大相似性(MaxSim),计算方法如下:对于每个查询 Token 的向量都要与所有文档 Token 对应的向量进行相似度计算,并跟踪每个查询 Token 的最大得分。查询和文档的总分就是这些最大余弦分数的总和。例如对于一个有 32 个 Token 向量的查询(最大查询长度为 32)和一个有 128 个 Token 的文档,需要执行 32*128 次相似性操作,如下图所示。
因此相比之下, Cross Encoder 可以称作早期交互模型 (Early Interaction Model),而以 ColBERT 为代表的工作可称为延迟交互模型(Late Interaction Model)。
下图从性能和排序质量上,分别对以上排序模型进行对比。由于延迟交互模型满足了对排序过程中查询和文档之间复杂交互的捕获,同时也避免了对文档 Token 编码的开销,因此既能保证良好的排序效果,也能实现较快的排序性能 —— 相同数据规模下, ColBERT 的效率可达 Cross Encoder 的 100 倍以上。因此延迟交互模型是一种非常有前景的排序模型,一个天然的想法是:能否在 RAG 中直接采用延迟交互模型替代向量搜索 + 精排这样的两阶段排序架构?
为此,我们需要考虑 ColBERT 工程化的一些问题:
1. ColBERT 的 MaxSim 延迟交互相似度函数,计算效率大大高于 Cross Encoder,但相比普通向量搜索,计算开销仍然很大:因为查询和文档之间的相似度,是多向量计算,因此 MaxSim 的开销是普通向量相似度计算的 M * N 倍 (M 为查询的 Token 数, N 为 文档的 Token 数)。针对这些,ColBERT 作者在 2021 年推出了 ColBERT v2 【参考文献 2】,通过 Cross Encoder 和模型蒸馏,改进了生成的 Embedding 质量,并且采用压缩技术,对生成的文档向量进行量化,从而改善 MaxSim 的计算性能。基于 ColBERT v2 包装的项目 RAGatouille 【参考文献 3】成为高质量 RAG 排序的解决方案。然而,ColBERT v2 只是一个算法库,端到端的让它在企业级 RAG 系统使用,仍然是一件困难的事情。
2. 由于 ColBERT 是预训练模型,而训练数据来自于搜索引擎的查询和返回结果,这些文本数据并不大,例如查询 Token 数 32 , 文档 Token 数 128 是典型的长度限制。因此将 ColBERT 用于真实数据时, 超过限制的长度会被截断,这对于长文档检索并不友好。
基于以上问题, 开源 AI 原生数据库 Infinity 在最新版本中提供了 Tensor 数据类型,并原生地提供端到端的 ColBERT 方案。当 Tensor 作为一种数据类型,ColBERT 编码输出的多个向量,就可以直接用一个 Tensor 来存放,因此 Tensor 之间的相似度就可以直接得出 MaxSim 打分。针对 MaxSim 计算量大的问题,Infinity 给出了 2 个方案来优化:其一种是 binary 量化,它可以让原始 Tensor 的空间只需原始尺寸的 1/32 , 但并不改变 MaxSim 计算的相对排序结果。这种方案主要用于 Reranker,因为需要根据前一阶段粗筛的结果取出对应的 Tensor 。另一种是 Tensor Index,ColBERTv2 实际上就是 ColBERT 作者推出的 Tensor Index 实现,Infinity 采用的则是 EMVB【参考文献 4】,它可以看作是 ColBERT v2 的改进,主要通过量化和预过滤技术,并在关键操作上引入 SIMD 指令来加速实现。Tensor Index 只能用来服务 Ranker 而非 Reranker。此外,针对超过 Token 限制的长文本,Infinity 引入了 Tensor Array 类型:
一篇超过 ColBERT 限制的文档,会被切分成多个段落,分别编码生成 Tensor 后,都跟原始文档保存在一行。计算 MaxSim 的时候,查询跟这些段落分别计算,然后取最大值作为整个文档的打分。如下图所示:
因此,采用 Infinity,可以端到端地引入延迟交互模型高质量地服务 RAG。那么,应该是采用 ColBERT 作为 Ranker ,还是 Reranker 呢?下边我们采用 Infinity 来在真实数据集上进行评测。由于 Infinity 的最新版本实现了有史以来最全的混合搜索方案,召回手段包含向量搜索、全文搜索、稀疏向量搜索,上文所述的 Tensor ,以及这些手段的任意组合,并且提供了多种 Reranker 手段,如 RRF,以及 ColBERT Reranker 等,因此我们在评测中包含了各种混合搜索和 Reranker 的组合。
我们采用 MLDR 数据集进行评测。MLDR 是 MTEB 【参考文献 5】用来评测 Embedding 模型质量的 benchmark 集,其中 MLDR 是其中一个数据集,全称为 Multi Long Document Retrieval,一共包含 20 万长文本数据。评测采用 BGE-M3【参考文献 6】作为 Embedding 模型,采用 Jina-ColBERT 【参考文献 7】来生成 Tensor,评测脚本也放到了 Infinity 仓库【参考文献 8】。
评测一:ColBERT 作为 Reranker 是否有效。将 20 万 MLDR 数据分别用 BGE-M3 生成稠密向量和稀疏向量,并插入到 Infinity 数据库中,数据库包含 4 列,分别保存原始文本,向量,稀疏向量,以及 Tensor,并分别构建相应全文索引、向量索引、稀疏向量索引。评测包含所有的召回组合,包含单路召回、双路召回,以及三路召回,如下所示:
评测指标采用 nDCG@10。其他参数:采用 RRF Reranker 时粗筛返回的 Top N = 1000 ,查询累计共有 800 条,平均每条查询长度在 10 个 token 左右。
从图中看到,所有的召回方案,在采用了 ColBERT Reranker 之后,都有明显的效果提升。ColBERT 作为一种延迟交互模型,它可以提供跟在 MTEB 的 Reranker 排行榜上位居前列相提并论的排序质量,但是性能却是它们的 100 倍,所以可以在更大的范围内进行重排序。图中给出的结果是针对 Top 100 进行 Reranker,而采用 Top 1000 进行 ColBERT 重排序,数值没有明显变化,性能还有明显下降,因此不推荐采用。传统上采用基于 Cross Encoder 的外部 Reranker ,Top 10 就会有秒级的延迟,而 Infinity 内部实现了高性能的 ColBERT Reranker,即使针对 Top 100 甚至 Top 1000 做重排序,也不会影响用户体验,而召回的范围却大大增加,因此可以显著改进最终的排序效果。此外,这种 ColBERT Reranker 计算只需在纯 CPU 架构上即可运行,这也大大降低了部署的成本。
评测二:对比基于 ColBERT 作为 Ranker 而不是 Reranker。因此,这时需要针对 Tensor 这列数据构建 Tensor Index。同时,为了评估 Tensor Index 引入的精度损耗,还进行了暴力搜索。
可以看到,相比 Reranker ,即使是采用没有精度损失的暴力搜索,也没有显著的提升,而采用基于 Tensor Index 的排序质量甚至低于采用 Reranker。然而,作为 Ranker 的查询时间却要慢得多:MLDR 数据集包含 20 万文档数据,大约 2GB 左右,采用 Jina-ColBERT 转成 Tensor 数据后,高达 320 G,这是因为 Tensor 数据类型是把一篇文档的每个 Token 对应的向量都要保存下来, ColBERT 模型的维度是 128 维,因此默认数据量会膨胀 2 个数量级,即使构建了 Tensor Index,在查询这么多数据的时候,也需要平均 7s 才能返回一个查询,但得到的结果却并没有更好。
因此,很显然,ColBERT 作为 Reranker 的收益比作为 Ranker 要高得多。当前最佳的 RAG 检索方案,是在 3 路混合搜索(全文搜索 + 向量 + 稀疏向量)的基础上加 ColBERT Reranker。有伙伴可能会问了,为了采用 ColBERT Reranker,就需要增加单独的 Tensor 列,并且该列会相比原始数据集膨胀 2 个数量级,这样做是否值得?首先:Infinity 针对 Tensor 提供了 Binary 量化手段,作为 Reranker,它并不影响排序结果很多,但却可以让最终的数据仅有原始 Tensor 大小的 1/32。其次,即便如此,也会有人认为这样的开销过高。然而站在使用者的视角,用更多的存储,来换取更高的排序质量和更廉价的成本(排序过程无需 GPU),这样做依然是非常值得的。最后,相信很快就可以推出效果上略有下降,但存储开销大大降低的 Late Interaction 模型,作为一款 Data Infra 基础设施, 对这些变化保持透明,把这些 Trade Off 交给用户是明智的选择。
以上是基于 Infinity 在 MLDR 数据集上的多路召回评测,在其他数据集的评测结果,可能会有所不同,但整体上结论不会变 —— 3 路混合搜索 + 基于 Tensor 的重排序,是当前搜索结果质量最高的召回手段。
由此可以看到,ColBERT 及其延迟交互模型,在 RAG 场景具有很大的应用价值,以上是在文本对话内容生成的相关工作,近期,延迟交互模型在多模态场景,也得到了 SOTA 的结果。这就是 ColPali【参考文献 9】,它改变了 RAG 的工作流程,如下图所示:
RAG 在面临复杂格式文档时,当下的 SOTA ,是采用文档识别模型,对文档的布局做识别,并针对识别出的部分结构,例如图表,图片等,再分别调用相应的模型,将它们转化为对应的文字,再用各种格式保存到 RAG 配套的数据库中。而 ColPali 则省掉了这些步骤,它直接采用多模态模型生成 Embedding 内容。提问的时候,可以直接针对文档中的图表进行回答:
ColPali 模型的训练跟 ColBERT 类似,也是采用查询 - 文档页面对的形式,从而捕获查询和文档多模态数据之间的语义关联,只是采用 PaliGemma 【参考文献 10】用来生成多模态 Embedding 。相比没有采用 Late Interaction 机制但同样采用 PaliGemma 生成 Embedding 的方案 BiPali,在 nDCG@5 的评测指标对比是 81.3 vs 58.8,这种差距是就是 “极好” 和 “压根不能工作” 的区别。
因此,尽管 ColBERT 出现至今已有 4 年时间,可是 Late Interaction 模型在 RAG 的应用才刚刚开始,它必将扩大 RAG 的使用场景,在包含多模态在内的复杂 RAG 场景提供高质量的语义召回。而 Infinity 已经为它的端到端应用做好了准备,欢迎关注和 Star Infinity,https://github.com/infiniflow/infinity, 致力于成为最好的 AI 原生数据库!
#LLM可解释性的未来希望
稀疏自编码器是如何工作的,这里有一份直观说明
简而言之:矩阵 → ReLU 激活 → 矩阵
在解释机器学习模型方面,稀疏自编码器(SAE)是一种越来越常用的工具(虽然 SAE 在 1997 年左右就已经问世了)。
机器学习模型和 LLM 正变得越来越强大、越来越有用,但它们仍旧是黑箱,我们并不理解它们完成任务的方式。理解它们的工作方式应当大有助益。
SAE 可帮助我们将模型的计算分解成可以理解的组件。近日,LLM 可解释性研究者 Adam Karvonen 发布了一篇博客文章,直观地解释了 SAE 的工作方式。
可解释性的难题
神经网络最自然的组件是各个神经元。不幸的是,单个神经元并不能便捷地与单个概念相对应,比如学术引用、英语对话、HTTP 请求和韩语文本。在神经网络中,概念是通过神经元的组合表示的,这被称为叠加(superposition)。
之所以会这样,是因为世界上很多变量天然就是稀疏的。
举个例子,某位名人的出生地可能出现在不到十亿分之一的训练 token 中,但现代 LLM 依然能学到这一事实以及有关这个世界的大量其它知识。训练数据中单个事实和概念的数量多于模型中神经元的数量,这可能就是叠加出现的原因。
近段时间,稀疏自编码器(SAE)技术越来越常被用于将神经网络分解成可理解的组件。SAE 的设计灵感来自神经科学领域的稀疏编码假设。现在,SAE 已成为解读人工神经网络方面最有潜力的工具之一。SAE 与标准自编码器类似。
常规自编码器是一种用于压缩并重建输入数据的神经网络。
举个例子,如果输入是一个 100 维的向量(包含 100 个数值的列表);自编码器首先会让该输入通过一个编码器层,让其被压缩成一个 50 维的向量,然后将这个压缩后的编码表示馈送给解码器,得到 100 维的输出向量。其重建过程通常并不完美,因为压缩过程会让重建任务变得非常困难。
一个标准自编码器的示意图,其有 1x4 的输入向量、1x2 的中间状态向量和 1x4 的输出向量。单元格的颜色表示激活值。输出是输入的不完美重建结果。
解释稀疏自编码器
稀疏自编码器的工作方式
稀疏自编码器会将输入向量转换成中间向量,该中间向量的维度可能高于、等于或低于输入的维度。在用于 LLM 时,中间向量的维度通常高于输入。在这种情况下,如果不加额外的约束条件,那么该任务就很简单,SAE 可以使用单位矩阵来完美地重建出输入,不会出现任何意料之外的东西。但我们会添加约束条件,其中之一是为训练损失添加稀疏度惩罚,这会促使 SAE 创建稀疏的中间向量。
举个例子,我们可以将 100 维的输入扩展成 200 维的已编码表征向量,并且我们可以训练 SAE 使其在已编码表征中仅有大约 20 个非零元素。
稀疏自编码器示意图。请注意,中间激活是稀疏的,仅有 2 个非零值。
我们将 SAE 用于神经网络内的中间激活,而神经网络可能包含许多层。在前向通过过程中,每一层中和每一层之间都有中间激活。
举个例子,GPT-3 有 96 层。在前向通过过程中,输入中的每个 token 都有一个 12,288 维向量(一个包含 12,288 个数值的列表)。此向量会累积模型在每一层处理时用于预测下一 token 的所有信息,但它并不透明,让人难以理解其中究竟包含什么信息。
我们可以使用 SAE 来理解这种中间激活。SAE 基本上就是「矩阵 → ReLU 激活 → 矩阵」。
举个例子,如果 GPT-3 SAE 的扩展因子为 4,其输入激活有 12,288 维,则其 SAE 编码的表征有 49,512 维(12,288 x 4)。第一个矩阵是形状为 (12,288, 49,512) 的编码器矩阵,第二个矩阵是形状为 (49,512, 12,288) 的解码器矩阵。通过让 GPT 的激活与编码器相乘并使用 ReLU,可以得到 49,512 维的 SAE 编码的稀疏表征,因为 SAE 的损失函数会促使实现稀疏性。
通常来说,我们的目标让 SAE 的表征中非零值的数量少于 100 个。通过将 SAE 的表征与解码器相乘,可得到一个 12,288 维的重建的模型激活。这个重建结果并不能与原始的 GPT 激活完美匹配,因为稀疏性约束条件会让完美匹配难以实现。
一般来说,一个 SAE 仅用于模型中的一个位置举个例子,我们可以在 26 和 27 层之间的中间激活上训练一个 SAE。为了分析 GPT-3 的全部 96 层的输出中包含的信息,可以训练 96 个分立的 SAE—— 每层的输出都有一个。如果我们也想分析每一层内各种不同的中间激活,那就需要数百个 SAE。为了获取这些 SAE 的训练数据,需要向这个 GPT 模型输入大量不同的文本,然后收集每个选定位置的中间激活。
下面提供了一个 SAE 的 PyTorch 参考实现。其中的变量带有形状注释,这个点子来自 Noam Shazeer,参见:https://medium.com/@NoamShazeer/shape-suffixes-good-coding-style-f836e72e24fd 。请注意,为了尽可能地提升性能,不同的 SAE 实现往往会有不同的偏置项、归一化方案或初始化方案。最常见的一种附加项是某种对解码器向量范数的约束。更多细节请访问以下实现:
- OpenAI:https://github.com/openai/sparse_autoencoder/blob/main/sparse_autoencoder/model.py#L16
- SAELens:https://github.com/jbloomAus/SAELens/blob/main/sae_lens/sae.py#L97
- dictionary_learning:https://github.com/saprmarks/dictionary_learning/blob/main/dictionary.py#L30
import torch
import torch.nn as nn# D = d_model, F = dictionary_size
# e.g. if d_model = 12288 and dictionary_size = 49152
# then model_activations_D.shape = (12288,) and encoder_DF.weight.shape = (12288, 49152)class SparseAutoEncoder (nn.Module):"""A one-layer autoencoder."""def __init__(self, activation_dim: int, dict_size: int):super ().__init__()self.activation_dim = activation_dimself.dict_size = dict_sizeself.encoder_DF = nn.Linear (activation_dim, dict_size, bias=True)self.decoder_FD = nn.Linear (dict_size, activation_dim, bias=True)def encode (self, model_activations_D: torch.Tensor) -> torch.Tensor:return nn.ReLU ()(self.encoder_DF (model_activations_D))def decode (self, encoded_representation_F: torch.Tensor) -> torch.Tensor:return self.decoder_FD (encoded_representation_F)def forward_pass (self, model_activations_D: torch.Tensor) -> tuple [torch.Tensor, torch.Tensor]:encoded_representation_F = self.encode (model_activations_D)reconstructed_model_activations_D = self.decode (encoded_representation_F)return reconstructed_model_activations_D, encoded_representation_F
标准自编码器的损失函数基于输入重建结果的准确度。为了引入稀疏性,最直接的方法是向 SAE 的损失函数添加一个稀疏度惩罚项。对于这个惩罚项,最常见的计算方式是取这个 SAE 的已编码表征(而非 SAE 权重)的 L1 损失并将其乘以一个 L1 系数。这个 L1 系数是 SAE 训练中的一个关键超参数,因为它可确定实现稀疏度与维持重建准确度之间的权衡。
请注意,这里并没有针对可解释性进行优化。相反,可解释的 SAE 特征是优化稀疏度和重建的一个附带效果。下面是一个参考损失函数。
# B = batch size, D = d_model, F = dictionary_size
def calculate_loss (autoencoder: SparseAutoEncoder, model_activations_BD: torch.Tensor, l1_coeffient: float) -> torch.Tensor:reconstructed_model_activations_BD, encoded_representation_BF = autoencoder.forward_pass (model_activations_BD)reconstruction_error_BD = (reconstructed_model_activations_BD - model_activations_BD).pow (2)reconstruction_error_B = einops.reduce (reconstruction_error_BD, 'B D -> B', 'sum')l2_loss = reconstruction_error_B.mean ()l1_loss = l1_coefficient * encoded_representation_BF.sum ()loss = l2_loss + l1_lossreturn loss
稀疏自编码器的前向通过示意图。
这是稀疏自编码器的单次前向通过过程。首先是 1x4 大小的模型向量。然后将其乘以一个 4x8 的编码器矩阵,得到一个 1x8 的已编码向量,然后应用 ReLU 将负值变成零。这个编码后的向量就是稀疏的。之后,再让其乘以一个 8x4 的解码器矩阵,得到一个 1x4 的不完美重建的模型激活。
假想的 SAE 特征演示
理想情况下,SAE 表征中的每个有效数值都对应于某个可理解的组件。
这里假设一个案例进行说明。假设一个 12,288 维向量 [1.5, 0.2, -1.2, ...] 在 GPT-3 看来是表示「Golden Retriever」(金毛犬)。SAE 是一个形状为 (49,512, 12,288) 的矩阵,但我们也可以将其看作是 49,512 个向量的集合,其中每个向量的形状都是 (1, 12,288)。如果该 SAE 解码器的 317 向量学习到了与 GPT-3 那一样的「Golden Retriever」概念,那么该解码器向量大致也等于 [1.5, 0.2, -1.2, ...]。
无论何时 SAE 的激活的 317 元素是非零的,那么对应于「Golden Retriever」的向量(并根据 317 元素的幅度)会被添加到重建激活中。用机械可解释性的术语来说,这可以简洁地描述为「解码器向量对应于残差流空间中特征的线性表征」。
也可以说有 49,512 维的已编码表征的 SAE 有 49,512 个特征。特征由对应的编码器和解码器向量构成。编码器向量的作用是检测模型的内部概念,同时最小化其它概念的干扰,尽管解码器向量的作用是表示「真实的」特征方向。研究者的实验发现,每个特征的编码器和解码器特征是不一样的,并且余弦相似度的中位数为 0.5。在下图中,三个红框对应于单个特征。
稀疏自编码器示意图,其中三个红框对应于 SAE 特征 1,绿框对应于特征 4。每个特征都有一个 1x4 的编码器向量、1x1 的特征激活和 1x4 的解码器向量。重建的激活的构建仅使用了来自 SAE 特征 1 和 4 的解码器向量。如果红框表示「红颜色」,绿框表示「球」,那么该模型可能表示「红球」。
那么我们该如何得知假设的特征 317 表示什么呢?目前而言,人们的实践方法是寻找能最大程度激活特征并对它们的可解释性给出直觉反应的输入。能让每个特征激活的输入通常是可解释的。
举个例子,Anthropic 在 Claude Sonnet 上训练了 SAE,结果发现:与金门大桥、神经科学和热门旅游景点相关的文本和图像会激活不同的 SAE 特征。其它一些特征会被并不显而易见的概念激活,比如在 Pythia 上训练的一个 SAE 的一个特征会被这样的概念激活,即「用于修饰句子主语的关系从句或介词短语的最终 token」。
由于 SAE 解码器向量的形状与 LLM 的中间激活一样,因此可简单地通过将解码器向量加入到模型激活来执行因果干预。通过让该解码器向量乘以一个扩展因子,可以调整这种干预的强度。当 Anthropic 研究者将「金门大桥」SAE 解码器向量添加到 Claude 的激活时,Claude 会被迫在每个响应中都提及「金门大桥」。
下面是使用假设的特征 317 得到的因果干预的参考实现。类似于「金门大桥」Claude,这种非常简单的干预会迫使 GPT-3 模型在每个响应中都提及「金毛犬」。
def perform_intervention (model_activations_D: torch.Tensor, decoder_FD: torch.Tensor, scale: float) -> torch.Tensor:intervention_vector_D = decoder_FD [317, :]scaled_intervention_vector_D = intervention_vector_D * scalemodified_model_activations_D = model_activations_D + scaled_intervention_vector_Dreturn modified_model_activations_D
稀疏自编码器的评估难题
使用 SAE 的一大主要难题是评估。我们可以训练稀疏自编码器来解释语言模型,但我们没有自然语言表示的可度量的底层 ground truth。目前而言,评估都很主观,基本也就是「我们研究一系列特征的激活输入,然后凭直觉阐述这些特征的可解释性。」这是可解释性领域的主要限制。
研究者已经发现了一些似乎与特征可解释性相对应的常见代理指标。最常用的是 L0 和 Loss Recovered。L0 是 SAE 的已编码中间表征中非零元素的平均数量。Loss Recovered 是使用重建的激活替换 GPT 的原始激活,并测量不完美重建结果的额外损失。这两个指标通常需要权衡考虑,因为 SAE 可能会为了提升稀疏性而选择一个会导致重建准确度下降的解。
在比较 SAE 时,一种常用方法是绘制这两个变量的图表,然后检查它们之间的权衡。为了实现更好的权衡,许多新的 SAE 方法(如 DeepMind 的 Gated SAE 和 OpenAI 的 TopK SAE)对稀疏度惩罚做了修改。下图来自 DeepMind 的 Gated SAE 论文。Gated SAE 由红线表示,位于图中左上方,这表明其在这种权衡上表现更好。
Gated SAE L0 与 Loss Recovered
SAE 的度量存在多个难度层级。L0 和 Loss Recovered 是两个代理指标。但是,在训练时我们并不会使用它们,因为 L0 不可微分,而在 SAE 训练期间计算 Loss Recovered 的计算成本非常高。相反,我们的训练损失由一个 L1 惩罚项和重建内部激活的准确度决定,而非其对下游损失的影响。
训练损失函数并不与代理指标直接对应,并且代理指标只是对特征可解释性的主观评估的代理。由于我们的真正目标是「了解模型的工作方式」,主观可解释性评估只是代理,因此还会有另一层不匹配。LLM 中的一些重要概念可能并不容易解释,而且我们可能会在盲目优化可解释性时忽视这些概念。
总结
可解释性领域还有很长的路要走,但 SAE 是真正的进步。SAE 能实现有趣的新应用,比如一种用于查找「金门大桥」导向向量(steering vector)这样的导向向量的无监督方法。SAE 也能帮助我们更轻松地查找语言模型中的回路,这或可用于移除模型内部不必要的偏置。
SAE 能找到可解释的特征(即便目标仅仅是识别激活中的模式),这一事实说明它们能够揭示一些有意义的东西。还有证据表明 LLM 确实能学习到一些有意义的东西,而不仅仅是记忆表层的统计规律。
SAE 也能代表 Anthropic 等公司曾引以为目标的早期里程碑,即「用于机器学习模型的 MRI(磁共振成像)」。SAE 目前还不能提供完美的理解能力,但却可用于检测不良行为。SAE 和 SAE 评估的主要挑战并非不可克服,并且现在已有很多研究者在攻坚这一课题。
有关稀疏自编码器的进一步介绍,可参阅 Callum McDougal 的 Colab 笔记本:https://www.lesswrong.com/posts/LnHowHgmrMbWtpkxx/intro-to-superposition-and-sparse-autoencoders-colab
参考链接:
https://www.reddit.com/r/MachineLearning/comments/1eeihdl/d_an_intuitive_explanation_of_sparse_autoencoders/
https://adamkarvonen.github.io/machine_learning/2024/06/11/sae-intuitions.html
#LLM大模型技术原理
导读对Llama 3大型语言模型技术的一次全面概述,涵盖了预训练、后训练及推理阶段的关键技术,包括数据处理、量化方法(如INT8和FP8量化)、以及如何通过微调提升模型效率和准确性等方面的内容。
本文从Llama 3报告出发,基本整理一些现代LLM的技术。'基本',是说对一些具体细节不会过于详尽,而是希望得到一篇相对全面,包括预训练,后训练,推理,又能介绍清楚一些具体技术,例如RM,DPO,KV Cache,GQA,PagedAttention,Data Parallelism等等的索引向文章。由于东西比较多,且无法详尽细节,所以推荐大家二次整理为自己的笔记。
本文的主要参考是Llama Team的The Llama 3 Herd of Models报告原文,以及沐神回归B站新出的论文精读系列。同时也包括一些知乎的优秀文章。
1 Intro
Illustration of the overall architecture and training of Llama 3
Overview of the Llama 3 Herd of models.
1.1 现代基础模型训练的主要阶段
(a)预训练阶段(pre-training stage):算法相对直接,一般是用大量的数据去做下一个词的预测(next-word prediction)。
(b)后训练阶段(post-training stage):算法比较丰富,包括SFT,RLHF,DPO等等。任务上看,包括让模型做一些指令跟随的任务(instruction following),将模型偏好对齐到人类喜好上(align with human preferences),或者提高模型在特定任务的能力,例如code,math,roleplay等等。
从过去的模型看,基本上可以认为GPT1,2,3都是在做pre-training,而InstructGPT和RLHF则是在做post-training。以上是较为笼统的介绍。
1.2 现代基础模型训练的关键
Meta:We believe there are three key levers in the development of high-quality foundation models: data, scale, and managing complexity.
meta认为现代基础模型训练的关键是:data, scale, and managing complexity。
(a)关于data ,Llama系列有堆数据的传统:相较于Llama 2 1.8T的预训练语料,Llama 3的预训练语料堆到了15T的multilingual tokens。
沐神:15个T可能是目前在公有的网络上面,能够抓到的文本数据的一个大概的上限,这个'上限'的意思是指,与其再找一些增量的数据,不如去调整现有的数据的质量。
(b)关于scale,Llama 3.1提供了8B,70B,405B三个规模。每个规模的性能差异可参考下面的benchmark。
(c)关于managing complexity,复杂度管理,说白了即Llama 3的算法相对简单。Llama 3选择了一个标准的稠密Transformer模型架构,只进行了少量调整,而没有选择MOE。后训练方面,Llama 3采用了SFT、RS和DPO,即一套'相对简单'的过程,而不是更复杂的RLHF算法,因为后者往往稳定性较差且更难以扩展。这些都属于design choice。2,3章会详细介绍相关技术。
1.3 benchmark表现
Llama 3各规格模型的benchmark表现如下。简要介绍其中的MMLU和IFEval。
Performance of finetuned Llama 3 models on key benchmark evaluations.
(a)MMLU系列 :类似于各种考试里面的选择题,只是主要考察模型的知识面(背答案)。
Question: Glucose is transported into the muscle cell: Choices:
A. via protein transporters called GLUT4.
B. only in the presence of insulin.
C. via hexokinase.
D. via monocarbylic acid transporters. Correct answer: A
原版MMLU是比较老的benchmark,存在大家overfit的可能性。MMLU-Pro相对更新一些,可以看到在MMLU-Pro上,8B,70B,405B的差距相当大,说明参数规模和内化到权重中的知识量还是非常相关的。
(b)IFEval :IF即Instruction Following,考察模型对指令的理解和遵循能力。原文见:IFEval Dataset | Papers With Code[1]。
IFEval 示例
在IFEVAL上,8B和70B的差距还是很明显的(80.4/87.5),而70B和405B的差距已经不明显了(87.5/88.6)。说明参数规模到达一定程度后,再想通过扩大规模来提IF能力,可能会逐渐不显著。
(c)剩下的benchmark则偏垂直一些,分别包含了Code,Math,Reasoning,Tool use,Long context,Multilingual,可参见报告原文。
补充:上述评估集既然都有overfit和leaking的风险,那还有没有其他的benchmark呢?当然,比如LiveBench这种monthly更新的benchmark,LiveBench[2]。不过,天底下是没有完美的benchmark的,尤其是对于具体业务而言。
总体上看,8B和70B在各方面差距都还是比较明显,但70B和405B在以上的评估集中,则差异相对小一些。405B的推理和训练都比较慢,一般情况下,70B算是复杂应用的首选。如果特别复杂,再考虑405B,毕竟性价比还是会差一些。值得一提的是,Llama 3.1 70B在IFEval上接近Claude3.5 sonnet的水准。
2 Pre-Training
Meta:Language model pre-training involves: (1) the curation and filtering of a large-scale training corpus, (2) the development of a model architecture and corresponding scaling laws for determining model size, (3) the development of techniques for efficient pre-training at large scale, and (4) the development of a pre-training recipe. We present each of these components separately below.
上文比较笼统地说明了Pre-Training的要点。
2.1 Pre-Training Data
- • Web Data Curation
预训练数据处理的要点包括de-duplication methods and data cleaning mechanisms,即去重和清洗,如果做得不好,质量会很差。具体报告中的Web Data Curation章节提到了以下内容:
(a)PII and safety filtering:报告提到预训练数据中移除了包含PII(personally identifiable information,关于人的身份信息,隐私信息)和成人内容的域名。但具体是什么一个标准来锚定该数据是否属于PII和成人内容,未给出示例一类的说明,所以大概率是混了一些进去的。
(b)Text extraction and cleaning:由于web data是raw HTML content,所以Llama构建了一个parser来解析各类文档。有趣的观点是,报告认为Markdown对模型的性能有害,因此删除了所有Markdown marker。但挪掉之后具体怎么做的,未加说明。
(c)De-duplication:Llama使用了三个级别的去重,URL,document, and line level。具体来说,URL去重即保留每个URL对应页面的最新版本。document级别则在整个数据集上采用了global MinHash来去除近似重复的文档。line level的具体做法则是按照每30M的documents进行搜索,去除其中出现超过6次的文本行。
(d)Heuristic filtering:启发式的过滤。包括n-gram的过滤,如果n比较长,重复较多,则把该行去掉,典型的例子是logging文本。也包括危险词的过滤,如果一个网页的dirty word太多,则去掉。报告还提到使用了基于token-distribution Kullback-Leibler divergence(KL散度)的方法来过滤过于奇葩的数据。即如果一个文档和其他文档算KL的距离差太远的话,就把该文档标记为奇怪的文档去掉。
KL散度的概念比较常用,是用于衡量两个概率分布之间的差异程度。定义为:
(e)Model-based quality filtering:基于模型的分类。比如fasttext和基于Llama 2训练的Roberta-based classifiers,分类包括分高质量or低质量,也可以是打领域tag等等。
(f)Code and reasoning data and Multilingual data:也是一些特定数据的抽取pipeline,花钱花人力做的一些工作。
- • 数据混合(Data Mix)
数据配比确实相当重要,且是实验性较强的工作(炼丹),烧钱烧时间出成果。报告中提到了Knowledge classification和scaling law的一些实验。
(a)Knowledge classification. 即使用一个分类器划分数据的类别,例如客观知识类,娱乐八卦类,成人内容类......娱乐八卦类的数据对模型就不太好,分类后就可以让这类数据少来一些。
(b)Scaling laws for data mix. 即多做不同配比的实验,看指标变化。稍详细一点说,是在不同的小模型上做不同的配比实验,然后用来预测更大scale的最优配比。
总结,最后的预训练数据大概是50%的general knowledge,25%的mathematical and reasoning数据,17%的code数据,8%的多语言数据。
- • 退火数据(Annealing Data)
报告发现,在少量高质量的code和math的数据上做一下学习率的退火,能够提升预训练模型的benchmark performance。这很符合直觉,即'考前多背一下题目考的会更好一些'。(?)
具体来说,是在大量通用数据的训练完成后,用一小撮高质量的特定领域数据继续训练,同时将学习率慢慢降低。Llama 3在预训练的最后40M token采取了将LR线性退火到0的方法,同时配合数据配比调整。最后8B模型在GSM8k和MATH验证集上提升不错,但对405B的模型提升却可以忽略不计,说明该参数规模的模型也许不需要specific in-domain的训练样本来提升性能。
同时,报告提到可以使用退火来评估domain-specific的小数据集的质量,比做Scaling Law的相关实验效率更高。
2.2 Model Architecture
总体上看,Llama 3相较于2做了以下改动:GQA,面向一个sequence内部的不同文档的attention mask,128K tokens的词表,RoPE的调整。
- • 基本推理过程 -> KV Cache -> GQA
Llama 3使用标准的Dense Transformer架构,性能的提高主要来自于数据质量和多样性的改进,以及训练规模的增加(很喜欢说一些实话)。当然,和Llama 2相比还算有一些改变:
例如上述提到的Grouped Query Attention:GQA用于加速推理,节省解码的内存。对于70B及以上的模型,几乎是必须用的技术。GQA涉及到KV Cache,KV Cache涉及到基本的推理过程,因此从推理开始写。
(a)基本推理过程
LLM推理过程
1、输入的Text,根据词表被切分成n个token/token ids,n个token ids被映射为n个embedding向量,即1个embedding矩阵;
2、embedding矩阵通过L个transformer block(内部有各种注意力计算和FFN层),在最后一层输出一个与输入形状相同的embedding矩阵;
3、输出的n个embedding再过一个线性层lm_head,该线性层的输出形状和词表大小一致。线性层输出再接一个softmax,就得到了next token的概率分;
4、随后再根据解码策略采样即可。Next token被算出来后,加入输入的token序列(长度为n+1),继续计算第n+2个token,这就是自回归。
(b)KV Cache
由于在计算第 个token时, L个Transformer block的中间结果是可以被保存下来的, 所以也许可以复用它们。我们把第 层,第 个token的输出记为 。不难发现,需要计算第 个 token时, 有很大一部分中间结果和计算 时相同。可表示为:
输 入 token 序 列: 与 输 入 token 序 列 为 的中间结果 一致,所以我们利用缓存来可以减少大量的计算。
因此,LLM推理过程分为Prefill和Decode两个阶段,Prefill阶段会对Prompt中所有的token做并行计算,得到Prompt中所有Tokens的KV Cache以及计算得到首Token。Prompt Tokens计算得到的KV Cache会保存下来,留给Decode阶段复用;
Decode阶段是一个自回归过程,每解码一个新的Token,都需要用到所有之前计算得到的KV Cache来计算当前query token的Attention。因此,当输出长度越来越大或者context很长时,KV Cache将会占用大量的显存。
本段内容以及下图引用自:[KV Cache优化] MQA/GQA/YOCO/CLA/MLKV笔记: 层内和层间KV Cache共享[3]。
所以现在也存在prefix caching的概念,简单地说,就是把特定前缀的KV Cache缓存起来保留备用。对于指令复杂,prompt较长的任务,或者多轮对话场景非常有效。vllm已经可以很方便地开启prefix caching,对长输入短输出的固定任务优化较好。KV Cache有大量的方向可以做,是LLM推理优化的核心之一。
(c)GQA,Grouped Query Attention
GQA是从模型层面降低KV Cache大小的手段之一。聊GQA之前的惯例是聊MHA和MQA。
MHA,即Multi Head Attention,多头注意力,Transformer原文的attention形式。如下图所示,MHA中每个Query向量都会对应一个Key,Value,其输出会把每个注意力头的输出拼接起来。因此也会存较多的KV Cache。
MQA,即Multi Query Attention。如下图所示,MQA的思路比较直接,就是让每个注意力头共用一个KV,很显然,相较于MHA,KV Cache的占用直接减少到了1/head_num。不过,由于结构的修改和Attention部分的参数量降低,模型效果也必然受到影响。MQA似乎还是有些暴力。
因此出现了平衡的版本,即GQA,Grouped Query Attention。和图中一致,即将Queries进行分组,每组对应一个KV,用一种折中的方法实现了减少计算量和KV Cache大小。
- • RoPE,旋转位置编码
首先应该聊聊经典的正弦编码。上文在LM的一次推理过程中提到,token会映射为embedding向量,在经典transformer的结构中,这个embedding向量是词嵌入向量(实体的'孤立'语义)和位置编码(实体间的'关联'语义)的叠加。如何表征token的位置,则是位置编码研究的问题。
《动手学深度学习PyTorch版》:全要点笔记[4],经典transformer架构的位置编码是正弦编码。
正弦编码存在一些可能的问题,比如对相对位置的表示较弱。RoPE则尝试在解决这些问题。
2.3 Scaling Laws
最初的形式
简单来说,就是可以用小模型的一些实验结果来预测更大模型的结果。Scaling Law由OpenAI提出,有两个大家熟知的结论:
1、对于Decoder-only的LM, 计算量 , 模型参数量 , 数据大小 , 三者满足 。其中 的单位是Flops, 是token数;
2、模型的最终性能主要与 相关,与模型的具体结构(高矮胖瘦)相关性不高。
Llama报告的内容?
之前的Scaling Law的预测方法主要是从next-token prediction loss(训练时的validation loss)出发的,但这个loss和具体的任务表现不一定是绝对相关的。因为next-token prediction loss并不和具体任务表现(例如数学)绝对挂钩。所以Llama 3在做Scaling Law的实验时,做了一个two-stage的方法:
step1:预测模型在具体下游任务上的NLL loss,这个NLL loss还是和compute(FLOPs)挂钩,成函数关系;
step2:利用Scaling Law将step1中的loss和具体的task accuracy关联起来。例如1.4的NLL loss对应0.25的accuracy,1.2的误差对应0.95的accuracy,所以这个规律和具体也可以解耦,得到对于一个具体benchmark的Scaling Law曲线,x,y轴分别为loss和accuracy。
具体可见下图。ARC Challenge benchmark是一个做推理的多选题任务集。发现Scaling Law的预测还是挺准的。不过要注意,不同任务的benchmark曲线可能也长得不一样。
2.4 Training Recipe
Llama 3的预训练策略主要由三步构成,分别为:(1) initial pre-training, (2) long-context pre-training, and (3) annealing.
Initial Pre-Training
主要是一些细节。简单翻译下。我们使用 AdamW 对 Llama 3 405B 进行预训练, peak learning rate 为 , linear warm up为 8000 步,以及cosine learning rate(预计在 步中衰减到 ) 。为了提高训练稳定性, 我们在训练初期使用了较小的批次大小, 并随后增加了批次大小以提高效率。具体来说, 我们使用的initial batch size为 4 M 的 tokens, 长度为 4096 的序列, 在训练了 252 M tokens后后将这些值加倍, 8 M sequences of 8,192 tokens。在训练了2.87 T token后, 再次将加倍到 16 M 。我们发现这种训练配方非常稳定:我们观察到的损失峰值(loss spikes)很少,并且不需要进行干预来纠正模型训练的偏差。
同时也做了一些data mix的调整。比如多拿非英语数据,数学数据,更多的最新网络数据等等。
Long Context Pre-Training
简单翻译下。在预训练的最后阶段,我们对 long sequences 进行训练,以支持最多 128K tokens 的 context窗口。我们之前没有对 long sequences 进行训练,因为在 self-attention layers 中的计算量随 sequence length 呈平方增长。我们逐步增加支持的 context length,进行 pre-training,直到模型成功适应了增加的 context length。
我们通过以下两点评估成功的适应性:(1) 模型在 short-context evaluations 中的表现是否完全恢复,具体来说可能就是MMLU这些评测集;(2) 模型是否能完美解决长度达到该值的 'needle in a haystack' 任务(大海捞针任务)。
在 Llama 3 405B 的 pre-training 中,我们逐步在六个阶段增加了 context length,从最初的 8K context窗口开始,最终达到 128K context窗口。这个 long-context pre-training 阶段使用了大约 0.8T tokens。
Annealing
见2.1 Pre-Training Data,同退火数据(Annealing Data)一节的内容。
3 Post-Training
下图很清晰地概括了Llama 3的后训练思路,要素包括RM,SFT,RS,DPO。本章会一一介绍。后训练是业内绝大多数NLPer做的事情。
Illustration of the overall post-training approach for Llama 3.
Llama 3后训练策略的backbone是一个Reward Model和一个Language Model。首先利用人类标注的偏好数据,在pre-trained checkpoint之上训练一个RM。然后,对pre-trained checkpoint做SFT,之后用DPO做对齐,作为本轮的最佳模型,进入下轮迭代,参与Rejection Sampling过程。
注意到,训练是迭代式的,即有多轮方法相同的训练。具体来说,Llama 3进行了6轮的循环。在每个周期中,收集新的偏好标注和 SFT 数据,并从最新的模型中采样合成数据。
3.1 Reward Model
红框部分是RM的训练路径
首先应该简介一下Reward Model(RM)。Reward Model是一种通过”偏好排序数据“(A >> B > C = D)训练得到的模型,能够给一段文本一个偏好性(例如安全性,拟人性,或者某种综合性的偏好)的分数。这个分数是一个标量,体现了人类的某种偏好。
而且,A > B可能不仅是A > B,也可能是远好于,稍好于,这个其实也能在损失函数里体现出来(margin loss),即Llama 2论文中的部分:
Preference Data构建
Llama详细讲解了Preference Data的构建过程。大概是这样几个step:
step 1. 使用不同的数据配比和训练策略训练出多个for annotation的模型。部署多个不同的模型,针对一个具体的user prompt采样出两个来自不同模型的response。
step 2. 标注同学会按照“好多少”的标准,对response对进行打分,包括四个等级:significantly better, better, slightly better, or marginally better。
step 3. 偏好标注好后,鼓励标注同学去“edit”chosen response,即他们上一步已经选择了更好的那个答案,改的更好。既可以直接修改chosen response本身,也可以修改prompt来refine这些数据。
所以,最后有一部分偏好数据是有三个ranked response的,即edited > chosen > rejected。最后,得到了这样的数据构成。
训练
训练和Llama 2类似。但是Llama 3反而在损失函数中去掉了margin loss,即上文的 ,因为观察到在数据规模扩大后,margin的改进效果逐渐减弱,不如简化。
3.2 SFT
SFT大概是大多数同学接触LLM训练的首选。SFT,即使用标准的交叉熵损失(standard cross entropy loss),同时mask prompt部分的loss,训练target tokens的过程。
SFT Data构建
SFT数据有很多个来源:Rejection Sampling的数据,针对特定能力的合成数据,少量的人工标注数据。
Rejection Sampling
Rejection Sampling的过程,就是固定模型和prompt,让LM采样出K个不同的答案,根据RM的K个不同的分数,选出最优答案。然后将该最优答案作为SFT数据,做迭代式的训练。其中,模型一般是前一轮训练中表现最好的checkpoint,K则可以调整,一般是10-30。采样也有很多细节,涉及到preference pair构造,比如rejected可能不能无脑选最差的,这些需要实验。
为了提高拒绝采样的效率,Llama 3采用了PagedAttention。在 PagedAttention 中,内存浪费只会发生在序列的最后一个块中,可以很好地提升吞吐量。PagedAttention的内存共享也是很好的优化,在Rejection Sampling中,多个response是由同一个prompt生成的。在这种情况下,prompt 的计算和内存可以在输出序列中共享。这里做一些简单介绍。
PagedAttention
think of blocks as pages, tokens as bytes and requests as processes。
PagedAttention也是主流推理加速框架vLLM之选。大家应该都学过OS课,了解虚拟内存,内存分页管理,内存碎片的概念。PagedAttention也是受到OS的启发,认为KV Cache 没有必要存储在连续的内存中,而是像操作系统一样,把块的概念引入为“page”,byte的概念引入为“token”,进程的概念引入为“request”。
2.2节中我们提到,由于在计算第n+1个token时,L个Transformer block的中间结果是可以被保存下来的,所以也许可以复用它们。这被称作KV Cache。
但是KV Cache非常大,需要一块连续内存来存储。并且,我们在接收到sequence之前,并不知道需要预留多少连续内存,所以只能预先分配一个最大可能长度的cache,导致了很多浪费,这被称为“内部碎片”。而由于我们给多个sequence分配了内存,所以剩下的内存不足以分配给新的sequence,这一部分内存实际上也没用了,所以也造成了浪费,这被称为“外部碎片”。
PagedAttention 允许在非连续的内存空间中存储连续的 key 和 value 。具体来说, 它将每个序列的 KV cache 划分为块,每个块包含固定数量 token 的键和值。因此,对于1个sequence,最多会有1个page是有内存碎片的。由于按块分配,外部碎片则彻底没有了。这和OS中的分页存储解决的问题一致。
回到SFT Data,最后,得到了这样的数据构成。
训练细节上,Llama 3对405B进行微调时,学习率为10⁻⁵,训练步数在8.5K到9K之间。
3.3 Rejection Sampling
见 3.2 SFT 中的Rejection Sampling。
3.4 Direct Preference Optimization
DPO在SFT之后进行,目的是对齐人类的偏好。DPO是RLHF的简化,目的是跳过复杂的RM训练等过程,RLHF是先用标注的偏好数据去训练RM,然后再指导RL的过程,而DPO则这把上述两个步骤的loss融合到一起。因此,DPO的训练数据也是人类偏好数据,格式类似于chosen-rejected对。DPO的损失如下
# DPO的数据格式
{ 'prompt': '', 'chosen': '', 'rejected': ''
}
DPO训练细节
在训练过程中,Llama 3主要使用最新一批的偏好数据,这些数据是通过前几轮对齐中表现最好的模型收集的,需要用到RM。好处是,这些数据更好地符合每轮正在优化的Policy Model的分布。所以这种DPO也是Iterative的,属于on-policy。
(a)第一个细节是,由于DPO损失函数的特点,chosen response和rejected response中如果出现了一些共同的token,则会导致相互冲突的学习目标,因为模型需要同时增加和减少这些token的生成概率。所以Llama 3 Mask了formatting tokens 的 loss,实验发现这些token如果算loss,可能会导致tail repetition和突然生成终止的token。
(b)第二个细节是,Llama 3给chosen sequence加上了一个negative log-likelihood(NLL) loss,从NLL loss和标准交叉熵损失的差别上看,可以简单把NLL loss理解为SFT loss:
加上NLL loss的好处是,防止chosen response的log probability下降。坏处是,chosen response如果本身不够好,加这个SFT loss可能也不太好,需要具体问题具体分析。
3.5 Data Processing and Quality Control
数据质量始终是最关键的。由于Llama 3的大部分训练数据是模型生成的,因此需要仔细进行清洗和质量控制。这和绝大多数垂直业务模型也一致。
数据清洗(Data cleaning)
首先,数据中往往存在一些不理想的模式,Llama 3就有过度使用表情符号或感叹号的问题。一些非常经典的AI味语风也需要注意,例如“过于喜欢滑跪”的语气问题,遇事不决就“对不起”或“我道歉”,这种样本应该不能在数据集中太多。
数据修剪(Data pruning)
Llama 3还应用了一些基于模型的技术来去除低质量的训练样本,来提升模型整体性能:
1、主题分类(Topic classification):首先,对一个小模型(如Llama 3 8B)进行微调,使其成为topic classifier,例如专门用一大堆分类文本的任务数据去SFT一下。然后对所有训练数据进行分类,将其分类为粗粒度类别(如“数学推理”)和细粒度类别(如“几何和三角学”)。
2、质量评分(Quality scoring):使用Reward model和基于Llama的信号为每个样本的质量打分。对于基于RM的评分,我们将得分处于RM评分前四分之一的数据视为高质量数据。对于基于Llama的评分,就是在Llama 3设计了一些打分的prompt,一般英语数据使用三个维度的评分(准确性、指令遵循性和语气/表达),coding数据则使用两个维度的评分(错误识别和用户意图),并将获得最高分的样本视为高质量数据。
最后发现RM评分和Llama评分的分歧率较高,但发现结合这两种机制能在meta内部测试集中取得最佳的召回率。最终,选择被RM OR Llama 3分类模型标记为高质量的样本。
3、难度评分(Difficulty scoring):由于还希望优先处理对模型来说更复杂的样本,因此报告提到两种难度评估方法对数据进行评分:Instag和基于Llama的评分。对于Instag,我们提示Llama 3 70B对SFT提示进行意图标注,意图越多,复杂性越高。基于Llama的思路和Quality scoring相似,给了Llama 3一些prompt,基于三个维度去打分。
4、语义去重(Semantic deduplication):最后,进行语义去重。Llama 3首先使用RoBERTa对完整对话进行聚类,然后在每个聚类内按质量分数 × 难度分数对其进行排序。接着,遍历所有排序的样本进行贪婪选择,仅保留与当前聚类中已见样本的余弦相似度小于阈值的样本。
4 Inference
首先请参考2.2 Model Architecture中,关于基本推理过程,KV Cache,GQA部分的内容,同时请参考3.2 SFT中关于PagedAttention的介绍。
4.1 Parallelism
Parallelism,LLM分布式训练推理的一部分,包括Data Parallelism和Model Parallelism,本节做一些介绍。同样涉及到OS的一些概念。
Data Parallelism
Data Parallelism,数据并行,在每个设备上,独立接收到不同的输入数据批次(可称mini-batch)并执行前向传播,以计算该批次上的损失。在反向传播过程中,每个设备会计算梯度,并与所有其他设备交换这些梯度。然后,使用这些梯度的平均值来更新每个设备上的模型权重,确保在下一次训练步骤开始时,所有设备都具有相同的模型权重。
好处是加快了batch的训练速度,并且能够放下更大batch size的数据。坏处是,每张卡也都使用了完整的模型权重,得保证单卡能装得下。
Data Parallelism
Model Parallelism
Model Parallelism。模型并行,包括Tensor Parallelism和Pipeline Parallelism。Model Parallelism解决的是单张卡放不下一个完整模型权重的问题,每张显卡只放部分参数。一般来说,会按照层进行划分参数,按层划分一般叫Pipeline Parallelism。如果模型的一层如果都装不下了,同一个模型层内拆分开训练,是Tensor Parallelism。
好处是能放下更大的权重了,坏处是后面层的卡需要等待前面层的计算结果,所以GPU会有空闲状态。反向传播时也一样,前面层的卡要等后面层的卡。
Llama 3中的Pipeline Parallelism
使用BF16数值表示模型参数时,Llama 3 405B模型无法在一台配备8个Nvidia H100 GPU的单机内完全加载到GPU内存中。为了解决这一问题,Llama 3 team使用两台机器(node)上的16个GPU并行进行BF16精度的模型推理。
在每个node内部,利用NVLink的high bandwidth来启用tensor parallelism。而在node之间,连接的带宽较低,延迟较高,因此采用pipeline parallelism(Gpipe)。
在使用pipeline parallelism进行训练时,bubble是一个主要的效率问题(详见论文Gpipe)。然而,在推理过程中,这并不是一个问题,因为推理不涉及反向传递。因此,Llama 3使用micro-batching来提高推理的吞吐量(throughput)。
Gpipe
在前向传播过程中,GPipe 首先将每个大小为 N 的mini-batch划分为 M 个相等的micro-batch,并将它们通过 K 个GPU进行流水线处理。在反向传播过程中,每个micro-batch的梯度是基于前向传播时使用的相同模型参数计算的。在每个mini-batch结束时,所有 M 个micro-batch的梯度会被累积,并应用于所有GPU以更新模型参数。
micro-batching效果
报告在key-value cache pre-fill stage和decoding stage两个阶段(见 2.2 Model Architecture 的讲解)都评估了micro-batches的效果。在4096个输入 tokens和256 个输出 tokens的情况下,报告发现,在相同的local batch size下,micro-batches提高了推理的吞吐量,如下图所示。
这些改进归因于micro-batches在这两个阶段中实现了并发执行。由于micro-batches带来了额外的同步点(synchronization points),导致延迟增加,但总体而言,micro-batches仍然带来了更好的吞吐量-延迟平衡(throughput-latency trade-off)。
4.2 Quantization
Quantization,量化,也是当前热门的话题,核心手段是通过降低模型参数的精度来减少GPU占用,并减少计算量。和PagedAttention类似,同样可以从OS中找到很多相关的东西。一些常见的精度表示如下:
INT8 量化
INT 8量化相对简单。如图所示的是absmax的INT 8量化,输入是一个FP16的向量。假设用 absmax 对向量[1.2, -0.5, -4.3, 1.2, -3.1, 0.8, 2.4, 5.4]进行量化。首先需要计算该向量的最大绝对值,在本例中为5.4。Int8 的范围为[-127, 127],因此我们将127除以5.4,得到缩放因子(scaling factor)23.5。最后,将原始向量乘以缩放因子得到最终的量化向量[28, -12, -101, 28, -73, 19, 56, 127]。
要恢复原向量,可以将 int8 量化值除以缩放因子,但由于上面的过程是“四舍五入”的,我们将丢失一些精度。
FP8 量化
Llama 3利用H100 GPU的原生FP8支持来执行低精度推理。为了启用低精度推理,Llama 3对模型内部的大多数矩阵乘法应用FP8量化。实现细节见下面的两篇参考文章。特别是,对模型中前馈网络层的大多数参数和激活值进行量化,这些部分约占推理计算时间的50%。其中还有一些细节:
Llama 3没有对模型的自注意力层中的参数进行量化。也没有在第一个和最后一个Transformer层中执行量化。并且,采用了按行量化的方式,对参数和激活矩阵的每一行计算缩放因子(Scaling Factor)。如下图所示。
量化结果
量化结果主要是两个方面,一个是好处,即efficiency的提升;一个是坏处,即accuracy的下降。
对于efficiency,Llama 3针对于4,096 input tokens and 256 output tokens做了定量实验,在prefill阶段(2.2 Model Architecture 中有详细介绍),使用FP8推理可将吞吐量提高多达50%(4k->9k);在decode阶段,也能更好地trade off throughput-latency。
对于accuracy,在标准benchmark上,即使不做上文所说的细节,FP8推理的表现也与BF16推理相当。但是当Scaling Factor没有上限时,模型有时会生成错误的响应,所以benchmark无法正确和充分地反映FP8量化的影响。于是Llama 3使用FP8和BF16生成了100,000个响应,选择用奖励模型的分布来分析。从下图可以看到,FP8的得分几乎没有影响RM的得分分布。
Throughput-latency trade-off in FP8 inference with Llama 3 405B
Reward score distribution for Llama 3 405B using BF16 and FP8 inference.
5 写在最后
最近平时工作可以说是把脑子想“干”了,所以花大概三个周末完成了这篇接近2w字的文章。写完感觉有很多不足,但还是随便找个时间发了吧。其一是,本来是打算从Llama 3这种优质开源模型和报告出发,进行一些知识上的梳理,结果行文时几乎保留了论文原来的结构,导致前一个知识点到下一个知识点不够丝滑;
其二是,由于水平不够和“综合性”考量的限制,所以对很多需要深入的知识没有详尽。后面几个周末也许还会持续迭代一下本文,主要是继续细化技术点。所以也恳请诸位指出错误或不足,尽情提出需要补充内容的部分。
引用链接
[1] IFEval Dataset | Papers With Code: https://paperswithcode.com/dataset/ifeval
[2] LiveBench: https://livebench.ai/
[3] [KV Cache优化] MQA/GQA/YOCO/CLA/MLKV笔记: 层内和层间KV Cache共享: https://zhuanlan.zhihu.com/p/697311739
[4] 《动手学深度学习PyTorch版》:全要点笔记: https://zhuanlan.zhihu.com/p/664880302
#70倍极致压缩
大模型的检查点再多也不怕
该论文的作者均来自于华为诺亚实验室,第一作者为李文硕,通讯作者为王云鹤和陈醒濠。相关团队团队近年来在ICML、CVPR、NeurIPS、ICCV、ECCV等顶会上有多项代表性工作发表,在高效大语言模型、视觉模型等领域都有丰富的成果产出,和知名高校和科研机构合作广泛。
大模型作为当下 AI 工业界和学术界当之无愧的「流量之王」,吸引了大批学者和企业投入资源去研究与训练。随着规模越做越大,系统和工程问题已经成了大模型训练中绕不开的难题。例如在 Llama3.1 54 天的训练里,系统会崩溃 466 次,平均 2.78 小时一次!
那么,频繁存储检查点就显得十分必要。但存储检查点本身也是一个大工程。
Meta 做了很多努力来加速存储检查点时间和增加存储频率,来对抗频繁出现的系统失效。但频繁存储也意味着大量的存储资源开销,其训练集群配备了 240PB 的 SSD 来应对这一挑战,光存储这一项的耗费就要亿元!
华为诺亚的 ExCP 方法也就应运而生,为了应对存储带来的巨大开销,他们提出了极致压缩检查点技术,能够无损压缩模型 70 倍,大幅降低训练中的存储开销。
代码目前已经开源,在 Apache 2.0 框架下发布,issue 中已经有小伙伴成功复现了结果。
- 文章地址:https://arxiv.org/abs/2406.11257
- 仓库地址:https://github.com/Gaffey/ExCP
方法也很有创新性,文章中提到了两个重要的概念,一个是利用训练中检查点的残差信息,通过时间序列上信息的稀疏性实现更高的剪枝比例;另一个是将优化器和权重联合起来进行压缩,实现整体的高压缩率。
具体方法
1. 检查点残差
在训练过程中,当前的参数可以看作上一个检查点存储的权重加上逐次迭代时梯度更新的总和,这部分是相对稀疏的,包含的信息量较少,因此对这一残差进行压缩,可以获得更好的压缩比例。而与此相反的,优化器中存储的动量是梯度一阶矩和二阶矩的滑动平均值,对于一阶矩来说,它的滑动平均默认的参数是 0.9,在数百到数千个迭代之后与上一次检查点存储的内容已经没有太大的关联,所以对于优化器直接压缩其本身的值而非残差。最终待压缩的检查点表示为
2. 权重 - 优化器动量联合压缩
目前已有的模型压缩相关的工作一般只关注于模型的推理性能,或者是模型最终存储检查点的大小,而不关注模型在整个训练过程中对储存空间的开销。因而已有工作只对权重进行压缩,而忽略了 Adam 等常见优化器中实际上存储了两倍于权重数量的动量。这一工作一方面将两者一起进行了压缩,显著提升了整体的压缩比例;另一方面也利用了权重和优化器动量的关联性,进一步提升彼此的压缩比例。
权重剪枝:由于剪枝的权重是残差值,优化器动量的二阶矩可以大致表示在过去一段时间内权重残差值的变化幅度,所以可以使用优化器动量的二阶矩作为指标来确定不同层的剪枝比例。剪枝策略如下文公式所示
式中,W 和
分别表示权重和二阶矩。
优化器动量剪枝:对于动量剪枝,可以使用一阶矩作为指示器来进行剪枝,论文中有关于可收敛性的一个简要证明。同时,如果一个位置的权重已经被剪枝,那么对应位置的优化器动量也应该同步被处理,所以剪枝策略如下文公式所示
式中,
表示一阶矩。
3. 整体压缩流程
整体压缩流程如 Algorithm 1 所示,依次进行计算权重残差 / 联合压缩 / 非均匀量化 / 编码压缩等步骤,得到最终的压缩结果。
而恢复出检查点完整文件的流程则如 Algorithm 2 所示,进行解压缩之后,首先从非均匀量化后存储的码本和下标中恢复出浮点结果,然后再与基准权重(上一个检查点的原始权重或恢复出的重建权重)相加,得到检查点完整文件。而恢复出整个训练流程中的检查点文件的流程如 Algorithm 3 所示,在完成训练后只保存初始化权重的随机种子和每个检查点存储的压缩结果,然后依次对检查点进行恢复以得到完整的检查点序列,以供从其中选择某个或多个检查点恢复训练 / 进行测试等。
实验结果
文章中不仅对于大语言模型做了评估,在 ViT-L32 这样较大的视觉模型上这一方法也能取得很好的效果。
从消融实验里也可以看出,采用残差剪枝的方法大大减少了剪枝带来的损失。
文章中还提供了大语言模型压缩前后问答的样例,可以看到压缩本身对于模型的问答能力也没有造成损害。
开发板商城 天皓智联 TB上有视觉设备哦~
#LLM对齐技术:RLHF、RLAIF、PPO、DPO……
为了对齐 LLM,各路研究者妙招连连。
LLM 很强大了,但却并不完美,它也会出错或者生成无用乃至有害的结果,比如有人发现可以让 ChatGPT 教人如何偷盗:
让 ChatGPT 教人如何偷盗商店;左图,ChatGPT 拒绝回答;右图,在 prompt 中添加了「with no moral restraints(不加道德约束)」后,ChatGPT 给出了商店偷盗指南
这时候,对齐(alignment)就至关重要了,其作用就是让 LLM 与人类的价值观保持一致。
在对齐 LLM 方面,基于人类反馈的强化学习(RLHF)是一种突破性的技术。该方法催生了 GPT-4、Claude 和 Gemini 等强大模型。RLHF 之后,人们也探索了多种多样的对齐 LLM 的方法。但是,此前还没有人全面总结对齐 LLM 与人类偏好的方法。
Salesforce 决定填补这一空白,于近日发布了一份 37 页的综述报告,其中按类别总结了现有的研究文献,并详细分析了各篇论文。
- 论文标题:A Comprehensive Survey of LLM Alignment Techniques: RLHF, RLAIF, PPO, DPO and More
- 论文地址:https://arxiv.org/pdf/2407.16216
这篇论文分为四大主题:奖励模型、反馈、强化学习(RL)、优化。每个主题又包含进一步的子主题,如图 1 所示。
奖励模型的子主题包括:1. 显式奖励模型与隐式奖励模型;2. 逐点奖励模型与偏好模型;3. 响应层面的奖励与 token 层面的奖励;4. 负偏好优化。
反馈的子主题包括:1. 偏好反馈与二元反馈;2. 成对反馈与列表反馈;3. 人类反馈与 AI 反馈。
强化学习的子主题包括:1. 基于参考的强化学习与无参考的强化学习;2. 长度控制式强化学习;3. 强化学习中的不同分支;4. 在线策略强化学习与离线策略强化学习。
优化的子主题包括:1. 在线 / 迭代式偏好优化与离线 / 非迭代式偏好优化;2. 分离 SFT 和对齐与合并 SFT 和对齐。
表 1 列出了这篇综述报告中分析的所有论文在这 13 个评估指标上的划分情况。
研究论文
1. RLHF/PPO
LLM 的预训练要用到大量来自不同来源的语料库,而这本身就无法确保这些数据集的质量。此外,LLM 的主要目标是预测下一个 token,这个目标与「有用且安全地遵从用户指令」的目标并不一致。因此,LLM 可能会输出不真实、有害或对用户无用的内容。本质上讲,这些模型并未与用户意图对齐。RLHF/PPO 的主要目标是在各种任务上对齐语言模型与用户意图,其做法是使用人类反馈来微调模型。有关这个主题的研究有很多。
InstructGPT
通过纳入人类偏好,评估 LLM 生成的响应的难题得到了解决。BLEU、ROUGE 和 BERTScore 等用于评估 LLM 的传统评估指标无法保证与人类偏好的一致性。为了解决这个问题,研究者直接将人类偏好整合进了 LLM 以增强其性能。这个过程通常涉及两个主要步骤:奖励模型学习和强化学习策略训练。
在奖励模型学习阶段,会使用 prompt 和配对的响应训练一个显式的逐点奖励函数。
之后,开始强化学习策略训练阶段;在这个阶段,LLM 和预训练奖励模型分别作为一个强化学习框架中的智能体和环境。
为了训练 InstructGPT,要用到三个数据集:1.SFT 数据集:包含用于训练 SFT 模型的标注者演示。2.RM(奖励模型)数据集:由人类标注者对模型输出的排名构成,用于训练奖励模型。3.PPO 数据集:由用作 RLHF 微调输入的 prompt 构成。
训练后的 InstructGPT 会在三个方面得到评估:有用性、可信度、有害性。
从结果上看,人类评估表明「相比于 175B 的 GPT-3,人们 更偏好 1.3B 参数版本的 InstructGPT 模型的输出,尽管后者的参数量少 100 多倍。」值得注意的是,InstructGPT 在有用性和毒性任务上的表现均优于 GPT-3,这于对齐而言至关重要。
Anthropic 的 RLHF
Anthropic 也研究过同一主题,论文为《Training a helpful and harmless assistant with reinforcement learning from human feedback》。
OpenAI 发现 RLHF 有助于对齐,但也可能导致模型在某些 NLP 基准上的性能下降,这个现象被称为「对齐税(alignment tax)」。其开发的 InstructGPT 模型有 1.3B 参数。相反,Anthropic 的研究者评估了大小在 13M 到 52B 之间的 7 种不同模型,这些模型的大小按 4 倍的几何级数增长。
他们得出结论说,对较小的模型来说,对齐会产生「税」,但对较大模型来说,对齐只有好处,尤其是参数量在 13B 到 52B 之间的模型。
考虑到对齐的这种优势,他们还实验了用编程技术数据集来提升 LLM 的能力。OpenAI 的 RLHF 方法包含 PPO 和 PPO-ptx,其中 PPO-ptx 的设计目标就是为了降低在 NLP 基准上的对齐税。而 Anthropic 的 RLHF 研究发现,只要模型够大,PPO 本身就能在 NLP 下游任务上带来对齐的好处。他们还确定了强化学习策略训练中 KL 散度的最优参数为 β = 0.001。
在线 / 迭代式 RLHF
传统上,对齐 LLM 的 RLHF 技术都是离线方法。但这类方法有些缺点,比如所得结果难以应对分布外数据。
为此,需要对 LLM 进行持续的微调,进行迭代式 / 在线学习,即使用中间策略为 prompt 生成响应,再使用预言机(oracle)为这样的成对数据给出偏好反馈,再将这些反馈馈送给策略。在实践中,迭代式学习分为两个部分:偏好预言机学习和迭代式策略优化。参阅论文《RLHF workflow: From reward modeling to online RLHF》。
2. RLAIF
获取人类偏好数据集的成本不低,因此基于人工智能反馈的强化学习(RLAIF)诞生了。此外,随着 LLM 的能力不断进步,所能收集到的 AI 偏好数据集的质量也不断提高,由此可提升 LLM 的对齐效果。
Anthropic 的 RLAIF
Anthropic 基于 RLHF 的基础研究工作,提出了一种名为 RLAIF 的全新方法。参阅论文《Constitutional ai: Harmlessness from ai feedback》。
该方法主要包含两个阶段:1. 通过 Critiques(批评)和 Revisions(修订)进行监督学习,这由一个章程引导。2. RLAIF。
谷歌的 RLAIF
基于 Anthropic 的 RLAIF 研究成果,谷歌一个研究团队认为之前的研究无法直接比较人类反馈与 AI 反馈的效果,值得进一步研究。在收集 AI 反馈的过程中,要创建一个结构化的 prompt,其构成包括:导言、少样本示例(可选)、要标注的样本、结尾。
为了生成 AI 反馈,需要执行一个两步式评估:首先,使用指令中的 4 个组件加上 CoT,让 LLM 生成响应。在下一步中,这个 LLM 响应再附带上「preferred summary=」这样的结尾被发送回 LLM,从而生成「summary 1=0.6, summary 2=0.4」这样的偏好概率。为了减少位置偏差,需要交替放置这两个响应的序列,并计算其平均分数。
RLAIF 过程采用了两个策略:1.「蒸馏 RLAIF」,其遵循传统的 RLHF 方法,即使用偏好训练一个奖励模型,然后再将其用于训练 LLM 策略;2. 「直接 RLAIF」,其直接将 LLM 反馈用作 prompt 来输出评估分数,再将该分数用作强化学习策略训练的信号。
最后,其评估过程会使用三个关键指标:1.AI - 标注者对齐度:AI 与人类标注者的一致程度。2. 胜率:人类标注者比较两个候选项并选择其中某一个的可能性。3. 无害率:人类评估者认为无害的响应的占比。
更多详情请参阅论文《RLAIF: Scaling reinforcement learning from human feedback with AI feedback》。
直接人类偏好优化
传统 RLHF 方法通常涉及到优化源自人类偏好的奖励函数。该方法虽有效,但也可能带来一些难题,比如增大计算复杂度以及在估计和优化奖励时需要考虑偏置 - 方差权衡。参阅论文《High-dimensional continuous control using generalized advantage estimation》。
近期有研究探索了其它一些旨在根据人类偏好(无需依赖某个标量的奖励信号)来直接优化 LLM 策略的方法。
这些方法的目标是通过更直接地使用偏好数据来简化对齐流程、降低计算开销以及实现更稳健的优化。通过将该问题描述为一个偏好优化问题,而不是奖励估计和最大化问题,这些方法能提供一种将语言模型与人类判断对齐的不同视角:
- SliC-HF,使用人类反馈进行序列似然校准,参阅论文《SliC-HF: Sequence likelihood calibration with human feedback》。
- RSO,拒绝采样优化,参阅论文《Statistical rejection sampling improves preference optimization》。
- DPO,直接偏好优化,参阅论文《Direct preference optimization: Your language model is secretly a reward model》。
- DPOP,DPO-positive,参阅论文《Smaug: Fixing failure modes of preference optimisation with DPO-positive》。
- β-DPO,参阅论文《β-DPO: Direct preference optimization with dynamic β》。
- IPO,身份偏好优化,参阅论文《A general theoretical paradigm to understand learning from human preferences》。
- sDPO,逐步 DPO,参阅论文《sDPO: Don’t use your data all at once》。
- GPO,广义偏好优化,参阅论文《Generalized preference optimization: A unified approach to offline alignment》。
token 级 DPO
使用 DPO 时,奖励会被一起分配给 prompt 和响应。相反,使用 MDP 时,奖励会被分配给各个动作。后续的两篇论文在 token 层面阐述了 DPO 并将其应用扩展到了 token 级的分析。
- DPO 可以执行 token 级信用分配的研究,参阅论文《From r to Q∗: Your language model is secretly a Q-function》,报道《这就是 OpenAI 神秘的 Q*?斯坦福:语言模型就是 Q 函数》。
- TDPO,token 级 DPO,参阅论文《Token-level direct preference optimization》。
迭代式 / 在线 DPO
使用 DPO 时,会使用所有可用的偏好数据集来对齐 LLM。为了持续提升 LLM,应当实现迭代式 / 在线 DPO。这就引出了一个有趣的问题:如何高效地收集新的偏好数据集。下面两篇论文深入探讨了这一主题。
- 自我奖励式语言模型,参阅论文《Self-rewarding language models》。
- CRINGE,参阅论文《The cringe loss: Learning what language not to model》。
二元反馈
事实证明,收集偏好反馈比收集二元反馈(比如点赞或点踩)的难度大,因此后者可促进对齐过程的扩展。KTO 和 DRO 这两项研究关注的便是使用二元反馈来对齐 LLM。
- KTO,Kahneman-Tversky 优化,参阅论文《KTO: Model alignment as prospect theoretic optimization》。
- DRO,直接奖励优化,参阅论文《Offline regularised reinforcement learning for large language models alignment》。
融合 SFT 和对齐
之前的研究主要还是按顺序执行 SFT 和对齐,但事实证明这种方法很费力,并会导致灾难性遗忘。后续的研究有两个方向:一是将这两个过程整合成单一步骤;二是并行地微调两个模型,最终再进行融合。
- ORPO,比值比偏好优化,参阅论文《ORPO: Monolithic preference optimization without reference model》。
- PAFT,并行微调,参阅论文《PAFT: A parallel training paradigm for effective llm fine-tuning》。
长度控制式 DPO 和无参考 DPO
之前有研究表明,LLM 的输出往往过于冗长。为了解决这个问题,R-DPO 和 SimPO 的关注重心是在不影响生成性能的前提下实现对响应长度的控制。
此外,DPO 必需参考策略来确保已对齐模型不会与参考模型有太大偏差。相较之下,SimPO 和 RLOO 提出了一些方法,可以在不影响 LLM 效果的情况下消除对参考模型的需求。
- R-DPO,正则化 DPO,参阅论文《Disentangling length from quality in direct preference optimization》。
- SimPO,简单偏好优化,参阅论文《SimPO: Simple preference optimization with a reference-free reward》,报道《全面超越 DPO:陈丹琦团队提出简单偏好优化 SimPO,还炼出最强 8B 开源模型》。
- RLOO,REINFORCE Leave-One-Out,参阅论文《Back to basics: Revisiting reinforce style optimization for learning from human feedback in LLMs》。
逐列表的偏好优化
之前在 PPO 和 DPO 方面的研究关注的是成对偏好,而 RLHF 方面的研究则是收集逐列表的偏好来加速数据收集过程,之后再将它们转换成成对偏好。尽管如此,为了提升 LLM 的性能,直接使用逐列表的数据集来执行偏好优化是可行的。以下三篇论文专门讨论了这种方法。
- LiPO,逐列表偏好优化,参阅论文《LIPO: Listwise preference optimization through learning-to-rank》。
- RRHF,参阅论文《RRHF: Rank responses to align language models with human feedback without tears》。
- PRO,偏好排名优化,参阅论文《Preference ranking optimization for human alignment》。
负偏好优化
这些研究有一个共同前提:当前这一代 LLM 已经在翻译和总结等任务上超越了人类性能。因此,可以将 LLM 的输出视为期望响应,而无需依靠将人类标注的数据视为偏好响应;这样做是有好处的。反过来,不期望得到的响应依然也可被用于对齐 LLM,这个过程就是所谓的负偏好优化(NPO)。
- NN,否定负例方法,参阅论文《Negating negatives: Alignment without human positive samples via distributional dispreference optimization》。
- NPO,负例偏好优化,参阅论文《Negative preference optimization: From catastrophic collapse to effective unlearning》。
- CPO,对比偏好优化,参阅论文《Contrastive preference optimization: Pushing the boundaries of llm performance in machine translation》。
纳什学习
之前的研究通常是使用逐点奖励和 BT 模型来得到成对偏好。但是,这种方法比不上直接成对偏好建模并且无法解决成对偏好中的不一致问题。为了克服这些局限,一些研究提出了纳什学习方法。
- 根据人类反馈的纳什学习,参阅论文《Nash learning from human feedback》。
- SPPO,自博弈偏好优化,参阅论文《A minimaximalist approach to reinforcement learning from human feedback》。
- DNO,直接纳什优化,参阅论文《Direct nash optimization: Teaching language models to self-improve with general preferences》。
不同方法的比较
一些研究则是为了比较这些不同方法。这类研究可以阐释每种方法各自的优缺点。
- 评估 DPO 及其变体
论文《Insights into alignment: Evaluating dpo and its variants across multiple tasks》在推理、数学问题求解、可信度、问答和多任务理解等多种任务上全面评估了隐式奖励模型,即无强化学习算法,包括 DPO、KTO、IPO 和 CPO。这些评估涉及三个不同场景:1) 微调监督式微调(SFT)模型、2) 微调预训练模型、3) 微调指令模型。
该研究发现,在大多数基准上,KTO 比其它对齐方法更优。此外,研究表明,对齐并不会显著提升模型的推理和问答性能,但确实能大幅提升模型的数学问题求解能力。该研究还注意到了数据量的重要性,对齐方法在较小的数据子集上的性能最佳。此外,研究发现 KTO 和 CPO 能有效绕过 SFT 阶段,在不影响性能的前提下直接进入对齐阶段。相比之下,当绕过 SFT 阶段,直接进入对齐阶段时,DPO 和 IPO 会表现出明显的性能下降。
- DPO 是比 PPO 更好的 LLM 对齐方法吗?
论文《Is DPO superior to PPO for LLM alignment? A comprehensive study》表明,DPO 可能存在固有局限,可能会产生有偏差的解答,并可能由于分布变化而导致性能下降,
他们发现,DPO 训练出的策略倾向于未曾见过的响应,尤其是分布外的样本。而迭代式 / 在线 DPO 则能缓解这个问题,其做法是广泛探索响应空间并不断更新参考模型。相较之下,RLHF/PPO 则是通过优势归一化、大批量大小以及对参考模型使用指数移动平均来解决这些挑战。最终,这些发现表明 PPO 优于迭代式 / 在线 DPO,而这又进一步优于标准 DPO。
未来方向
通过分析过往论文,该团队确定了一些有待进一步探索的研究问题。
用于对齐评估的一般任务
不同论文使用了不同的任务来评估这些方法的性能。但是,GSM8K 等一些任务更关注推理,可能并不适合用于评估对齐性能。相反,TruthfulQA 等任务或那些关注毒性的任务应当优先考虑,以评估已微调 LLM 的毒性。应当想办法将这些任务组合起来,创建一个用于评估对齐的统一排行榜。
将隐式奖励模型、逐列表偏好和纳什学习用于更大规模的语言模型
目前,使用隐式奖励模型的最大模型的参数量也不过 70B。如果能将这些方法扩展用于更大的模型,比如 GPT-4 和 Claude-3 大小的模型,那应该能帮助我们更好地理解它们与 RLHF/PPO 的相对效果。
类似地,逐列表偏好模型也值得进一步研究。使用 RLHF 时,要使用逐列表偏好收集偏好数据集,之后再将其转换成多对成对偏好数据。大规模应用逐列表偏好模型的潜在问题依然有待解决。
最后,纳什学习可以解决人类标注者之间的不一致问题。如果能将纳什学习模型集成到更大规模的 LLM 中,就可以证明其捕获人性复杂性的能力。
有关二元反馈的实验
KTO 和 DRO 都采用了「点赞」和「点踩」这样的二元反馈机制,而不是成对偏好。这些二元反馈来自偏好数据集,其中将期望响应标记成正例,将不期望响应标记成负例。我们还需要对现实的二元数据集进行进一步研究。此外,相比于偏好数据,二元数据集更容易收集,因此有望使用更大规模的二元反馈数据集来进行对齐。但是,二元反馈中的噪声可能比偏好数据集中的噪声更加明显,因此如何有效滤除有噪声数据也是一个非常有趣的研究方向。
实验研究有用的 AI 反馈
目前的 AI 反馈主要包括 RLAIF 中的无害反馈和迭代式 DPO 中的反馈排名。但是,使用 RLAIF 时,有用反馈依然是由人类标注者提供。这种方法是合理的,因为生成有用响应的难度比识别有害反馈明显大得多。一个有趣的未来研究方向是使用 LLM 来生成有用的反馈,由此让 LLM 可以自我提升。
加速纳什学习
纳什学习方法可以有效建模成对偏好并解决人类标注之间的不一致问题。但是,它必需多次迭代才能收敛到最优策略。尽管其作者没有明说对齐所需的时间,但可猜测其会比 DPO 等隐式奖励模型慢得多。因此,提升纳什学习过程的速度也是一个值得关注的研究方向。
迭代 / 在线学习的终止
在使用迭代 / 在线训练时,确定终止迭代的时间很关键。之前有研究发现,迭代式学习有时会降低 LLM 在某些任务上的性能,这可能是过拟合的迹象。但是,目前还没有研究者探索如何确定终止迭代的合理 epoch。
简化 SFT + 对齐
当前的方法通常是以一种连续方式实现 SFT 和对齐。但是,这种方法往往会导致灾难性遗忘,并让整个训练过程变得更加费力。PAFT 方法减轻灾难性遗忘的方式是先分别微调 SFT 和对齐然后再将它们融合到一起,但这也会提升复杂性。相较之下,ORPO 技术是同时整合这两个过程,但却会导致性能下降。那么,该如何有效地将 SFT 和对齐组合起来实现高性能同时又维持高效率呢?这还是一个有待解决的挑战。
#大模型原理解读
生成式 AI 太火爆了,可以说无处不在,频频刷爆我们的朋友圈。你可能已经试用过 ChatGPT 了,甚至已经把它当作你的智能小助手。
但我知道很多人心里会有个疑问:这些 AI 模型的智能究竟是怎么来的?今天咱们就来聊聊这个话题。我会用大家都能懂的,而不是那些让人头大的高等数学术语来解释生成式文本模型的工作原理,揭开它的神秘面纱,把它变成简单的计算机算法。
#01
LLM 的功能
首先,我要澄清人们对 LLM 工作原理的一个重大误解。大多数人认为这些模型可以回答问题或与你聊天,但实际上它们只能接收你提供的一些文本作为输入,然后猜测下一个词(更准确地说,下一个 Token)是什么。
让我们从 Token 开始了解 LLM 的奥秘。
Token
Token 是 LLM 理解的文本基本单位。虽然将 Token 看作单词很方便,但对 LLM 来说,目标是尽可能高效地编码文本,所以在许多情况下,Token 代表的字符序列比整个单词都要短或长。标点符号和空格也被表示为 Token,可能是单独或与其他字符组合表示。
LLM 使用的所有 Token 统称为其词汇,因为它可以用来表示任何可能的文本。字节对编码(BPE)算法通常用于 LLM 生成 Token 词汇。为了让你对规模有个大致的了解,GPT-2 语言模型是开源的,可以详细研究,其词汇量为 50,257 个 Token。
LLM 词汇中的每个 Token 都有一个唯一的标识符,通常是一个数字。LLM 使用分词器在常规文本字符串和等效的 Token 数列表之间进行转换。如果你熟悉 Python 并想尝试 Token,可以安装 OpenAI 的 tiktoken 包:
$ pip install tiktoken
然后在 Python 提示符中尝试以下内容:
>>> import tiktoken
>>> encoding = tiktoken.encoding_for_model("gpt-2")>>> encoding.encode("The quick brown fox jumps over the lazy dog.")
[464, 2068, 7586, 21831, 18045, 625, 262, 16931, 3290, 13]>>> encoding.decode([464, 2068, 7586, 21831, 18045, 625, 262, 16931, 3290, 13])
'The quick brown fox jumps over the lazy dog.'>>> encoding.decode([464])
'The'
>>> encoding.decode([2068])
' quick'
>>> encoding.decode([13])
'.'
在这个实验中,你可以看到对于 GPT-2 语言模型,Token 464 代表单词 “The”,而 Token 2068 代表单词 “quick”,包括一个前导空格。该模型使用 Token 13 表示句号。
由于 Token 是通过算法确定的,你可能会发现一些奇怪的现象,比如这三个变体的单词 “the”,在 GPT-2 中都编码为不同的 Token:
>>> encoding.encode('The')
[464]
>>> encoding.encode('the')
[1169]
>>> encoding.encode(' the')
[262]
BPE 算法并不总是将整个单词映射到 Token。事实上,使用频率较低的单词不能成为独立的 Token,必须使用多个 Token 进行编码。以下是一个使用两个 Token 编码的单词示例:
>>> encoding.encode("Payment")
[19197, 434]>>> encoding.decode([19197])
'Pay'
>>> encoding.decode([434])
'ment'
下一个 Token 预测
如上所述,给定一些文本,语言模型会预测下一个紧跟其后的 Token。如果用 Python 伪代码展示可能会更清晰,下面是如何运行这些模型以获取下一个 Token 的预测:
predictions = get_token_predictions(['The', ' quick', ' brown', ' fox'])
该函数接收一个由用户提供的提示词编码而来的输入 Token 列表。在这个例子中,我假设每个单词都是一个独立的 Token。为了简化,我使用每个 Token 的文本表示,但正如你之前看到的,实际上每个 Token 会作为一个数字传递给模型。
这个函数的返回值是一个数据结构,它为词汇表中的每个 Token 分配一个紧随输入文本之后的概率。如果基于 GPT-2,这个函数的返回值将是一个包含 50,257 个浮点数的列表,每个浮点数预测相应 Token 将会出现的概率。
在上述例子中,你可以想象,一个训练良好的语言模型会给 Token “jumps” 一个较高的概率来紧跟提示词 “The quick brown fox” 后面。同样假设模型训练得当,你也可以想象,随机单词如 “potato” 继续这个短语的概率会非常低,接近于 0。
为了能够生成合理的预测,语言模型必须经过训练过程。在训练期间,它会被提供大量文本以进行学习。训练结束时,模型能够使用它在训练中见到的所有文本构建的数据结构来计算给定 Token 序列的下一个 Token 概率。
这与你的预期有何不同?我希望这现在看起来不再那么神奇了。
生成长文本序列
由于模型只能预测下一个 Token 是什么,因此生成完整句子的唯一方法是多次循环运行模型。每次循环迭代都会生成一个新的 Token,从返回的概率中选择该 Token。然后将该 Token 添加到下一次循环迭代的输入中,直到生成足够的文本为止。
让我们看一个更完整的 Python 伪代码,展示这种方法的工作原理:
def generate_text(prompt, num_tokens, hyperparameters):tokens = tokenize(prompt)for i in range(num_tokens):predictions = get_token_predictions(tokens)next_token = select_next_token(predictions, hyperparameters)tokens.append(next_token)return ''.join(tokens)
generate_text() 函数将用户提示作为参数。这可能是一个问题。
tokenize() 辅助函数使用 tiktoken 或类似库将提示转换为等效的 Token 列表。在 for 循环中,get_token_predictions() 函数是调用 AI 模型以获取下一个 Token 的概率,如前面的例子所示。
select_next_token() 函数的作用是获取下一个 Token 的概率(或预测)并选择最佳 Token 以继续输入序列。函数可以只选择概率最高的 Token,这在机器学习中称为 “贪心选择(greedy selection)”。更好的是,它可以使用随机数生成器来选择一个符合模型返回概率的 Token,从而为生成的文本添加一些变化。这也会使模型在多次给出相同提示时产生不同的响应。
为了使 Token 选择过程更加灵活,LLM 返回的概率可以使用超参数进行修改,这些超参数作为参数传递给文本生成函数。超参数允许你控制 Token 选择过程的 “贪婪” 程度。
如果你使用过 LLM,你可能熟悉 temperature 超参数。temperature 越高,Token 概率越平坦,这增加了选择不太可能的 Token 的机会,最终使生成的文本看起来更有创造性或更不寻常。你可能还使用了另外两个超参数,称为 top_p 和 top_k,它们控制被考虑选择的最高概率的 Token 数量。
一旦选定了一个 Token,循环就会迭代,模型会接收到一个包含新 Token 在末尾的输入,并生成另一个紧随其后的 Token。num_tokens 参数控制循环运行的迭代次数,换句话说,就是要控制生成多少文本。生成的文本可能(而且经常)在句子中间断开,因为 LLM 没有句子或段落的概念,它只处理一个 Token。为了防止生成的文本在句子中间断开,我们可以将 num_tokens 参数视为最大值而不是确切的 Token 数,在这种情况下,我们可以在生成句号 Token 时停止循环。
如果你已经理解了这些内容,那么恭喜你,你现在已经大致了解了 LLM 是如何工作的。在下一部分,我会更深入一些,但仍然尽量避免涉及支撑这一技术的数学原理,因为它相当复杂。
#02
模型训练
在不使用数学表达式的情况下讨论如何训练模型实际上是很困难的。我将从一个非常简单的训练方法开始展示。
鉴于任务是预测 Token 的后续 Token,一种简单的训练模型的方法是获取训练数据集中所有连续 Token,并用它们构建一个概率表。
让我们用一个简短的词汇表和数据集来做这个。假设模型的词汇表包含以下五个词元:
['I', 'you', 'like', 'apples', 'bananas']
为了使这个例子简短而简单,我不会将空格或标点符号作为 Token。
我们使用一个由三句话组成的训练数据集:
- I like apples
- I like bananas
- you like bananas
我们可以构建一个 5x5 的表格,并在每个单元格中写下表示单元格所在行的 Token 被单元格所在列的 Token 跟随的次数。以下是根据数据集中的三句话构建的表格:
- | I | you | like | apples | bananas |
I | 2 | ||||
you | 1 | ||||
like | 1 | 2 | |||
apples | |||||
bananas |
希望这很清楚。数据集中有两次出现 “I like”,一次出现 “you like”,一次出现 “like apples” 和两次出现 “like bananas”。
现在我们知道每对 Token 在训练数据集中出现的次数,我们可以计算每个 Token 跟随另一个 Token 的概率。为此,我们将每行中的数字转换为概率。例如,表格中间行的 Token “like” 后面跟一次 “apples” 和两次 “bananas”。这意味着 “like” 后面 33。3% 的概率是 “apples”,剩下的 66。7% 的概率是 “bananas”。
以下是计算出的所有概率的完整表格。空单元格的概率为 0%。
- | I | you | like | apples | bananas |
I | 100% | ||||
you | 100% | ||||
like | 33.3% | 66.7% | |||
apples | 25% | 25% | 25% | 25% | |
bananas | 25% | 25% | 25% | 25% |
对于 “I”、“you” 和 “like” 行来说,计算很简单,但 “apples” 和 “bananas” 行却出现了问题,因为它们没有任何数据。由于数据集中没有任何示例显示这些 Token 后面跟随其他 Token,这里我们的训练中存在一个 “漏洞”。
为了确保模型在缺乏训练的情况下仍能生成预测,我决定将 “apples” 和 “bananas” 后续 Token 的概率平均分配到其他四个可能的 Token 上,这显然可能会产生奇怪的结果,但至少模型在遇到这些 Token 时不会卡住。
训练数据中的漏洞问题实际上非常重要。在真正的 LLM 中,训练数据集非常庞大,因此你不会发现像我上面这个小例子中那样明显的训练漏洞。但由于训练数据覆盖率低而导致的小的、更难检测到的漏洞确实存在,并且相当普遍。
在这些训练不足的区域中,LLM 对 Token 的预测质量可能会很差,但通常是难以察觉的。这是 LLM 有时会产生幻觉的原因之一,这种情况发生在生成的文本读起来很流畅但包含事实错误或不一致时。
使用上面的概率表,你现在可以想象 get_token_predictions()函数的实现方式。在 Python 伪代码中它可能是这样的:
def get_token_predictions(input_tokens):last_token = input_tokens[-1]return probabilities_table[last_token]
比想象的更简单,对吧?这个函数接受一个由用户提示词生成的序列。它取序列中的最后一个 Token,并返回该 Token 在概率表中对应的那一行。
例如,如果你用 ['you', 'like'] 作为输入 Token 调用这个函数,那么该函数会返回 “like” 的那一行,“like” 会给予 “apples” 33.3% 的概率来继续句子,而 “bananas” 则是另外的 66.7%。根据这些概率,上面展示的 select_next_token() 函数每三次应该会选择一次 “apples”。
当 “apples” 被选为 “you like” 的延续时,句子 “you like apples” 就会形成。这是一个在训练数据集中不存在,但完全合理的原创句子。希望你开始了解这些模型如何通过重用模式和拼接它们在训练中学到的不同部分来生成看似原创的想法或概念。
上下文窗口
我在上一节中训练小模型的方法称为马尔可夫链。
这种技术的一个问题是,只使用一个 Token(输入的最后一个)来进行预测。任何出现在最后一个 Token 之前的文本在选择如何继续时都没有影响,所以我们可以说这种解决方案的上下文窗口等于一个 Token,这个窗口非常小。由于上下文窗口如此小,模型会不断 “忘记” 思路,从一个词跳到另一个词,缺乏一致性。
可以通过构建一个更大的概率矩阵来改进模型的预测。为了使用两个 Token 的上下文窗口,需要增加额外的表行,这些行代表所有可能的两个 Token 序列。在示例中使用的五个 Token 中,每一对 Token 将在概率表中新增 25 行,加上已经存在的 5 个单 Token 行。模型将不得不再次训练,这次不仅看 Token 对,还要看 Token 组的三元组。在每次 get_token_predictions() 函数的循环迭代中,当可用时,将使用输入的最后两个 Token 来查找较大概率表中的对应行。
但是,2 个 Token 的上下文窗口仍然不够。为了生成一致且至少有基本意义的文本,需要更大的上下文窗口。没有足够大的上下文,新生成的 Token 不可能与之前 Token 中表达的概念或想法相关联。那么我们该怎么办呢?将上下文窗口增加到 3 个 Token 将为概率表增加 125 行,并且质量仍然很差。我们需要将上下文窗口扩大到多大呢?
OpenAI 开源的 GPT-2 模型使用了一个 1024 个 Token 的上下文窗口。为了使用马尔可夫链实现这么大的上下文窗口,每行概率表都必须代表一个长度在 1 到 1024 个 Token 长的序列。使用上面示例中的 5 个 Token 词汇表,有 5 的 1024 次方种可能的序列长度为 1024 Token。需要多少表行来表示这些?我在 Python 会话中做了计算(向右滚动以查看完整数字):
>>> pow(5, 1024)
55626846462680034577255817933310101605480399511558295763833185422180110870347954896357078975312775514101683493275895275128810854038836502721400309634442970528269449838300058261990253686064590901798039126173562593355209381270166265416453973718012279499214790991212515897719252957621869994522193843748736289511290126272884996414561770466127838448395124802899527144151299810833802858809753719892490239782222290074816037776586657834841586939662825734294051183140794537141608771803070715941051121170285190347786926570042246331102750604036185540464179153763503857127117918822547579033069472418242684328083352174724579376695971173152319349449321466491373527284227385153411689217559966957882267024615430273115634918212890625
这行数太多了!而这只是表的一部分,因为我们还需要长度为 1023 的序列,1022 的序列,等等,一直到 1,因为我们想确保在输入中没有足够 Token 时也能处理较短的序列。马尔可夫链是有趣的,但它们确实存在一个很大的可扩展性问题。
而且一个 1024 Token 的上下文窗口已经不再那么大了。随着 GPT-3,上下文窗口增加到 2048 个 Token,然后在 GPT-3.5 中增加到 4096。GPT-4 开始时为 8192 个 Token,后来增加到 32K,然后又增加到 128K(没错,128,000 个 Tokens!)。现在开始出现上下文窗口为 1M 或更大的模型,这允许在做 Token 预测时有更好的一致性和回忆能力。
总之,马尔可夫链使我们以正确的方式思考文本生成问题,但它们有很大的问题,阻止我们考虑其作为可行的解决方案。
从马尔可夫链到神经网络
显然,我们不能再考虑使用概率表的方案,因为合理上下文窗口的概率表会需要庞大的 RAM。我们可以做的是用一个函数来替代概率表,该函数返回 Token 概率的近似值,这些概率是通过算法生成的,而不是存储在一个庞大的表格中。事实上,这正是神经网络擅长的事情。
神经网络是一种特殊的函数,它接受一些输入,对这些输入进行计算,然后返回一个输出。对于语言模型来说,输入是表示提示词的 Token,输出是下一个 Token 的预测概率列表。
神经网络之所以被称为 “特殊” 的函数,是因为它们除了函数逻辑外,还受一组外部定义的参数控制。最初,网络的参数是未知的,因此函数产生的输出完全没有用。神经网络的训练过程在于找到能使函数在训练数据集上表现最佳的参数,假设如果函数在训练数据上表现良好,那么在其他数据上也会表现良好。
在训练过程中,参数会使用一种称为反向传播的算法进行小幅度的迭代调整,这个算法涉及大量数学运算,所以本文不会详细讨论。每次调整后,神经网络的预测结果会略有改善。参数更新后,网络会再次根据训练数据集进行评估,评估结果用于指导下一轮调整。这个过程会持续进行,直到函数在训练数据集上表现出良好的下一个 Token 预测为止。
为了让你了解神经网络工作的规模,可以考虑 GPT-2 模型有大约 15 亿个参数,而 GPT-3 将参数数量增加到 1750 亿。据说 GPT-4 有大约 1.76 万亿个参数。以现有硬件条件训练这种规模的神经网络需要很长时间,通常是数周或数月。
有意思的是,由于参数众多,都是在没有人为干预的情况下通过漫长的迭代过程计算出来的,因此很难理解模型的工作原理。一个训练有素的 LLM 就像一个黑匣子,非常难以调试,因为模型的大部分 “思考” 都隐藏在参数中。即使是训练该模型的人也难以解释其内部工作原理。
层、Transformer 和注意力机制
你可能会好奇,在神经网络函数内部发生了哪些神秘的计算,在参数调优的帮助下,可以将一列输入 Token 转换为合理的下一个 Token 的概率。
一个神经网络被配置为执行一系列操作,每个操作称为一个 “层”。第一层接收输入,并进行某种转换。转换后的输入进入下一层,再次被转换。如此反复,直到数据到达最后一层,并进行最后一次转换,生成输出或预测结果。
机器学习专家设计出不同类型的层,对输入数据进行数学转换,并找出如何组织和组合层以达到预期的结果。有些层是通用的,而有些层则专为处理特定类型的输入数据而设计,如图像或在 LLM 中的 Token 化文本。
当前在 LLM 中用于文本生成最流行的神经网络架构称为 Transformer。使用这种设计的 LLM 被称为 GPT,即生成式预训练 Transformer。
Transformer 模型的显著特点是其执行的一种称为注意力机制的层计算,这使得它们能够在上下文窗口中的 Token 之间推导出关系和模式,并将这些关系和模式反映在下一个 Token 的概率中。
注意力机制最初用于语言翻译器,作为一种找到输入序列中最重要的 Token 以提取其含义的方法。这种机制使得现代翻译器能够在基本层面上 “理解” 一个句子,通过关注(或将 “注意力” 引向)重要的词或 Token。
#03
LLM 是否具有智能?
到现在,你可能已经开始对 LLM 在生成文本的方式上是否表现出某种形式的智能形成一种看法。
我个人并不认为 LLM 具备推理能力或提出原创思想的能力,但这并不意味着它们毫无用处。由于它们在上下文窗口中的 Token 上进行的巧妙计算,LLM 能够发现用户提示中存在的模式,并将这些模式与训练期间学到的类似模式相匹配。它们生成的文本主要由训练数据的片段组成,但它们将词(实际上是 Token)拼接在一起的方式非常复杂,在许多情况下,产生的结果感觉是原创且有用的。
鉴于 LLM 容易产生幻觉现象,我不会信任任何由 LLM 生成,未经人工验证就直接传递给终端用户的工作流。
未来几个月或几年内出现的更大规模的 LLM 会实现类似于真正智能的东西吗?我觉得这在 GPT 架构下不会发生,因为它有很多限制,但谁知道呢,也许通过未来的一些创新,我们会实现这一目标。