文章

llama1 技术报告

llama1 技术报告

1. LLaMa 简介

论文:LLaMA: Open and Efficient Foundation Language Models

github:https://github.com/facebookresearch/llama

LLaMA 是一系列从 7 B到 65B 参数的基础语言模型。Meta 训练这些模型使用了数万亿个 token,并且证明了完全可以只使用公开可得的数据集来训练最先进的模型,而无需使用专有和不可获取的数据集。特别是,LLaMA-13B 在大多数基准测试中表现优于GPT-3(175B),而 LLaMA-65B 在竞争中与最佳模型 Chinchilla70B 和PaLM-540B 持平。 大规模语言模型(Large Language Models,LLMs)在大量文本语料库上训练后,已经显示出它们能够从文本指令或少量示例中执行新的任务。这些少样本特性首次出现在将模型扩展到足够大的规模时,从而形成了一系列关注进一步扩展这些模型的工作。这些努力是基于更多参数将导致更好性能的假设。然而,Hoffmann等人的最新工作显示,在给定的计算预算下,最佳性能并不是由最大的模型实现的,而是由更多数据训练的较小模型实现的。Hoffmann等人的缩放定律的目标是确定在特定的训练计算预算下,如何最佳地缩放数据集和模型大小。然而,这个目标忽视了推理预算,在大规模提供语言模型时变得至关重要。在这种情况下,考虑到目标性能水平,首选模型不是训练速度最快的,而是推理速度最快的。虽然训练一个大型模型达到一定性能水平可能更便宜,但训练时间更长的较小模型在推理阶段最终会更经济。例如,虽然Hoffmann等人建议在 200B 标记上训练 10B 模型,但 Meta 发现 7B 模型的性能在 1T token 后仍在持续提高。 重点是训练一系列语言模型,以在各种推理预算下实现最佳性能,通过使用更多 token 进行训练,而不是通常使用的数量。由此得到的模型称为 LLaMA,参数范围从 7B 到 65B,与最好的现有 LLMs 相比具有竞争力的性能。例如,LLaMA-13B 在大多数基准测试中优于 GPT-3,尽管大小只有后者的10倍较小。在更高端的规模上,LLaMA 的 65B 参数模型也与最佳的大规模语言模型(如Chinchilla或PaLM-540B)相竞争。 与 Chinchilla、PaLM 或 GPT-3 不同,LLaMa 仅使用公开可得的数据,而大多数现有模型则依赖于不公开可得或未经记录的数据(例如“Books – 2TB”或“Social media conversations”)。有一些例外,特别是 OPT、GPT-NeoX、BLOOM 和 GLM,但没有一个能与 PaLM-62B 或 Chinchilla 相竞争。

2. 具体方法

LLaMa 预训练数据

LLaMa 预训练数据大约包含 1.4T tokens,对于绝大部分的训练数据,在训练期间模型只见到过1次,Wikipedia 和 Books 这两个数据集见过2次。 表1所示是 LLaMa 预训练数据的含量和分布,其中包含了 CommonCrawl 和 Books 等不同域的数据。 暂时无法在飞书文档外展示此内容

English CommonCrawl [67%]:对五个 CommonCrawl 数据集进行预处理,时间跨度从2017年到2020年,使用 CCNet 流水线。该过程在行级别进行数据去重,使用 fastText 线性分类器进行语言识别,以删除非英语页面,并使用 n-gram 语言模型过滤低质量内容。此外,还训练了一个线性模型,用于将页面分类为 Wikipedia 中的引用页面与随机抽样页面,并丢弃未被分类为引用的页面。 C4 [15%]。C4的预处理还包括去重和语言识别步骤:与 CCNet 的主要区别在于质量过滤,这主要依赖于标点符号的存在或网页中的词语和句子数量等启发式方法。 Github [4.5%]。使用 Google BigQuery 上可用的公共 GitHub 数据集。只保留了在 Apache、BSD 和 MIT 许可下发布的项目。此外,使用基于行长度或字母数字字符比例的启发式方法过滤低质量文件,并使用正则表达式删除了诸如头文件之类的样板文件。最后,对生成的数据集进行了文件级别的去重,使用完全匹配的方法 Wikipedia [4.5%]。添加了截至2022年6月至8月的 Wikipedia 数据,涵盖20种语言。处理数据以去除超链接、评论和其他格式样板。 Gutenberg and Books3 [4.5%]。添加了两个书的数据集,分别是 Gutenberg 以及 ThePile (训练 LLM 的常用公开数据集) 中的 Book3 部分。处理数据时执行重复数据删除,删除内容重叠超过 90% 的书籍。 ArXiv [2.5%]。处理了arXiv Latex文件,以添加科学数据到数据集中。移除了第一节之前的所有内容,以及参考文献。还移除了.tex文件中的注释,并且内联展开了用户编写的定义和宏,以增加论文之间的一致性。 Stack Exchange [2%]。作者添加了 Stack Exchange,这是一个涵盖各种领域的高质量问题和答案网站,范围从计算机科学到化学。作者从 28 个最大的网站保留数据,从文本中删除 HTML 标签并按分数对答案进行排序 Tokenizer。使用字节对编码(BPE)算法对数据进行分词,使用 SentencePiece 的实现。值得注意的是,作者将所有数字分割成单个数字。

LLaMa 模型架构 在最近关于大型语言模型的研究中,LLaMa 的网络基于 Transformer 架构。作者利用了随后提出的各种改进,这些改进在不同模型(如PaLM)中得到了应用。以下是与原始架构的主要区别,以及从哪里得到了这种变化的灵感(括号中)。 Pre-normalization [受 GPT3 的启发] 为了提高训练稳定性,LLaMa 对每个 Transformer 子层的输入进行归一化,而不是对输出进行归一化。LLaMa 使用了 RMSNorm 归一化函数。 Pre-normalization、RMSNorm: 大模型系列–(1)模型架构 SwiGLU 激活函数 [受 PaLM 的启发]: LLaMa 使用 SwiGLU 激活函数替换 ReLU 以提高性能,维度从\(4d\)变为\(\frac{2}{3}4d\)。 SwiGLU 是2019年提出的新的激活函数,它结合了 SWISH 和 GLU 两种者的特点。SwiGLU 主要是为了提升Transformer 中的 FFN(feed-forward network) 层的实现。 \(SwiGLU(x,W,V,b,c,β)=Swish_β(xW+b)⊗(xV+c)\) GLU GLU(Gated Linear Units,门控线性单元)引入了两个不同的线性层,其中一个首先经过sigmoid函数,其结果将和另一个线性层的输出进行逐元素相乘作为最终的输出: \(GLU(x,W,V,b,c)=σ(xW+b)⊗(xV+c) \tag 1\) 这里W , V 以及b , c分别是这两个线性层的参数;\(\sigma(xW+b)\)作为门控,控制\(xV+c\)的输出。 这里使用\(\sigma\)作为激活函数,修改改激活函数得到的变体通常能带来更好的性能表现,比如SwiGLU修改激活函数为Swish。我们来看下Swish激活函数。 Swish Swish激活函数的形式为: \(\text{Swish}_\beta(x) = x \sigma(\beta x) \tag 2\) 其中\(\sigma(x)\)是Sigmoid函数;\(\beta\)是一个可学习的参数。 Rotary Embeddings [受 GPTNeo 的启发]: LLaMa 没有使用之前的绝对位置编码,而是使用了旋转位置编码(RoPE),可以提升模型的外推性。关于 RoPE 的具体细节,可以参考下面的链接: https://zhuanlan.zhihu.com/p/647109286 LLaMa 优化器 LLaMa 使用了 AdamW 优化器进行训练,超参数为:\(β1 = 0.9\),\(β2 = 0.95\)。 使用 cosine 学习率衰减策略,2000 步的 warm-up,最终学习率等于最大学习率的 10%,使用 0.1 的权重衰减和 1.0 的梯度裁剪。

  1. 余弦学习率调度策略(Cosine Annealing):这种策略会模拟余弦函数的衰减趋势来调整学习率,使学习率在训练过程中先减小后增加,形成一个周期性的波动。它有助于模型在训练过程中跳出局部最小值,有可能找到更好的全局最小值。根据搜索结果,余弦退火学习率调度策略的数学表达式如下: \(η_t=η_{min}+\frac{1}{2}(η_{max}−η_{min})(1+cos⁡(\frac{T_{cur}}{T_{max}}π))\) 其中,\(η_{max}\)是初始学习率,\(η_{min}\) 是学习率下限,\(T_{max}\) 是最大周期数,\(T_{cur}\) 是当前周期数 。
  2. Warm-up策略:在训练初期,模型权重的更新可能会非常剧烈,导致训练不稳定。Warm-up策略通过在训练初期使用较小的学习率,逐步“预热”模型,使模型权重更新更加平稳。随着训练的进行,学习率会逐渐增加到预定的正常水平。这种策略有助于模型在训练初期稳定下来,避免因学习率过大而导致的发散。根据搜索结果,Warm-up策略通常在训练的前几个epoch内实施,例如设置Warm-up的epoch数量为10,然后逐渐将学习率提升至正常水平 。 暂时无法在飞书文档外展示此内容 [图片] Training loss over train tokens for the 7B,13B, 33B, and 65 models LLaMa 的高效实现 研究团队做了一些优化来提高模型的训练速度:
  3. 因果多头注意的有效实现:使用因果多头注意的有效实现来减少内存使用和运行时间。该实现可在xformers库中获得,其灵感来自于固定激活值显存优化和FlashAttention。这是通过不存储注意力权重和不计算由于语言建模任务的因果性质而被掩盖的key/query分数来实现的。
  4. 激活重计算:为了进一步提高训练效率,通过检查点减少了在向后传递过程中重新计算的激活量。更准确地说,节省了计算成本高的激活,比如线性层的输出。这是通过手动实现transformer层的backward函数来实现的,而不是依赖于PyTorch的autograd。
  5. 模型并行和序列并行:为了从这种优化中充分受益,需要通过使用模型和序列并行来减少模型的内存使用。此外,还尽可能地重叠激活的计算和gpu之间通过网络的通信。 在训练一个包含 65B 参数的模型时,LLaMa 的代码在具有 80GB 内存的 2048 个 A100 GPU 上每秒处理约 380个 token。这意味着在包含 1.4万亿 token 的数据集上进行训练大约需要21天。 总结 总结一下 LLaMa 的技术要点:
    • 模型结构:主体结构依然是 GPT,不同之处在于位置编码使用了旋转编码(RoPE),归一化使用了 RMSNorm,激活函数使用了 SwiGLU 。
    • 训练优化:选择了小 LLM配大数据的思路,预训练使用了 1.4T 的 token,经过了充分的训练。 整体上看似乎并没有特别大的亮点,但是简单实用,这也是 Meta 这些大厂的一贯风格。
本文由作者按照 CC BY 4.0 进行授权