前言
近期,ChatGPT成为了全网热议的话题。这款基于大规模语言模型技术(LLM,Large Language Model)的人机对话工具,已引起了广泛关注。当前主流的大规模语言模型普遍采用Transformer架构,并通过大量数据进行自监督训练。然而,如何构建自监督训练数据?在基础的Transformer结构上,各家又做出了哪些创新呢?为了确保训练过程高效而稳定,又有哪些“黑科技”在助力呢?今天,我们将介绍一篇来自人民大学的综述论文,揭秘这些大模型的训练技巧。
论文地址:
Link to paper
训练数据的收集与处理
大规模语言模型对训练数据的规模与质量有着更高的要求。那么,当前的大模型都使用了怎样的语料呢?这些语料发挥着怎样的作用?又该如何进行清洗和预处理?大模型在处理训练数据时还有哪些特殊的细节需要注意?
数据来源
大规模语言模型的训练数据一般可分为一般性语料与特殊语料。一般性语料,例如网页、书籍和对话文本,占据了较大的比例,能够在多种话题上为模型提供语言知识;而特殊语料,如多语言数据、科技语料和代码等,可以为模型引入解决特定任务的能力。现有的大模型训练语料的成分比例如下:
一般性语料中,网页语料的规模相对较大,虽然其中包括Wikipedia等高质量语料,但同样也混杂了垃圾邮件等低质量内容,因此需要过滤。问答语料,如来自Reddit等社交媒体平台,可以潜在地提升模型的问答能力。社交媒体通常涉及多人对话,能够将对话语料整理成树状结构,使得每一条支路都是一段完整的对话内容。书籍语料则提供了长篇书面文本,帮助模型学习严格的语言学知识,增强长距离依赖建模,从而提高生成内容的连贯性。
特殊语料方面,多语言语料有助于模型在翻译、多语言摘要和问答等任务上的表现。科技语料源自arXiv论文、教科书和数学网络社区,帮助模型掌握专业符号、术语和表达方式,提升其在科技任务推理中的表现。代码语料主要来源于Stack Exchange等问答社区以及GitHub上的开源项目,其中包含代码、注释和文档。近期的研究表明,代码语料能够提升模型的复杂推理能力,因为它具备长距离依赖和精确逻辑的特点。
获取开源语料源的相关地址,可以参考我们之前推送的资源:训练ChatGPT的必备资源:语料、模型和代码库完全指南。
清洗与预处理
在获得语料后,通常需要通过如下流程进行清洗和预处理,以提升数据质量。
具体而言,第一步是语料清洗,可以利用Wikipedia等样本作为正例,训练一个二分类器来筛选高质量语料。然而,近期的研究表明,这种筛选方式可能存在偏见,因此现在更推荐使用启发式规则进行筛选,例如剔除非目标任务语言、丢弃低困惑度数据、删除标点/符号过多或过长的句子,并剔除包含特定词汇(如HTML标签、链接、脏话、敏感词)的语句。
第二步是去重,处理重复词汇或短语的句子,以及重复率(基于词/n-grams共现)过高的段落。这样可以提升训练集质量,减少生成内容的重复现象,并避免测试集泄露所导致的过拟合问题。
第三步是通过关键词等方式剔除用户隐私信息(如姓名、地址、电话等)。
最后,经过三步清洗后,就可以进行分词,并准备训练。分词方面并没有特别复杂的技术,通常使用现成的分词器(如GPT-2)或者基于SentencePiece、Byte Pair Encoding等算法建立分词方法。
一些注意细节
大模型的特点要求在处理预训练语料时,需要关注一些特殊的细节:
- 调节语料混合比例。不同来源的语料混合比例需要合理调节,不能简单地以语料规模为依据。均衡的语料比例有助于增强模型的泛化能力,而特定类型的语料则可以提升模型在特定任务上的表现。
- 规模匹配。语料的规模应与模型的参数规模相匹配。经验表明,在给定算力的情况下,语料的token数与模型参数数相当时,模型的表现将相对更佳。因此,不应一味追求大规模语料,更应兼顾控制规模、提升质量和充分训练。
- 重视语料质量(再次强调)。实验表明,低质量语料即使不使用相比使用效果更佳。过多的重复数据会导致训练过程失败(崩溃或落入无意义的局部最优)。
模型结构与任务
主流的大规模语言模型普遍基于Transformers结构。从下图可见,绝大多数模型都采用了因果解码器结构,即仅使用解码器(单向注意力遮掩)来处理输入和输出内容。这或许是由于GPT-3展现出因果解码器的强大能力,使得研究者对其他结构的探索兴趣减少。
另外两种大规模语言模型结构,编码-解码器结构类似于最初的机器翻译模型,采用两个不共享参数的组件分别处理输入和输出内容。而前缀解码器与因果解码器相似,但在输入部分未采用单向注意力遮掩,允许双向注意力。这有点像共享参数的编码-解码器结构。
除了Transformer结构的选择,上表还展示了一些模型设计的细节,具体包括:
- 层归一化(Layer Normalization):是确保模型收敛、缓解训练崩溃的重要手段。经典的Pre Norm在每个多头注意力层与前馈网络层前加层归一化。Pre RMS Norm则在Pre Norm的基础上去掉了归一化中的均值部分,仅进行标准差的缩放,让优化过程更加平滑,是目前主流的推荐方法。此外,在Embedding后加Norm虽能使优化更平滑,但会明显降低模型表现,现今一般不再采用。
- 激活函数方面,传统的ReLU已不再适用。现越来越多研究认为SwiGLU和GeGLU能够带来更优表现,但相较于GeLU等函数,它们会引入更多参数。
- 位置信息编码:传统上有学习的绝对位置编码(Learned)与针对相对距离的相对位置编码(Relative)。后者在处理测试时使用更长语料时具有更好的外推性。最近RoPE方法被广泛应用,其将query和key向量加入绝对位置编码,使得其内积中包含相对位置信息的表达。
此外,上表中还汇总了部分超参数信息,如层数、头数、隐层规模和最大上下文长度(MCL)。
相较模型结构细节,预训练任务的设计则相对简单。最常见的预训练任务是自回归语言模型,模型逐一地根据输入历史预测下一个词,这一方法被广泛应用于GPT-3等语言模型。像T5和GLM-130B等模型则引入了降噪自编码的训练目标,帮助模型还原输入中被遮掩的语段。
优化设置与技巧
为了使训练过程更加高效和稳定,大规模语言模型的训练还采用了一系列“黑科技”。具体而言,这些技巧旨在:1. 提升模型最终表现;2. 提升模型收敛速度;3. 避免模型收敛到高损失的局部最优或出现不收敛现象;4. 避免训练过程崩溃。当前已有的大模型公开的优化设置与技巧如下表所示。
- Batch大小:通常设置得较大,以更有效地利用大规模训练数据,并提高训练过程的稳定性。比如,使用8196的batch size(每个batch处理1.6M个token输入)。GPT-3采取动态调整batch size的方式,使其处理的token数从32K逐步增大到3.2M。
- 学习率:通常较小,并包括warm-up设置,以确保训练的平稳进行。例如,在前0.1%~0.5%的训练步骤中,设置一个线性的学习率递增。峰值学习率一般在一定范围内,之后则采用余弦衰减策略,逐渐降低学习率,并在收敛前再降低约10%。
- 优化器:一般采用Adam、AdamW和Adafactor等。其中,Adafactor是Adam的一个节约显存的变种。
其它稳定训练过程的技巧包括梯度裁剪(gradient clipping),阈值一般设定为1.0;weight decay(类似于L2正则)则为0.1。尽管如此,大模型的训练过程仍然会出现崩溃的情况。PaLM和OPT提出在发生崩溃时可以从之前的某个中间节点继续训练,并跳过导致崩溃的训练数据。GLM发现,embedding层常出现异常梯度,需适度调整。
- 数据并行性(Data parallelism):是最常用的一种多卡训练方式。将训练数据分配到多显卡上分别进行前向和反向传播,再汇总梯度更新参数,实现模型同步。该方法可以解决单卡batch过小的问题。
- 流水线并行性(Pipeline parallelism):在单块显卡上仅存储和计算某些相邻层,为了缓解时序操作等待带来的低效问题,GPipe和PipeDream等工具提出在流水线中集成多个batch的数据,并异步更新参数。该方法能够缓解单卡处理batch-size为1的困难。
- 张量并行性(Tensor parallelism):对于大矩阵乘法运算,将矩阵进行拆分,从而实现较小矩阵的乘法拼接。该方法由Megatron-LM、Colossal-AI等工具实现,有效减轻显存占用,同时会带来一定的通讯成本。
- 混合精度训练:通过使用半精度浮点计算替代训练过程中的部分参数,特别是在前向传播部分,从而降低显存和提升速度。A100等显卡对半精度计算进行了优化,使得混合精度训练更加高效。近期也有研究提出用Brain Floating Point(BF16)替代传统的FP16,以增加指数位、减少有效数字。不过,虽然混合精度计算在速度上有明显提升,但经验表明仍可能影响准确度及模型表现。
- ZeRO:DeepSpeed提出的方案,旨在进一步优化数据并行的同时提高模型的显存空间并行性。上述混合精度计算流程表明,大量参数之外的存储资源被消耗掉。事实上,1.5B参数的半精度GPT-2在32GB显卡上无法训练,正是这个原因。ZeRO的主要思想在于将梯度、动量等更新相关信息也分布式存储于每块显卡上,从而实现各显卡更新对应参数并同步更新;在更新梯度后有效地释放相关显存。由于该方法相对复杂,此处不做详细阐述。PyTorch的DeepSpeed和FSDP工具均支持ZeRO。
在实际使用中,上述优化设置通常会组合使用。例如,BLOOM模型使用384块A100,采用8路数据并行、4路张量并行和12路流水线并行,并运用基于BF16的混合精度训练策略。DeepSpeed、Colossal-AI、Alpa等开源工具亦支持并行相关的功能。
此外,为了减少试错成本,GPT-4还提出了可预测的扩展,通过较小的神经网络模型预测大模型设置的可能表现,PyTorch的FSDP则支持让CPU分担一部分计算压力。
结束语
大规模语言模型训练不仅是一个科学问题,更是一个复杂的工程问题。科学家与工程师必须通力合作,才能有效推动大模型的发展。各种训练技巧助力提升大模型的训练效率与稳定性,然而,了解工程细节仅通过论文是远远不够的。深入掌握这些内容,还需认真阅读开源项目代码并进行实践操作。