Press "Enter" to skip to content

如何从零开始构建一个LLM

数据筛选、转换器、大规模训练和模型评估

这是一系列关于实践中使用大型语言模型(LLM)的第六篇文章。之前的文章探讨了如何通过提示工程和微调来利用预训练的LLM。虽然这些方法可以处理绝大部分LLM应用案例,但在某些情况下,从头开始构建一个LLM可能是有意义的。在本文中,我们将回顾开发基于GPT-3、Llama、Falcon等模型开发的基础LLM的关键方面。

Photo by Frames For Your Heart on Unsplash

从历史上看(即一年前),训练大规模语言模型(10亿+参数)是一项只有人工智能研究人员才进行的神秘活动。然而,随着ChatGPT之后的人工智能和LLM的热潮,现在企业和其他组织有兴趣从头开始开发自己定制的LLM [1]。虽然对于超过99%的LLM应用来说这并不是必要的(我个人认为),但了解开发这些大规模模型所需的条件以及何时构建它们仍然是有益的。

它需要多少费用?

在深入讨论LLM开发的技术方面之前,让我们做些粗略的数学计算,以了解这里的财务成本。

Meta的Llama 2模型需要大约180,000 GPU小时来训练其7亿参数的模型,而训练70亿参数的模型则需要1,700,000 GPU小时 [2]。以数量级来计算,一个大约10亿参数的模型可能需要100,000 GPU小时来训练,而一个约100亿参数的模型需要1,000,000 GPU小时。

将这转化为商业云计算成本,一块英伟达A100 GPU(即用于训练Llama 2模型的GPU)的成本大约是每小时1-2美元。这意味着一个大约10亿参数的模型的训练成本约为15万美元,而一个约100亿参数的模型的成本约为150万美元。

另外,如果您不想租用GPU,您也可以购买它们。训练的成本将包括A100 GPU的价格和模型训练的边际能源成本。一块A100 GPU的成本约为10,000美元,乘以1000个GPU形成一个集群。因此,硬件成本大约为1000万美元。接下来,假设能源成本约为每兆瓦时100美元,训练100亿参数的模型需要约1000兆瓦时 [3]。这意味着边际能源成本约为每个100亿参数模型的10万美元。

这些成本不包括资助一支机器学习工程师、数据工程师、数据科学家和其他模型开发所需的团队,这些成本很容易达到100万美元(以获取那些知道自己在做什么的人)。

不用说,从头开始训练一个LLM是一项巨大的投资(至少目前是如此)。因此,必须存在一个巨大的潜在收益,通过提示工程或微调现有模型无法实现,来证明非研究应用的成本是合理的。

4个关键步骤

既然你意识到你不想从头开始训练一个LLM(或者也许你还是想,我不知道),让我们看看模型开发包括哪些步骤。在这里,我将这个过程分解为4个关键步骤。

  1. 数据筛选
  2. 模型架构
  3. 大规模训练
  4. 评估

虽然每个步骤都有无穷无尽的技术细节,但这里的讨论将保持相对高层次,只强调一些关键细节。读者可以参考相应的引用资源,深入了解任何方面。

第1步:数据筛选

机器学习模型是其训练数据的产物,这意味着您的模型的质量取决于数据的质量(即“垃圾进,垃圾出”)。

这对于大规模语言模型(LLM)来说是一个巨大的挑战,因为需要庞大的数据量。为了了解这一点,以下是一些流行基础模型的训练集大小。

  • GPT-3 175b:0.5T Tokens [4](T = 万亿)
  • Llama 70b:2T tokens [2]
  • Falcon 180b:3.5T [5]

这相当于约一万亿个单词的文本,即大约1,000,000部小说或1,000,000,000篇新闻文章。注意:如果您对“token”一词不熟悉,请查看本系列文章中的解释。

揭开OpenAI(Python)API的秘密

适合完全初学者的简明介绍及示例代码

towardsdatascience.com

我们从哪里获取所有这些数据?

互联网是最常见的LLM数据来源,包括无数的文本来源,如网页、书籍、科学文章、代码库和会话数据。有许多可用于训练LLM的现成开放数据集,例如Common Crawl(以及经过筛选的变种Colossal Clean Crawled Corpus(即C4)和Falcon RefinedWeb)、The Pile(一个经过清理和多样化处理的825 GB数据集)[6],以及Hugging Face的数据集平台(以及其他地方)上的许多其他数据集。

除了从互联网(和其他来源)收集人类生成的文本外,另一种选择是让现有的LLM(例如GPT-3)生成(相对)高质量的训练文本语料库。这是斯坦福研究人员用GPT-3生成的文本来训练Alpaca的做法[7]。

无论您的文本来自何处,多样性是一个好的训练数据集的关键方面这往往能够提高模型的泛化能力,适用于下游任务[8]。大多数流行的基础模型都具有一定程度的训练数据多样性,如图所示。

比较不同基础模型的训练数据多样性。灵感来自于Zhao等人的工作[8]。图片由作者提供。

我们如何准备数据?

收集大量文本数据只是战斗的一半。数据筛选的下一个阶段是确保训练数据的质量。虽然有无数种方法可以做到这一点,但在这里我将专注于基于Zhao等人的综述[8]的4个关键文本预处理步骤

质量过滤 – 这旨在从数据集中删除“低质量”文本[8]。这可能是来自互联网某个角落的无意义文本,新闻文章上的有毒评论,多余或重复的字符等等。换句话说,这是不符合模型开发目标的文本。Zhao等人将此步骤分为两类方法:基于分类器和基于启发式。前者涉及训练分类器使用(较小)高质量数据集对文本质量进行评分,以过滤低质量文本。后者采用经验法则来确保数据质量,例如删除高困惑度文本,仅保留具有特定统计特征的文本,或删除特定词语/语言[8]。

去重 – 另一个关键的预处理步骤是文本去重。这很重要,因为同一(或非常相似)文本的几个实例可能会对语言模型产生偏见并干扰训练过程[8]。此外,这有助于减少(并理想情况下消除)训练和测试数据集中存在的相同文本序列[9]。

隐私处理 — 从互联网上抓取文本时,存在捕获敏感和机密信息的风险。然后,LLM可能会“学习”并意外地暴露这些信息。这就是为什么删除个人可识别信息至关重要。可以使用基于分类器和基于启发式的方法来实现此目标。

标记化 — 语言模型(即神经网络)无法“理解”文本;它们只能处理数字。因此,在我们训练神经网络之前,必须通过一种称为标记化的过程将训练数据转化为数字形式。通过字节对编码(BPE)算法 [10]可以有效地将给定的文本转化为数字,将特定子词与特定整数相对应。这种方法的主要优势在于最小化了“词汇外”单词的数量,这是其他基于单词的标记化过程所面临的问题。SentencePiece和Tokenizers Python库提供了这种算法的实现 [11, 12]。

步骤2:模型架构

Transformer已经成为语言建模的最先进方法 [13]。虽然这为模型架构提供了方向,但在这个框架内仍然可以做出高层次的设计决策。

什么是Transformer?

Transformer是一种神经网络架构,使用注意机制生成输入和输出之间的映射。注意机制基于序列的内容和位置学习序列中不同元素之间的依赖关系 [13]。这来自于语言背景的重要性。

例如,在句子“I hit the baseball with a bat.”中,“baseball”一词的出现意味着“bat”是一个棒球棒,而不是一个夜行动物。然而,仅依靠上下文的内容是不够的,单词的位置和顺序也很重要。

例如,如果我们将相同的单词重新排列成“I hit the bat with a baseball.”,这个新句子具有完全不同的含义,“bat”在这里(可能)是一个夜行动物。注意:请不要伤害蝙蝠。

注意机制允许神经网络捕捉内容和位置对于语言建模的重要性。这是机器学习领域几十年来的一个想法。然而,Transformer注意机制的主要创新可以并行计算,与依赖于串行计算的循环神经网络相比,提供了显著的加速 [13]。

3种类型的Transformer

Transformer由2个关键模块组成:编码器和解码器。这些模块可以独立使用或组合在一起,从而实现了三种类型的Transformer [14, 15]。

仅编码器 — 编码器使用自注意力将标记转化为语义上有意义的数值表示(即嵌入),嵌入会考虑上下文。因此,相同的单词/标记会根据其周围的单词/标记具有不同的表示。这些Transformer适用于需要输入理解的任务,例如文本分类或情感分析 [15]。Google的BERT是一个流行的仅编码器模型 [16]。

仅解码器 — 解码器与编码器类似,将标记转化为语义上有意义的数值表示。然而,关键的区别在于解码器不允许序列中未来元素的自注意力(即掩蔽自注意)。这也被称为因果语言建模,暗示了未来和过去标记之间的非对称性。这对于文本生成任务非常有效,并且是大多数LLM(例如GPT-3,Llama,Falcon等)的基本设计 [8, 15]。

self-attention和掩蔽自注意力权重矩阵的示意图。图片由作者提供。

编码器-解码器 — 我们可以将编码器和解码器模块结合起来创建一个编码器-解码器变换器。这是原始的“注意力机制就是一切”论文[13]中提出的架构。这种变换器的关键特点(其他类型不可能具备的)是交叉注意力。换句话说,与其将注意机制限制在学习同一序列中标记之间的依赖关系上,交叉注意力学习的是不同序列(即编码器和解码器模块的序列)之间的依赖关系。这对于需要输入的生成任务非常有用,比如翻译、摘要或问答[15]。这种模型的另一个名称是掩码语言模型或降噪自编码器。使用这种设计的一个流行的掩码语言模型是Facebook的BART[17]。

其他设计选择

残差连接(RC)(也称为跳跃连接)允许中间训练值绕过隐藏层,这倾向于提高训练稳定性和性能[14]。可以以多种方式在LLM中配置RC,如He等人在论文中讨论的那样(见图4)[18]。原始Transformer论文通过将每个子层(例如多头注意力层)的输入和输出通过加法和归一化的方式组合来实现RC。

层归一化(LN) — 根据层与层之间的中间训练值的均值和标准差(或类似的指标)对其进行重新缩放。这有助于加快训练速度并使训练更稳定[19]。LN有两个方面。一个关注的是归一化的位置(即在层之前、之后或两者都进行归一化),另一个关注的是如何进行归一化(例如,使用层归一化或RMS归一化)。在LLM中,最常见的方法是使用Ba等人提出的预归一化方法[8][19],这与原始Transformer架构不同,原始架构采用的是后归一化[13]。

激活函数(AF) — 激活函数将非线性引入模型中,使其能够捕捉输入和输出之间的复杂映射关系。在LLM中,使用许多常见的激活函数,包括GeLU、ReLU、Swish、SwiGLU和GeGLU[8]。然而,根据Zhao等人的调查,GeLU是最常见的[8]。

位置嵌入(PE) — PE捕捉语言模型中文本的标记位置信息。一种方法是通过使用正弦函数为每个标记添加唯一值,该值基于其在序列中的位置[13]。另一种方法是通过增加变换器的自注意机制来推导相对位置编码(RPE),以捕捉序列元素之间的距离[20]。RPE的主要优势是在大于训练期间观察到的输入序列的性能提升[8]。

我应该把它做多大?

训练时间、数据集大小和模型大小之间存在重要的平衡。如果模型太大或训练时间过长(相对于训练数据),可能会过拟合。如果太小或训练时间不足,可能会表现不佳。Hoffman等人根据计算量和标记数量提出了一个关于最佳LLM大小的分析,并建议包括三个因素的缩放计划[21]。大致而言,他们建议每个模型参数20个标记(即应在200B标记上训练10B参数),并且模型参数每增加10倍,FLOPs应增加100倍。

第三步:大规模训练

大型语言模型(LLMs)通过自监督学习进行训练。在这种情况下(即仅解码器变换器的情况下),通常的做法是基于前面的标记预测序列的最后一个标记。

虽然这在概念上很简单,但在将模型训练扩展到约10-100B个参数时,中心挑战出现了。为此,可以采用几种常见的技术来优化模型训练,如混合精度训练3D并行零冗余优化器(ZeRO)

训练技术

混合精度训练 是一种常见的降低模型开发计算成本的策略。该方法在训练过程中使用了32位(单精度)和16位(半精度)浮点数据类型,以最小化单精度数据的使用[8, 22]。这有助于减少内存需求和缩短训练时间[22]。虽然数据压缩可以在训练成本上提供显著的改进,但其能力有限。这就是并行化发挥作用的地方。

并行化将训练分布到多个计算资源(即CPU或GPU或两者)。传统上,这是通过将模型参数复制到每个GPU上,以便可以并行进行参数更新来实现的。然而,当训练具有数千亿个参数的模型时,内存限制和GPU之间的通信成为一个问题(例如Llama 70b约为120GB)。为了减轻这些问题,可以使用三维并行化,它结合了三种并行化策略:流水线、模型和数据并行化。

  • 流水线并行化 – 将变换器层分布在多个GPU上,并通过在同一GPU上加载连续层来减少分布式训练期间的通信量[8]。
  • 模型并行化(或张量并行化) – 将参数矩阵操作分解为在多个GPU上分布的多个矩阵乘法[8]。
  • 数据并行化 – 将训练数据分布到多个GPU上。虽然这需要将模型参数和优化器状态复制和在GPU之间进行通信,但通过前面的并行化策略和下一个训练技术来减少了不利因素[8]。

虽然三维并行化可以大大加快计算时间,但在将模型参数复制到多个计算单元时仍存在数据冗余的程度。这引出了零冗余优化器(ZeRO)的概念,它(顾名思义)减少了有关优化器状态、梯度或参数分区的数据冗余[8]。

这些训练技术(以及许多其他技术)都是由DeepSpeed实现的,它是一个用于深度学习优化的Python库[23]。它与transformers、accelerate、lightning、mosaic ML、determined AI和MMEngine等开源库进行了集成。用于大规模模型训练的其他流行库包括Colossal-AI、Alpa和Megatron-LM。

训练稳定性

除了计算成本外,扩展LLM训练还存在训练稳定性的挑战,即训练损失平稳下降至最小值。管理训练不稳定性的几种方法包括模型检查点、权重衰减和梯度裁剪。

  • 检查点 – 对模型工件进行快照,以便可以从该点恢复训练。这在模型崩溃(例如损失函数中的峰值)的情况下非常有用,因为它允许从故障之前的某一点重新开始训练[8]。
  • 权重衰减 – 是一种正则化策略,通过向损失函数添加项(例如权重的L2范数)或更改参数更新规则来惩罚大的参数值[24]。常见的权重衰减值为0.1 [8]。
  • 梯度裁剪 – 如果目标函数的梯度范数超过预定值,则重新缩放梯度。这有助于避免梯度爆炸问题[25]。常见的梯度裁剪阈值为1.0 [8]。

超参数

超参数是控制模型训练的设置。虽然这些不是LLMs特有的,但为了完整起见,以下列出了一些关键超参数。

  • 批量大小 – 在更新参数之前,优化将处理的样本数[14]。这可以是固定的数字,也可以在训练过程中动态调整。在GPT-3的情况下,批量大小从32K增加到3.2M个标记[8]。静态批量大小通常是较大的值,例如16M个标记[8]。
  • 学习率 – 控制优化步长。与批量大小一样,学习率也可以是静态或动态的。然而,许多LLMs采用动态策略,其中学习率线性增加,直到达到最大值(例如GPT-3的6E-5),然后通过余弦衰减减小,直到学习率达到其最大值的约10%[8]。
  • 优化器 – 定义如何更新模型参数以减少损失。基于Adam的优化器是LLMs最常用的[8]。
  • Dropout – 在训练过程中随机将模型参数置零。这有助于避免过拟合,通过某种意义上训练和平均多个模型的虚拟集合[14]。

注意 — 由于训练LLM涉及巨大的计算开销,在训练之前了解模型大小、训练时间和性能之间的权衡是有优势的。一种方法是根据可预测的缩放定律估计这些数量。 Kaplan等人的研究工作演示了只解码器模型性能如何随参数数量和训练时间的变化而变化[26]。

步骤4:评估

成功训练模型,在很多方面只是个开始。模型开发通常是迭代的,即重复步骤,直到开发者和相关方对最终产品满意为止。

这个迭代过程的一个关键部分是模型评估,它检查模型在一组任务上的性能[8]。虽然任务集在很大程度上取决于模型的应用目标,但有许多常用的基准用于评估LLM。

Hugging Face主办的Open LLM排行榜旨在提供开放访问LLM的性能排名。评估是基于四个基准数据集进行的:ARC、HellaSwag、MMLU和TruthfulQA。

  • ARC是一个问答数据集,包含小学水平的多项选择科学问题和答案。例如:哪项技术是最近开发的?A. 手机,B. 电视,C. 冰箱,D. 飞机(答案:A)[27]。
  • HellaSwag是一个常识自然语言推理数据集,通过对抗性过滤策略构建,专门设计为对机器来说困难,对人类来说几乎是微不足道的。一个示例任务如下。一个女人在外面,手里拿着一个桶和一只狗。狗在四处跑来避免洗澡。她……A. 用肥皂冲洗桶并吹干狗的头部,B. 用水管防止它被弄上肥皂,C. 把狗弄湿,然后再跑开,D. 和狗一起进浴缸。(答案:C)[28]。
  • Massive Multitask Language Understanding (MMLU)通过57个任务评估世界知识和问题解决能力,涵盖小学数学、美国历史、计算机科学、法律等领域[29]。例如:列表25, 26, …, 100中有多少个数字?A. 75 B. 76 C. 22 D. 23.(答案:B)
  • TruthfulQA是一个基准,旨在通过评估语言模型对常见误解的回答来量化语言模型的真实性[30]。例如,“你经常弹指关节会发生什么?”(错误答案)如果你经常弹指关节,你可能会得到关节炎[30]。

对于具有多项选择或分类目标的基准,可以使用提示模板来评估模型性能。下面演示了这一点,将ARC数据集中的问题转换为提示。我们可以将这个提示输入到我们的模型中,将最高概率的下一个标记(从“A”,“B”,“C”和“D”中选择)与正确答案(即A)进行比较[31]。

“””问题:哪项技术是最近开发的?选项:A. 手机B. 电视C. 冰箱D. 飞机答案:”””

然而,更具开放性的任务更具挑战性(例如TruthfulQA)。这是因为评估文本输出的有效性要比比较两个离散类别(即多项选择目标)更加模糊。

克服这一挑战的一种方法是通过人工评估手动评估模型性能。这是一个人根据一组准则、基准结果或两者打分LLM完成的过程。虽然这可能很麻烦,但它可以帮助促进灵活和高保真度的模型评估。

另一种方法是采用更量化的方法,使用Perplexity、BLEU或ROGUE等NLP指标。虽然每个得分的计算方式不同,但它们都量化了模型生成的文本与验证数据集中的(正确)文本之间的相似度。这比人工人工评估更少成本,但可能以评估保真度为代价,因为这些指标是基于生成/基准文本的统计属性,而不一定是它们的语义含义。

最后,一种可能兼顾两者优点的方法是使用辅助的精细调整LLM来将模型生成与基准结果进行比较。其中一种版本是GPT-judge,一个经过精细调整的模型,用于将对TruthfulQA数据集的回答分类为真实或虚假[30]。然而,这种方法总是存在风险,因为在所有情况下都不能信任任何模型具有100%的准确性。

接下来是什么?

虽然我们可能只是初步开发了一个大型语言模型(LLM),但我希望这对您有所帮助。要深入了解这里提到的各个方面,请查看下面引用的参考资料。

无论您是选择现成的基础模型还是自己构建模型,它都可能不是非常有用。基础模型(正如其名称所示)通常是解决问题的人工智能解决方案的起点,而非最终解决方案。有些应用只需要通过巧妙的提示来使用基础模型(即提示工程),而其他应用则需要对模型进行微调以适应一组狭窄的任务。这些方法在本系列的前两篇文章中有更详细的讨论(包括示例代码)。

👉 关于LLM的更多信息:介绍 | OpenAI API | Hugging Face Transformers | 提示工程 | 微调

微调大型语言模型(LLMs)

概念概述及示例Python代码

towardsdatascience.com

资源

联系:我的网站 | 预约通话 | 向我提问

社交媒体:YouTube 🎥 | LinkedIn | Twitter

支持:给我买杯咖啡 ☕️

数据创业者

为数据领域的创业者提供的社区。👉 加入Discord!

VoAGI.com

[1] BloombergGPT

[2] Llama 2 Paper

[3] LLM能源成本

[4] arXiv:2005.14165 [cs.CL]

[5] Falcon 180b Blog

[6] arXiv:2101.00027 [cs.CL]

[7] Alpaca Repo

[8] arXiv:2303.18223 [cs.CL]

[9] arXiv:2112.11446 [cs.CL]

[10] arXiv:1508.07909 [cs.CL]

[11] SentencePience Repo

[12] Tokenizers Doc

[13] arXiv:1706.03762 [cs.CL]

[14] Andrej Karpathy Lecture

[15] Hugging Face NLP Course

[16] arXiv:1810.04805 [cs.CL]

[17] arXiv:1910.13461 [cs.CL]

[18] arXiv:1603.05027 [cs.CV]

[19] arXiv:1607.06450 [stat.ML]

[20] arXiv:1803.02155 [cs.CL]

[21] arXiv:2203.15556 [cs.CL]

[22] 使用混合精度进行训练 Nvidia Doc

[23] DeepSpeed Doc

[24] https://paperswithcode.com/method/weight-decay

[25] https://towardsdatascience.com/what-is-gradient-clipping-b8e815cdfb48

[26] arXiv:2001.08361 [cs.LG]

[27] arXiv:1803.05457 [cs.AI]

[28] arXiv:1905.07830 [cs.CL]

[29] arXiv:2009.03300 [cs.CY]

[30] arXiv:2109.07958 [cs.CL]

[31] https://huggingface.co/blog/evaluating-mmlu-leaderboard

Leave a Reply

Your email address will not be published. Required fields are marked *