大语言模型(LLMBook)
记录一下读这本书的一些Notes
https://github.com/RUCAIBox/LLMSurvey
前言
反观 GPT 系列模型的发展历程,有两点令人印象深刻。第一点是可拓展的训 练架构与学习范式:Transformer 架构能够拓展到百亿、千亿甚至万亿参数规模,并 且将预训练任务统一为预测下一个词这一通用学习范式;第二点是对于数据质量 与数据规模的重视:不同于 BERT 时代的预训练语言模型,这次大语言模型的成 功与数据有着更为紧密的关系,高质量数据、超大规模数据成为大语言模型的关 键基础。
确实,为 了训练百亿级别的高水平大模型,通常需要最少百卡级别的 A100/A800 (80G) 资 源,而为了充分探索训练过程中的各种细节,往往需要有千卡级别的 A100/A800 (80G) 资源作为支撑。
引言
。ELMo [11] 是一个早期的代表性预训练语言模型,提出使用大量的无标注数据训练双向 LSTM (Bidirectional LSTM, biLSTM)网络,预训练完成后所得到的 biLSTM 可以用来学 习上下文感知的单词表示。然而,传统序列神经网络的长文本建模能力较弱,并且不容易并行训练,这些缺点限制了早期预训练模型(如 ELMo)的性能。
在 2017 年,谷歌提出了基于自注意力机制(Self-Attention)的 Transformer 模型 [12],通过 自注意力机制建模长程序列关系。Transformer 的一个主要优势就是其模型设计对 于硬件非常友好,可以通过 GPU 或者 TPU 进行加速训练,这为研发大语言模型提 供了可并行优化的神经网络架构
一般来说,编码器架构被认为更适合去解决自然语 言理解任务(如完形填空等),而解码器架构更适合解决自然语言生成任务(如文本摘要等)。
大语言模型主要通过预测下一个词元的预训练任务进 行学习,虽然并没有针对特定的下游任务进行优化,却能够建立远强于传统模型 的通用任务求解能力。实际上,基于大规模无标注文本的下一个词元预测任务本 质上可以看作一个多任务学习过程 [17],因为针对不同词元的预测任务可能涉及 到情感分类(“... 这部电影真好看”)、数值计算(“3+4=7”)、知识推理(“中国陆 地面积最大的省份是新疆”)等非常多样的训练任务。
- 在海量的数据中进行next-token prediction,已经涉及到了很多任务了
大语言模型的能力特点
* 具有较为丰富的世界知识.
* 具有较强的通用任务解决能力
* 具有较好的复杂任务推理能力
* 具有较强的人类指令遵循能力
* 具有较好的人类对齐能力
* 具有可拓展的工具使用能力
大语言模型关键技术概览
* 规模扩展。实现规模扩展的关键在于模型架构的可扩展性
* 数据工程。数据质量,数据规模
* 高效预训练。DeepSpeed/Megatron-LM
* 能力激发。指令微调,提示工程
* 人类对齐。RLHF,对齐人类价值观。(这里应该也算是指令微调?)
* 工具使用。通过指令微调/提示工程做
虽然工业界或者大型研究机构不断推出性能优异的开源大模型, 但是这些模型的训练过程的开源程度还不够充分,许多重要的训练细节仍缺乏公 开的研究报道。特别地,现有的大语言模型非常依赖于工程方法的优化(如数据 清洗等),但是这些技术的理论支撑还比较缺乏。
通过将图像、视频等模态的信息与文本语义空间相融合,可以通过 计算量相对较少的微调方法来研发多模态大语言模型。进一步,基于下一个词元 预测的思路也可能会带来多模态领域的基础模型架构的转变,例如 OpenAI 最新 推出的 Sora 模型就是基于图像块序列建模的思路进行构建的。
- 想到了vision transformer,把图像块建模为序列,做next token prediction即可
基础介绍
一般来说,预训练是指使用与下游任务无关的大规模数据进行模型参数的初 始训练,可以认为是为模型参数找到一个较好的“初值点”。这一思想最早在计算 机视觉领域被广泛使用,通过使用大规模的图像标注数据集合 ImageNet 用于初始化视觉模型的参数。
在自然语言处理领域,word2vec [8] 采用了类似的预训练思想, 使用无标注的文本语料训练可通用的词嵌入模型;后来被 ELMo [11]、BERT [13] 和 GPT-1 [14] 推广到训练可迁移的自然语言任务架构,逐步成为了研发大语言模 型的核心技术路径。目前的开源模型普遍 采用 2∼3T 规模的词元进行预训练,并有趋势进一步扩大这一规模。这一过程对于 算力需求量极高,一般来说训练百亿模型至少需要百卡规模的算力集群(如 A100 80G)联合训练数月时间(与具体的算力资源相关);而训练千亿模型则需要千卡 甚至万卡规模的算力集群,对于算力资源的消耗非常惊人。
尽管整体的预训练技术框架非常直观,但是实施过程中涉及到大量需要深入 探索的经验性技术,如数据如何进行配比、如何进行学习率的调整、如何早期发现 模型的异常行为等。预训练过程需要考虑各种实施细节,而这些细节有很多并没 有公开发表的经验可循,需要研发人员具有丰富的训练经验和异常处理能力,避免大规模训练开始以后进行回退和反复迭代,从而减少算力资源的浪费,提升训 练成功的几率。大语言模型的研发看似是一个算力需求型的工程,实际上相关人 才是最重要的。可以说,一个大语言模型项目的核心训练人员的能力最后会决定 模型的整体水平。
OpenAI 在 2022 年初发布了 InstructGPT [28] 的学术论文,系统地介绍了如何将语言模型 进行人类对齐。具体来说,主要引入了基于人类反馈的强化学习对齐方法 RLHF (Reinforcement Learning from Human Feedback), 在指令微调后使用强化学习加 强模型的对齐能力。
scaling law:
模型规模(𝑁)、数据规模(𝐷)和计算算力(𝐶)
Chinchilla 扩展法则 from DeepMind:
Chinchilla 扩展法则这项研究的意义并不在于给出了资源在数据规模与模型规模上的具体分配方案,而是首次形式化指出了之前的预训练工作可能忽视了训练 数据的规模扩展。例如,具有 175B 参数的 GPT-3 仅仅使用了 300B 的词元进行训练, 所使用的数据量远远没有达到模型能够编码的最大数据容量。
根据 Chinchilla 扩展 法则的指导,DeepMind 的研究团队进一步训练得到了具有 70B 参数的Chinchilla 模型,使用大概 1.4T 的词元进行训练。虽然后续有些人借鉴 Chinchilla 模型的线性分配比例(数据规模大概是模型参数规模的五倍),但是目前这一分配系数已经 基本没有参考意义了。越来越多的工作表明,现有的预训练语言模型对于数据的 需求量远高于这些扩展法则中所给出的估计规模。例如,LLaMA-2 (7B) 的模型就 使用了 2T 的词元进行训练,很多更小的模型也能够通过使用超大规模的预训练数 据获得较大的模型性能提升。
这种现象的一个重要原因是由于 Transformer 架构具 有较好的数据扩展性,到目前为止,还没有实验能够有效验证特定参数规模语言 模型的饱和数据规模(即随着数据规模的扩展,模型性能不再提升)。
* 目前看,模型质量不太会随着数据的提升而饱和,所以数据比较关键
* 根据实际经验,比如GPT等模型,随着训练,效果会越来越好,不会达到收敛点。所以才有了随着算力提升模型效果的规律可预测扩展对于大模型训练具有两个主要的指导作用。首先,对于大语言 模型来说,详细进行各种训练技巧或变体的测试需要耗费巨大的算力资源。因此, 一个较为理想的经验性方法是,基于小模型获得训练经验然后应用于大模型的训 练,从而减少实验成本。
例如,可以训练小型代理模型来确定适合大型模型的预 训练数据混合的最佳比例
* 这里训练数据混合比例是指什么?什么和什么混合?不同类型的数据吗?
* 为什么和Scaling Law有关?根据 GPT-4 的 报告 [35],通过扩展法则可以准确预测某些任务能力(例如编码能力),但是对 于有些任务的性能预测是非常困难的。此外,有些重要能力(例如上下文学习能 力 [23])根据扩展法则是不可预测的,只有当模型大小超过一定规模时才会出现, 如下文所讨论的涌现能力。
* 并不是所有的能力都遵循scaling law,比较关键的上下文学习能力(感觉偏向理解),依赖模型的规模相比于上下文学习能力,指令遵循能力整体上更容易获得,但是最终的任务执行效果 还取决于模型性能和任务难度决定。例如,FLAN-PaLM 模型 [41] 测试了 8B、62B 以及 540B 三个参数规模的模型在指令微调之后的效果,当参数规模达到 62B 及 以上的情况,才能够在包含 23 个复杂推理任务的 BBH 评估基准上,展现出较好 的零样本推理能力
* 可能是模型大到一定层面,才有足够的层来处理比较抽象的信息,从而获得推理能力
BERT 与 GPT-1 虽然都采 用了基于 Transformer 架构的预训练学习方式,但是它主要面向自然语言理解任务 (Natural Language Understanding, NLU)
OpenAI 团队在 GPT-2 的论文中还尝试解释无监督预训练在下游任务中取得良 好效果的原因:“由于特定任务的有监督学习目标与无监督学习目标(语言建模) 在本质上是相同的(预测下一个词元),主要区别就在于它们只是在全部训练数据 的子集上进行优化,因此对于特定下游任务而言,优化无监督的全局学习目标本 质上也是在优化有监督的任务学习目标” 。
对这一说法的通俗理解是,语言 模型将每个(自然语言处理)任务都视为基于世界文本子集的下一个词预测问题。 因此,如果无监督语言建模经过训练后具有足够的能力复原全部世界文本,那么 本质上它就能够解决各种任务。虽然 GPT-3 的论文没有明确 提出上下文学习能力是大语言模型的涌现能力,但是指出了上下文学习对于大模 型的性能增益会更加显著,而对于小模型来说则收益较小(见 GPT-3 论文 的 原始图 1.2 )。
OpenAI 关于人类对齐的公开研究工作可以追溯到 2017 年(实际 5 时间或更早)。在一篇题为“Learning from Human Preferences” 的博客文章中,OpenAI 的研究团队介绍了一项使用强化学习算法从人类标注的偏好数据中学习如何 改进模型性能的工作。
在这篇强化学习工作发表不久,2017 年 7 月 OpenAI 研 究团队又提出了一项改进的强化学习算法— PPO 算法(Proximal Policy Optimization, PPO),这也成为了 OpenAI 在后续人类对齐技术里所采用的标配强化学 习算法。值得一提的是,在 OpenAI 的论文和相关文 档中,很少使用“指令微调”(Instruction Tuning)一词,主要是使用“监督微调” 一词(即基于人类反馈的强化学习算法的第一步 )
InstructGPT中使用的就是SFT,或者叫instruction tuning,然后再做的RLHF
为了有效降低使用模型的潜在风险, OpenAI 采用了迭代部署策略 ,通过多阶段开发和部署的生命周期来研发模型 与产品。
* OpenAI. “Lessons learned on language model safety and misuse”. In: OpenAI Blog (2022).
大语言模型资源
Meta AI 使用 LLaMA-2 作为基座模型,通过进一步的有监 督微调、基于人类反馈的强化学习等技术对模型进行迭代优化,完整经历了“预训 练-有监督微调-基于人类反馈的强化学习”这一训练流程,并发布了面向对话应用 的微调系列模型 LLaMA-2 Chat
通过引入 分组查询注意力和滑动窗口注意力技术,Mistral 在 16K 序列长度和 4K 注意力窗 口大小下速度提升了 2 倍。
Mixtral [67] 全称为 Mixtral 8×7B,是 Mistral AI 在 2023 年 12 月公 开发布的稀疏混合专家模型架构的大语言模型,这也是较早对外公开的 MoE 架 构的语言模型。在结构上,Mixtral 包含 8 组不同的“专家”参数,对于每个词元, Mixtral 的每一层都会通过路由网络选择两组“专家”来对其进行处理,并将它们 的输出相加结合起来。
虽然 Mixtral 一共有 46.7B 参数,但是每个词元在处理过 程中只会用到 12.9B 参数,因此其处理速度和资源消耗与 12.9B 参数的模型相当。为了使 LLaMA 模型能够有效地支持中文,研究人员通常会选择 扩展原始词汇表,在中文数据上进行继续预训练,并用中文指令数据对其进行微调
* 可以拓展词汇表,继续在中文数据上做预训练为了增强 LLaMA 模型的垂域能力,很多工作基于搜集到的垂域相关的指令数据,或者采用垂域知识 库以及相关专业文献等借助强大的闭源模型 API(例如 GPT-3.5、GPT-4 等)构建多 轮对话数据,并使用这些指令数据对 LLaMA 进行指令微调。常见的垂域 LLaMA 模型有 BenTsao(医学)、LAWGPT(法律)、TaoLi(教育)、Goat(数学)、Comucopia (金融)等。
* 垂直领域的finetune,通过和更强的模型做对话得到高质量的数据,再去finetune小模型由于 LLaMA 模型作为纯语言模型的强大能力,许多的多模态 模型都将其(或将其衍生模型)作为基础语言模型,搭配视觉模态的编码器,使 用多模态指令对齐视觉表征与文本
* 也有基于LLAMA做的多模态的模型。可能就是搭配一个视觉的编码器,比如基于图像块的tokenizer就可以了?
* 这种应该需要重新预训练?
* LLAMA生态
ShareGPT. 该数据集因来源于一个开源的数据收集平台 ShareGPT 而得名。 在该平台中,用户可以将自己的各种对话数据通过浏览器插件进行上传。这些对 话包括来自 OpenAI ChatGPT 的用户提示和回复,语种主要为英语和其他西方语 言。具体来说,查询来自于用户的真实提问或指令,回复则是 ChatGPT 对此生成 的回答。
合成数据集通常是使用大语言模型基于预定义的规则或方法进行构建的。其中,Self-Instruct-52K [74] 和 Alpaca-52K [42] 是两个具有代表性的合成数据集。
Self-Instruct-52K. Self-Instruct-52K 是使用 self-instruct 方法(详见第 7.1.3 节) 生成的英语指令数据集,共包含 52K 条指令以及 82K 个实例输入和输出。最初, 由人工收集创建了 175 个种子任务,每个任务包括 1 个指令和 1 个包含输入输出 的实例。然后,每次随机抽取了 8 个指令作为示例,以此提示 GPT-3 生成了新的 指令,之后在这些已有指令的基础上,继续利用 GPT-3 生成实例输入及其对应的 输出,从而获得了更多数据。这些新得到的指令和输入输出经过滤(去除低质量 或重复数据)后会加入数据集中,并继续类似的循环。通过迭代上述过程,最终 获得了 52K 条指令和 82K 个实例数据,其中每一条指令可能会用于生成多个输入 输出的实例。
* 这里输入给模型的数据应该是指令+输入,得到输出。比如翻译这个句子,A,B。那么翻译这个句子就是指令,A就是输入,B就是输出
* 有用性,无害性,诚实性是对齐人类的三个目标
Stack Exchange Preferences. 该数据集专注于对答案的有用性进行标注,涵盖 了来自知名编程问答社区 Stack Overflow 的约 10M 个问题和答案,具有很高的实 用价值。每个数据实例均包含一个具体的问题以及两个或更多的候选答案。每个 候选答案都附有一个根据投票数计算得出的分数,并附带了一个表示是否被选中 的标签。
* 感觉用stack overflow这里做有用性的对齐,质量会非常高DeepSpeed 为分布式训练提供了各种优化技术支持,如内存优化(ZeRO 技术、 梯度检查点)、数据并行、混合精度训练等
DeepSpeed-MII. 该框架旨在通过提高吞吐量、降低延迟等方式来降低大模型 解码生成的运行成本。首先,DeepSpeed-MII 实现了两项重要技术以加速文本生成 过程:(1)块状键值缓存,将键值缓存分割成固定大小的块,从而减少了内存碎片 化的情况,提升整体的系统吞吐量;(2)连续批处理,在模型的每个前向传播过 程中进行独立的调度决策,以实现更细粒度的调度和优化内存效率。
DeepSpeed-Chat. 该框架是一个易于使用的用于训练类 ChatGPT 模型的开发 工具,完整集成了包括基于人类反馈的强化学习算法在内的训练过程。
- 开源代码相关:
- Hugging Face下的Transformer/Datasets/Accelerate
- 注意Accelerate是简化,而不是替换,主要是优化PyTorch的分布式训练
- 微软的DeepSpeed
- NVIDIA的Megatron-LM
- Hugging Face下的Transformer/Datasets/Accelerate
数据准备
根据来源不同,预训练数据主要分为两种类型:通用文本数据和专用文本数 据。通用文本数据涵盖了网页、书籍和对话文本等。由于通用文本数据规模较大、 多样性强且易于获取,大多数大语言模型都会收集大量的通用文本数据,以增强 其语言建模能力
在预训练语料中,加入多语言的文本数据可以增强模型的多语理 解与生成能力。BLOOM [100] 模型和 PaLM [33] 模型在其预训练语料中分别使用 了涵盖 46 种和 122 种语言的多语数据,进而使得这两个模型在翻译、跨语言摘要 和问答等多语言任务中性能表现优异。
为了精确过滤含有有毒内容的文本,可以采用基于分类器的 过滤方法。Jigsaw 评论数据集 [124] 提供了用于训练毒性分类器的数据。该数据集 收集了近 160K 条论坛评论数据,每条评论都经过细致的标注,包括“有毒”、“严 重有毒”、“有威胁”、“侮辱性”、“暴力”以及“身份仇恨”等六个类别。利用 这一数据集进行训练,可以构建出高效的毒性文本分类器。通过设置合理的阈值, 训练完成的分类器将能够有效识别并过滤掉含有有毒内容的信息
对预训练数据进行去重处理是一个重要步骤。由于大语言模型具有较强的数 据拟合与记忆能力,很容易习得训练数据中的重复模式,可能导致对于这些模式 的过度学习。研究工作发现 [125],预训练语料中出现的重复低质量数据可能诱导 模型在生成时频繁输出类似数据,进而影响模型的性能。
有研究表明 [125],将语料中 0.1% 的数据重复 100 次后,基于这些 包含重复数据语料训练的 800M 参数模型,其性能仅能达到在无重复语料上训练 的 400M 参数模型的相同表现
* 重复数据的影响这么大?最近,子 词分词器(Subword Tokenizer)被广泛应用于基于 Transformer 的语言模型中,包 括 BPE 分词、WordPiece 分词和 Unigram 分词三种常见方法
hugging face这里有一个nlp course, 讲tokenizer: https://huggingface.co/learn/nlp-course/chapter6/1
最近的大 语言模型通常使用 SentencePiece 代码库 [144] 为预训练语料训练定制化的分词器, 这一代码库支持字节级别的 BPE 分词和 Unigram 分词。
此外,为 进一步提高某些特定能力(如数学能力),还可能需要针对性地设计分词器。例如, BPE 分词器可能将整数 7,481 分词为“7 481”,而将整数 74,815 分词为“748 15”。 这导致相同的数字被分割成不同的子串,降低了解决相关数学问题的能力。相比 之下,专门设计基于数字的分词方式可以避免这种不一致性,从而提升大语言模 型的数值计算能力。
* 符号这块需要特殊处理,避免语意信息丢失通常来说,数据调度(Data Scheduling)主要关注两个方 面:各个数据源的混合比例以及各数据源用于训练的顺序
LLaMA [34] 的预训练数据主要包括超过 80% 的网页数据、来 自 GitHub 和 StackExchange 的 6.5% 代码密集型数据、4.5% 的书籍数据,以及来 自 arXiv 的 2.5% 科学数据,这个数据配比成为了训练大语言模型的一个重要参考。
还可以使用可学习的方法来 优化数据组成,以改善模型的预训练效果 [36, 148]。例如,可以根据目标下游任 务来选择特征空间相似的预训练数据 [148],或对下游任务性能可以产生正面影响 的数据 [149]。为了减少对于目标任务的依赖,DoReMi [36] 首先使用给定的初始 领域权重训练一个小型参考模型,然后在每次迭代过程中,使用当前的领域权重 计算得到数据比例,用其训练另一个小型代理模型。然后通过比较两个模型损失 值的差距,对该域数据的采样权重进行优化。具体来说,对于代理模型“未较好 习得的”数据域,所分配的域权重将会被增加。最后,通过多轮迭代,代理模型最 终的域权重将被应用于大语言模型训练。
例如, 可以通过使用更多的数学文本和代码数据来增强大语言模型的数学推理和编程能 力,而增加书籍数据的比例可以提高模型捕捉文本长程依赖关系的能力 [150]。
相关研究表明,为了学习某些特定的技能,按照技能依赖 顺序编排对应数据集的学习方法(例如,基本技能 → 目标技能)比直接在相关的 特定语料库上学习效果更好 [151, 153]。
* 按照依赖学习的例子>
研究人员基于 LLaMA 2 [58] 开发了 CodeLLaMA [151],能够更为有效地执行代码任务。采用的数据为: 2T 通用词元 → 500B 代码密集型词元
CodeLLaMA 还提供了一个面向 Python 语言的特定代码大模型, 即 CodeLLaMA-Python,采用了如下的数据训练课程:2T 通用词元 → 500B 代码 相关的词元 → 100B Python 代码相关的词元。虽然 CodeLLaMA [151] 主要关注编程能力, 但是实验表明它在数学基准测试上的表现优于其基础模型 LLaMA-2 [156]。 整体的数据课程为:2T 通用词元 → 500B 代码相关的词元 → 50∼200B 数学相关的词元。
值得注意的是,Llemma 的继续预训练数据中还包含 5%的通用领域数据,这可以看做一种模型能力的“正则化”技术,加强对于原始 基座模型通用能力的保持。
* 避免丢失通用能力CodeLLaMA 将 LLaMA-2 的上下文窗口从 4K 扩展到了 100K,所采用的数据课程为:2.5T 词元,4K 上下文 窗口 → 20B 词元,16K 上下文窗口。
* 从短到长,可以节省训练时间为此,我们预训练一个 1.3B 的小模型,首先对语言配比进行确定,然后确定不同数据类型配比。具体来 说,每次训练时,从各个数据集按照不同配比采样得到 50B 数据,然后从头开始 对 1.3B 模型进行预训练,并根据在诸多下游任务的测试效果最终确定中英文语料 比例为 1:8。然后,维持该比例不变,并选择 LLaMA 的数据比例作为基础,在其 基础上使用控制变量法,每次仅调整某一类型数据的比例进行实验,依旧通过下 游任务效果来决定是否采用该新数据比例,进而获得整体的数据混合配比。然而, 在训练过程中,YuLan 各项能力出现了不一致的增长速率,例如文本生成能力迅 速提升但数学推理能力长期并未出现较好的增长。针对这一问题,我们进一步根 据各项能力的测试结果对于数据混合比例进行了手动调整。最终,YuLan 的预训 练阶段共使用了 1,680B 词元,其中包括 1,380B 英文数据,280B 中文数据,以及 20B 的多语数据。
* 预训练模型的例子,有几个需要关注的点:
* 观测模型各个阶段的能力,需要对各项指标的增长能力有所了解。这里提前发现了数学推理能力不够
* 为什么预期推理能力会增长?而不是涌现出来的?
* 说明需要有比较好的训练经验,才能及时发现问题。不同模型,不同数据可能都有不同的增长路线
* 数学能力需要增加代码数据,所以需要根据模型的表现(动态?)调整数据的输入
模型架构
* 都是transformer家族的模型们
DeepNorm 由微软的研究人员提出 [160],旨在稳定深层 Transformer 的训练。具体而言,DeepNorm 在 LayerNorm 的基础上,在残差连接中对 之前的激活值 𝒙 按照一定比例 𝛼 进行放缩。通过这一简单的操作,Transformer 的 层数可以被成功地扩展至 1,000 层 [160],进而有效提升了模型性能与训练稳定性。
由于 Transformer 模型中自注意力模块具有置换不变性,因此仅使用注意力机 制无法捕捉序列中的顺序关系,从而退化为“词袋模型”。
绝对位置编码. 在原始的 Transformer 模型中,为了处理序列数据的顺序信 息,采用了绝对位置编码方法。在编码器和解码器的输入端,根据输入的词元在 序列中的绝对位置生成唯一的位置嵌入,并与词元的嵌入表示进行相加来注入位 置信息。
相对位置编码. 与绝对位置编码不同,相对位置编码是根据键和查询之间 的偏移量计算得来的。计算得到的相对位置编码通常应用于注意力矩阵的计算中, 而不是直接与词元本身的位置编码进行相加。
除了在算法层面上提升注意力机制的计算效率,还 可以进一步利用硬件设施来优化注意力模块的速度和内存消耗。其中,两个具有 代表性的工作是 FlashAttention [173] 与 PagedAttention [174]。相比于传统的注意力 实现方式,FlashAttention 通过矩阵分块计算以及减少内存读写次数的方式,提高 注意力分数的计算效率;PagedAttention 则针对增量解码阶段,对于 KV 缓存进行 分块存储,并优化了计算方式,增大了并行计算度,从而提高了计算效率。
首先,因果解码器没有显式地区分输入和输出部分。如图 5.6 所示,该架构采用了单向的掩码注意力机制,使得每个输入的词元只关注序列中位于它前面的词元和它本身,进而自回归 地预测输出的词元。
前缀解码器架构也被称为非因果解码器架构,对于因果解码器的掩码机制进 行了修改。该架构和因果解码器一样,仅仅使用了解码器组件。与之不同的是,该 架构参考了编码器-解码器的设计,对于输入和输出部分进行了特定处理。如图 5.6 所示,前缀解码器对于输入(前缀)部分使用双向注意力进行编码,而对于输出 部分利用单向的掩码注意力利用该词元本身和前面的词元进行自回归地预测。与 编码器-解码器不同的是,前缀解码器在编码和解码过程中是共享参数的,并没有 划分为独立的解码器和编码器。
- 长上下文两点:
- 拓展位置编码
- 调整上下文窗口
在基于 Transformer 架构的大语言模型中,模型的上下文建模能力通常受到训 练集中文本数据长度分布的限制。一旦超出这个分布范围,模型的位置编码往往 无法得到充分训练,从而导致模型处理长文本的性能下降。因此,当大语言模型 面临超出其最大训练长度的任务时,需要对于位置编码进行扩展,以适应更长的 绝对或相对位置。
模型预训练
目前,常用 的预训练任务主要分为三类,包括 语言建模(Language Modeling, LM)、去噪自编 码(Denoising Autoencoding, DAE)以及混合去噪器(Mixture-of-Denoisers, MoD)。
语言建模任务是目前绝大部分大语言模型广泛采用的预训练任务。该任务的 核心在于“预测下一个词元”,并且经常被应用于训练基于解码器的大语言模型
语言建模的另一个重要变种是中间填充任务 [192]。此任务通过重新调整输入 序列的顺序,旨在训练模型对于中间缺失信息的填充能力。具体来说,一个输入 序列 𝒖 被划分为三个部分:前缀 𝒖 prefix 、中间部分 𝒖 middle 和后缀 𝒖 suffix 。随后,中 间部分被移至序列末尾。因此,模型需要自回归地对新序列 𝒖 prefix ⊕ 𝒖 suffix ⊕ 𝒖middle 进行预测。
现在很多工作都采用了动态批次调整策略,即在训练过程中逐渐增加批次大 小,最终达到百万级别。例如,GPT-3 的批次大小从 32K 个词元逐渐增加到 3.2M 个词元;PaLM-540B 的批次大小从 1M 个词元逐渐增加到 4M 个词元。相关研究 表明,动态调整批次大小的策略可以有效地稳定大语言模型的训练过程 [33]。这 是因为较小的批次对应反向传播的频率更高,训练早期可以使用少量的数据让模 型的损失尽快下降;而较大的批次可以在后期让模型的损失下降地更加稳定,使 模型更好地收敛。
* 小批次的话,会更新更多次的参数,所以训练会更快一点
流水 线并行通常需要配合梯度累积(Gradient Accumulation)技术进行优化。该技术的 主要思想是,计算一个批次的梯度后不立刻更新模型参数,而是累积几个批次后 再更新,这样便可以在不增加显存消耗的情况下模拟更大的批次。
* 计算/显存的trace off,不过模型放倒显存本身也是为了加速,所以这里也是对带宽的tradeoff。
* 说明放到内存,需要的时候从走PCIe回显卡,再计算梯度。不如直接在显卡上重新计算
* 还是计算密集型和带宽密集型的区分,计算密集型,就需要靠带宽来优化。带宽密集型,就重新计算。
通过同时使用半精度浮点 数(2 个字节)和单精度浮点数(4 个字节)进行运算,以实现显存开销减半、训练 效率翻倍的效果。具体来说,为了保证表示精度,需要保留原始 32 位模型的参数 副本。但在训练过程中,会先将这些 32 位参数转换为 16 位参数,随后以 16 位精 度执行前向传播和反向传播等操作,最后在参数更新时再对 32 位模型进行优化。
常见的半精度浮点数表示方式为 FP16,其包 含 1 位符号位、5 位指数位和 10 位尾数位,表示范围为 −65504 到 65504。进一步, 谷歌的研究人员深度学习场景提出了新的半精度浮点数表示 BF16,其包含 1 位符 号位、8 位指数位和 7 位尾数位,表示范围可以达到 10 38 数量级。相比于 FP16, BF16 有着更大的数值范围,在大模型训练中被广泛使用。
值得一提的是,目前较为主流的 GPU (例如英伟达 A100)都支持 16 位计算单元运算,因此混合精度训 练能够被硬件很好地支持。
* 这里的计算说明一共只会把所有的数据过一遍,而不是多遍
指令微调
一般来说,一个经过指令格式化的数据实例包括任务描述(也称为指令)、任 务输入-任务输出以及可选的示例。
* 指令就是任务描述
经过 NLP 指令数据微调后,大语言模型可以学习到指令遵循(Instruction Following)的能力,进而能够解决其他未见过的 NLP 任务 [39–41]。相关研究表明在 现有 NLP 数据集的输入-输出数据中添加合适的任务描述是提升大模型指令跟随 能力的关键因素;如果去除了这些任务描述,仅使用输入-输出数据对模型进行微 调,模型的性能会出现显著下降 [39]。
* 看起来主要是从这里学习到few-shot learning的能力
代表性 工作 Self-Instruct [74] 方法仅需要使用 100 多个人工撰写的实例作为初始任务池, 然后随机选择数据作为示例,就可以通过提示大语言模型生成新的指令微调数据。 这种半自动化的合成方法具备高效生成大规模指令微调数据的能力,从而显著降 低了人工标注所需的经济成本,在实践中得到了广泛应用。
* 通过数据生成指令,再生成数据
* 通过例子生成新的指令
* 根据新的指令生成输出
* 过滤重复,以及低质量的数据
Evol-Instruct:
* 然后用模型去做判断,过滤质量低的提示。
* 用人的地方都可以用模型替代
然而,指令数据并不是包含信息越多越好,添加某些看似有用的信息(例如 需要避免的事项、原因或建议)到指令中,可能不会带来明显的效果提升,甚至 可能产生不利影响 [201]。
* 指令数据不是越多越好Alpaca [42] 使用了 52K 条 合成数据来指令微调 LLaMA (7B),在 179 条日常对话数据的评测中到达了接近 text-davinci-003 的效果。进一步,LIMA [203] 仅使用了一千条人工标注的高质 量指令数据来微调 LLaMA (65B),就在 300 条日常对话测试中取得了较好的模型 表现。
* 数据质量非常关键另一方面,研究人员尝试从大量数据集中筛选出部分指令来进行微调。Alpagasus 利用 GPT-4 从原始的 52K 条 Alpaca 数据中筛选出 GPT-4 评分较高的 9 千条。 使用这 9 千条数据进行指令微调训练,便可以在下游测试任务中达到与原始 52K 条数据接近的效果。YuLan-Chat-3 提出了“平衡指令难度”策略,其用大模型的困 惑度分数来估算指令数据的难度水平,删除过于简单或过于困难的指令数据,从 而缓解大模型训练不稳定或者过拟合的现象。
* 数据处理的策略
* 通过蒸馏,提高数据质量,从而提高下游模型的能力
* 控制指令的难度,提高收敛速度目标函数. 预训练阶段通常采用语言建模损失(详见第 6.1.1 节),优化模型 在每一个词元上的损失。而指令微调可以被视为一个有监督的训练过程,通常采 用的目标函数为序列到序列损失,仅在输出部分计算损失,而不计算输入部分的 损失。
* SFT阶段,损失为序列到序列的损失
LoRA相关:
研究人员 [214] 发现模型在针对特定任务进行适配时,参数矩阵往往 是过参数化(Over-parametrized)的,其存在一个较低的内在秩
* 是针对特定任务的时候,才是过参数化的
* 当A和B矩阵比较小的时候,微调需要更新的参数量就会变少一般来说,LoRA 主要被应用在每个多头注意力层的 4 个线性变 换矩阵上(即 𝑾 𝑄, 𝑾 𝐾, 𝑾 𝑉, 𝑾 𝑂∈ R 𝐻×𝐻)
LoRA的变种:
AdaLoRA [215] 讨论了如何更好地进行秩的设置。它引入了一种动态低秩适 应技术,在训练过程中动态调整每个参数矩阵需要训练的秩同时控制训练的参数 总量。具体来说,模型在微调过程中通过损失来衡量每个参数矩阵对训练结果的 重要性,重要性较高的参数矩阵被赋予比较高的秩,进而能够更好地学习到有助 于任务的信息。相对而言,不太重要的参数矩阵被赋予比较低的秩,来防止过拟 合并节省计算资源。
QLoRA [216] 将原始的参 数矩阵量化为 4 比特,而低秩参数部分仍使用 16 比特进行训练,在保持微调效果 的同时进一步节省了显存开销。
还有一些其他的finetune的方法,用的比较少,就不记录了
还有一个instruction tuning的结论:
* 使用与下游任务格式更接近的指令能够带来更大提升
* 提高指令复杂性和多样性能够促进模型性能的提升
* 更大的参数规模有助于提升模型的指令遵循能力
人类对齐
虽然原始的 InstructGPT 采用了较小的 GPT-3(只有 6B 参数)作为奖励 现阶段的研究通常认为使用与待对齐模型规模相同或者更大规模的奖励模型可以 获得更好的对齐效果,主要是因为较大规模的奖励模型可以更好地理解待对齐模 型的知识与能力范围,从而提供更为合适的指导信号,例如 LLaMA-2 [58] 使用相 同的检查点初始化待对齐模型和奖励模型。
奖励模型训练. 第二步是使用人类反馈数据训练奖励模型。具体来说,首先 使用语言模型针对任务指令生成一定数量的候选输出。随后,邀请标注员对于输 出文本进行偏好标注,这个标注过程可以采用多种形式,其中最常用的是对候选 文本进行排序标注,这样可以有效减少多个标注员之间的不一致情况
在 InstructGPT 中,标注员将模型生成的输出按照最佳到最 差的顺序进行排序,并据此训练奖励模型来预测这个排序强化学习训练. 在这一步骤中,语言模型对齐被转化为一个强化学习问题。 具体来说,待对齐语言模型担任策略实施者的角色(称为策略模型),它接收提 示作为输入并返回输出文本,其动作空间是词汇表中的所有词元,状态指的是当 前已生成的词元序列。奖励模型则根据当前语言模型的状态提供相应的奖励分数, 用于指导策略模型的优化。为了避免当前训练轮次的语言模型明显偏离初始(强 化学习训练之前)的语言模型,通常会在原始优化目标中加入一个惩罚项(如 KL 散度)。
对比式训练方法一定程度上能够克服打分式训练方法的不足。针对 一个问题输入,人类标注者仅需对两条相应输出进行排序,排序在前的输出被视 为正例(更符合人类偏好),另一条输出则被视为负例。这种标注方式不仅降低了 标注难度,还提高了不同标注者之间的一致性。
* 因为打分式不同人的打分标准不同目标函数优化. 在训练大规模奖励模型时,有时会遇到过拟合问题。为了解 决这一问题,可以将最佳的模型输出所对应的语言模型损失作为正则项,从而缓 解奖励模型在二元分类任务上的过拟合问题。因此,可以在对比式方法的损失函 数(即公式 8.2)的基础上添加模仿学习(Imitation Learning)的损失函数,即奖励模型在学习最大化正负例分数差距的同时也学习基于输入 𝑥 生成正例 𝑦 + :
* 增加一个语言模型的损失,避免在分类任务上过拟合,因为模型参数比较大由于对齐存在多个标准(例如有用性和诚实性),单一奖励 模型很难满足所有对齐标准。因此,可以针对不同对齐标准训练多个特定的奖励 模型 {𝑟 𝑖 (𝑥, 𝑦)} 𝑖=1 𝑛 ,然后使用特定的组合策略(例如取平均值或加权平均)计算基 于这些奖励模型的最终奖励。
在实现中,DPO 采用梯度下降的方式来优化策略模型的参数 𝜃。通过对上述目 标函数的导数进行分析,可以发现优化过程中会增大 log 𝜋 𝜃 (𝑦 + |𝑥) 与 log 𝜋 𝜃 (𝑦 − |𝑥) 之间的差异。这表明优化过程中训练模型向符合人类偏好的内容靠近(𝑦 + ),同时尽 量避免生成不符合人类偏好的内容(𝑦 −)
文章评论