大模型(LLMs)增量预训练篇
来源:AiGC面试宝典 作者:宁静致远 日期:2024年01月27日
目录
- 1 为什么要增量预训练?
- 2 进行增量预训练需要做哪些准备工作?
- 3 增量预训练所用训练框架?
- 4 增量预训练训练流程是怎么样的?
- 5 增量预训练一般需要多大数据量?
- 6 增量预训练过程中,loss上升正常么?
- 7 增量预训练过程中,lr如何设置?
- 8 增量预训练过程中,warmup_ratio如何设置?
- 9 warmup的步数对大模型继续预训练是否有影响?
- 10 学习率大小对大模型继续预训练后上下游任务影响?
- 11 在初始预训练中使用Rewarmup对大模型继续预训练性能影响?
- 12 聊聊LLM预训练的基本原理
- 13 LLM预训练阶段有哪几个关键步骤?
1 为什么要增量预训练?
有一种观点,预训练学知识,指令微调学格式,强化学习对齐人类偏好,LIMA 等论文算是这一观点的证据。
所以要想大模型有领域知识,得增量预训练。(靠指令微调记知识不靠谱,不是几十万条数据能做到的。)
📝通俗解释:想象一下,预训练就像让一个小孩先上小学、中学、大学,系统性地学习各种知识;指令微调就像教他考试技巧和答题格式;而强化学习对齐人类偏好就像教他为人处世的方式。如果你想让模型成为某个领域的专家(比如医学、法律),就必须让它通过增量预训练去"上课学习",仅仅通过指令微调来"背答案"是行不通的。
2 进行增量预训练需要做哪些准备工作?
2.1 模型底座选型
主流是 LLaMA,因为 scaling 法则,可能 LLaMA 做了充分预训练。(当然有版权问题)
这里备选 BLOOM,感觉基座比 LLaMA 差,但是也有 7B 版本。
Falcon、CPM-bee、Aquila、Baichuan 待实验,license 友好,但生态和效果都是问题。其实,因为结构上都类似 LLaMA,未来估计会出现整合这些模型的项目。
📝通俗解释:选择模型底座就像选择建房子的地基。LLaMA 是目前最主流的选择,因为它验证了 scaling laws(缩放定律)——模型越大、训练数据越多,效果越好。其他模型虽然开源协议更友好,但效果和生态还在发展中。
(Falcon 公布的训练语料中没有中文)
这里没列 ChatGLM 和 ChatGLM2,因为有种说法在 SFT 模型上增量预训练效果比较差。(未证实)
2.2 数据收集
这里最经典的开源预训练数据还是 wudao 的 200G 和 the pile 这两个数据集(怀念一下 Open-Llama)
加起来有 1T 的文本量,足够前期玩耍了。
其实,刚开始实践的时候,不需要太多样本,先收集 GB 量级的领域文本跑通流程即可。
📝通俗解释:数据收集就像准备教材。WuDao 和 The Pile 是目前最常用的开源预训练数据集,相当于"教材库"。对于初学者来说,不需要一开始就收集海量数据,先用几个 GB 的领域文本把整个训练流程跑通才是最重要的。
2.3 数据清洗
当然这里数据治理可能是 chatgpt 魔法的最关键的部分,最基础的是把网页爬取数据中的广告清理掉。
Falcon 论文里介绍了数据清洗的手段,对于我们很有参考意义。
📝通俗解释:数据清洗就像给教材"去掉杂质"。网上爬取的数据就像从旧书堆里挑书,里面可能有广告、垃圾信息、无关内容等,需要通过规则过滤、模型识别等方式清理干净,否则模型会学到这些"坏习惯"。
3 增量预训练所用训练框架?
3.1 超大规模训练
如果是真大规模炼丹,那没什么好说的,直接 3D 并行。
Megatron-Deepspeed 拥有多个成功案例,炼 LLaMA 可以参考 LydiaXiaohongLi 大佬的实现。(实在太强)
炼 BLOOM 可以直接找到 Bigscience 的 git 仓库。
然而,转 checkpoint 还是挺费劲的。
📝通俗解释:3D 并行就像调动大规模生产线。需要同时使用数据并行(多个人同时做不同批次的数据)、流水线并行(不同人负责不同生产阶段)、张量并行(一个人同时处理多个任务)来加速训练。Megatron-Deepspeed 是目前最成熟的大规模训练框架。
3.2 少量节点训练
小门小户一共就几台机器几张卡的话,3D 并行有点屠龙术了。
张量并行只有在 nvlink 环境下才会起正向作用,但提升也不会太明显。
可以分 2 种情况:
单节点或者多节点(节点间通信快):直接 deepspeed ZeRO 吧。(笔者用了 linly 的增量预训练代码,但有能力的最好用其他代码)比如,Open-Llama 的 fork 版本。
多节点(但节点间通信慢):考虑用流水线并行,参考另一个大佬的实现。
📝通俗解释:如果只有几台机器,就不需要用"屠龙术"(3D并行)。ZeRO(零冗余优化器)是最常用的方案,它通过分片存储模型参数来节省显存。流水线并行适合机器之间网络连接较慢的情况,可以减少通信开销。
3.3 少量卡训练
如果资源特别少,显存怎么也不够,可以上 LoRA。
📝通俗解释:LoRA(低秩适配)是一种"省钱"的训练方式。它不直接修改原始模型的参数,而是添加少量"补丁"参数。这样可以用很少的显存微调大模型,虽然效果可能略差于全参数训练,但门槛低很多。
4 增量预训练训练流程是怎么样的?
4.1 数据预处理
参考 LLaMA 的预训练长度,也把数据处理成 2048 长度(如果不够,做 padding 补全)
📝通俗解释:将数据处理成固定长度(2048 tokens)是为了让模型能批量处理。就像把不同长度的句子截断或补齐到相同长度,方便一次性送入模型训练。
这里要吐槽,tencentpretrain 数据处理脚本的默认长度竟然是 128。
4.2 分词器
有很多工作加 LLaMA 中文词表,但是考虑到没有定论说加中文词表会更好,先用原版的吧,500k 的 tokenizer.model。
📝通俗解释:分词器(Tokenizer)就像把一句话拆成"单词"或"字"的工具。LLaMA 原版Tokenizer有50万个词表,虽然对中文支持一般,但目前没有明确证据证明增加中文词表效果更好,所以先用原版。
4.3 原始模型
可以使用一个中文增量预训练后的版本,当然这里坑挺大的,各家框架的模型层名不太一样。
为了快速跑通,用转换脚本快速转一下,能成功加载就行。
📝通俗解释:不同框架训练出来的模型,参数名称和存储格式可能不同。转换脚本就像"翻译器",把一种格式的模型转换成另一种格式,确保能正常加载使用。
4.4 训练参数
如果显存不够,可以 zero3+offload。其他参数暂时默认吧(事实上没有想象中慢)。
多机的话可以配一下 deepspeed 的 hostfile。
📝通俗解释:zero3+offload 是一种省显存的技术,把部分参数放到内存或硬盘上。DeepSpeed 的 hostfile 用于多台机器之间的通信配置。
4.5 观测训练进展
这一点可能是最重要的,跑通只是第一步,根据训练情况反复调整比较重要。
可以使用 wandb,记录 loss,flops,吞吐速度,已消耗的 token 数,和测试 ppl。
📝通俗解释:训练过程中需要"监控仪表盘"。wandb 是一个常用的监控工具,可以实时查看损失值(loss)、计算速度、token处理量等指标,就像开车的仪表盘一样重要。
4.6 模型转换
不同框架的 checkpoint 格式不同,还会根据并行度分成很多个文件。
以 ZeRO 为例,转换流程(很挫)是:
zerotof32f32tofp16fp16tohuggingface格式
📝通俗解释:模型转换就是"格式化"。不同训练框架保存的模型格式不同,需要一步步转换到常用的 HuggingFace 格式,才能被其他工具加载和使用。
4.7 模型测试
转为标准 huggingface 格式后可以用各种支持 llama 的前端加载,比如 text-generation-webui。
可以简单测试下续写能力,验证下模型是否正常。
至此,我们获得了 1 个增量预训练过的大模型基座。
📝通俗解释:模型测试就像"试驾"。转换成标准格式后,用文本生成界面测试一下模型的续写能力,看看它是否能正常输出内容、是否有语法错误等。
5 增量预训练一般需要多大数据量?
首先要确保你有足够大量的数据集,至少有几十亿(几B)的 token;否则几十条数据的情况更推荐做模型微调。
📝通俗解释:增量预训练需要大量数据,就像要成为某个领域的专家,需要读很多相关的书。如果数据太少(比如只有几十条),不如直接做模型微调(Fine-tuning),效果可能更好。
6 增量预训练过程中,loss上升正常么?
通常 增量预训练 开始的阶段会出现一段时间的 loss 上升,随后慢慢收敛。
📝通俗解释:训练初期 loss 上升就像"学新东西时会暂时忘记旧东西"。模型在学习新知识的过程中,可能会暂时"不适应",导致 loss 上升,这是正常现象,后续会慢慢收敛。
7 增量预训练过程中,lr如何设置?
学习率是一个很重要的参数,因为 lr 的大小会出现以下问题:
- 如果 lr 过大,那 loss 值收敛会更困难,旧能力损失的会更大;
- 如果 lr 过小,那可能难以学到新知识。
当你数据集比较小(例如 100B 以下),那建议使用较小的学习率。例如可以使用预训练阶段最大学习率的 10%。通常 7B 模型预训练阶段的学习率大概是 $3e-4$,所以我们可以选择 $3e-5$。
并且需要根据你的 batch size 做相应缩放。通常 lr 缩放倍数为 batch size 倍数的开方。例如 batch size 增大 4 倍,学习率对应扩大 2 倍即可。
📝通俗解释:学习率就像"步子的大小"。步子太大容易"扯到蛋"(学不会新知识,还会忘记旧知识),步子太小又跑得太慢(学不到东西)。通常增量预训练用原始学习率的十分之一比较安全。batch size 变大时,学习率也要相应增大,这样才能保持"步调一致"。
8 增量预训练过程中,warmup_ratio如何设置?
warmup_ratio 也很重要。通常 LLM 训练的 warmup_ratio 是 epoch * 1% 左右。例如预训练阶段一般只训一个 epoch,则 ratio 是 0.01;SFT 通常 3 个 epoch,ratio 对应为 0.03。
但是如果做增量预训练,建议 warmup_ratio 调大一点。如果你的数据集很大,有几百B,那 warmup 其实不影响最终模型效果。但通常我们的数据集不会有那么大,所以更小的 ratio 可以让模型"过渡"得更平滑。
学习率和 warmup_ratio 是两个相辅相成的概念,二者通常是成正比的关系。或者说如果你正在用一个较大的学习率,那你或许可以同时尝试增加 warmup 来防止模型"烂掉"。
📝通俗解释:warmup 就像"热身运动"。在正式训练前,先让学习率从很小慢慢升到最大值,让模型有个适应过程。如果学习率很大,热身时间也要长一点,否则模型可能会"受伤"(性能下降)。
9 warmup的步数对大模型继续预训练是否有影响?
- warmup 介绍:warmup 是一种微调中常用的策略,指学习率从一个很小的值慢慢上升到最大值;
- 对比实验设计:使用 4 种不同预热步数(eg: 0%, 0.5%, 1%, 2%)来进行实验
实验图表说明:
📝通俗解释:折线图展示了不同 warmup 比例对训练的影响。横轴是训练 token 数量,纵轴是验证集 loss(越低越好)。
图表分析:
- WU 0.0(无 warmup)在训练初期 Loss 下降非常迅速,但也表现出较大的不稳定性
- 其他三条带有 warmup 的曲线在初期 Loss 变化较平缓(甚至略有上升),随后逐渐下降
- 当 Tokens 超过 10B 后,所有曲线的走势趋于一致,Loss 均呈现缓慢下降趋势,最终收敛在 2.700 附近
实验结果:当模型经过「充分」训练后,不管多长的预热步数最后的性能都差不多。
📝通俗解释:实验结论是:只要训练得够久,不同 warmup 策略最终效果差不多。但如果在训练"不充分"的情况下(资源有限),更长的 warmup 能让模型在训练前期学得更好——下游任务学得快,上游知识忘得慢。
10 学习率大小对大模型继续预训练后上下游任务影响?
对比实验:使用了 4 种不同的最大学习率进行对比实验
实验结论:
- 经过充分训练后,学习率越大,下游性能最好,上游性能最差(忘得最多)
- 未经过预训练的模型无论是上游任务还是下游任务,都不如预训练过的模型效果
📝通俗解释:实验结论很有意思——大学习率能让模型更快学会新知识(下游任务好),但代价是忘记更多旧知识(上游任务差)。这就像让一个学生全力学习新科目,可能会忘记之前学过的内容。
注:前期训练,尽管大学习率在最后的 loss 是最低的,但在前期 loss 会增加的非常大,随后下降。
📝通俗解释:这提示我们,当资源不允许充分训练的情况下,较小的学习率和较长的 warmup 步数可能是一个更好的折中选择。
11 在初始预训练中使用Rewarmup对大模型继续预训练性能影响?
对比实验:不切换数据集,而是继续在之前的「预训练数据集(The Pile)」上继续训练
实验结果:无论使用多大学习率的 warmup 策略,效果都不如使用常量学习率。
这进一步证明,在原数据集上使用 warmup 接着训练会造成性能损伤,学习率越大则损伤越大,且这种损伤是无法在后续的训练中被找回的。
📝通俗解释:实验结论很关键——如果在原有数据上继续训练时使用 warmup(重新从低学习率开始),反而会让模型性能下降!学习率越大,损伤越大,而且这个损伤是"不可逆"的。
注:这提示我们,当预训练中遇到了训练中断需要继续训练时,我们应该在重新开始训练时将学习率恢复到中断之前的状态(无论是数值还是衰减率)。
📝通俗解释:这就像跑步中断后继续跑,应该保持原来的速度节奏,而不是重新热身从头开始。否则会"受伤"(损伤模型性能)。
12 聊聊LLM预训练的基本原理
大语言模型预训练采用了 Transformer 模型的解码器部分,由于没有编码器部分,大语言模型去掉了中间的与编码器交互的多头注意力层。
📝通俗解释:Transformer 模型就像一个"变形金刚",有编码器(Encoder)和解码器(Decoder)两部分。大语言模型只需要解码器,因为任务是"生成"下一个词,不需要"理解"输入后再"编码"。
大语言模型预训练是通过上文的词来预测下一个词,属于无监督的预训练。比如,给定一个无监督的语料 $U={u_1,...,u_n}$,而预训练语言模型是要使得下面式子最大化:
$$ L1(U) = \Sigma_i P(u_i \mid u_{i-k}, ..., u_{i-1}; \Theta) $$
即通过上文,来预测下一个单词,属于自回归模型,也叫做 AR 模型。
📝通俗解释:这个公式的意思是:给定前面的词,预测下一个词出现的概率。比如"今天天气真",模型会预测下一个词是"好"的概率最高。这就是所谓的"自回归"——利用自己预测的结果继续预测下一步。
AR 模型,即指从左往右学习的模型。AR 模型从上文学习,并将上一步的结果作为回归模型的输入,以预测下一个词。
在预测时,AR 模型只能看到上文的词,而无法知晓下文的词。AR 模型通常用于生成式任务,尤其是长文本的生成能力很强。
📝通俗解释:AR 模型就像一个"接龙"高手,只能看到前面的话来猜下一个词。这让它特别擅长写文章、做续写,但缺点是看不到"未来",无法根据后面的内容来修正当前预测。
在大语言模型的预训练中,还采用了 in-context learning 技术。为了让模型能够理解人类的意图,与人类的思想对齐,会构造类似这样数据:在句子前加上一个任务(task),同时会给出完成该任务的几个示例。
例如,向模型输入"请将中文翻译成英文。你好 Hello,再见,goodbye,销售,",然后让模型学习下一个输出"sell"。通过示例的个数又可以分为:
- few-shot learning: 允许输入数条示例和一则任务说明;
- one-shot learning: 只允许输入一条示例和一则任务说明;
- zero-shot learning: 不允许输入任何范例,只允许输入一则任务说明
zero-shot learning 可以表示为 $p(\text{output}|\text{input, task})$
通过引入 in-context learning 技术,使得预训练的大语言模型直接拥有完成特定任务的能力。
📝通俗解释:In-context learning(上下文学习)是 GPT 系列的"独门绝技"。它不需要重新训练模型,只需要给几个例子,模型就能理解任务并执行。比如不说"翻译"这个词,只给几个"中文→英文"的例子,模型就懂得了要翻译。
13 LLM预训练阶段有哪几个关键步骤?
大语言模型预训练是指采用大量数据喂入大规模模型去训练语言模型,得到初始化的模型参数。
随着 ChatGPT 的出现,在完成大语言模型的预训练后,还会采用监督学习、奖励模型以及强化学习进行进一步的微调,叫做 RLHF(基于人类反馈的强化学习)。
预训练后续阶段主要分为三个步骤:
步骤 1: SFT 监督微调(Supervised Fine-Tuning)
训练监督策略模型。在大语言模型的训练过程中,需要标注者参与监督过程。
- 从提示数据集中采样一个提示
- 标注者演示期望的输出行为
- 这些数据用于通过监督学习微调 GPT-3,得到 SFT 模型
📝通俗解释:SFT 就像"老师教学生"。找人类标注者写出理想的回答,然后用这些数据训练模型,让它学会"正确答案"是什么样的。
步骤 2: 奖励模型训练(Reward Model)
借助标注者的人工标注,训练出合意的奖励模型,为监督策略建立评价标准。
- 采样一个提示和几个模型输出
- 标注者对输出进行从最好到最差的排名
- 这些数据用于训练奖励模型,得到 RM 模型
📝通俗解释:RM 就像"打分评委"。让模型生成多个回答,人类排序哪个好哪个差,然后用这些数据训练一个"评分模型",这样就能自动判断回答的好坏。
步骤 3: PPO 强化学习模型训练(Proximal Policy Optimization)
采用近端策略优化进行强化学习。通过监督学习策略生成 PPO 模型,将最优结果用于优化和迭代原有的 PPO 模型参数。
- 从数据集中采样一个新的提示
- 策略生成一个输出
- 奖励模型计算该输出的奖励
- 该奖励用于使用 PPO 更新策略
📝通俗解释:PPO 就像"自我进化"。模型根据 RM 的评分来调整自己的输出策略,不断改进。这个过程可以循环多次,让模型越来越"聪明"。
总结
本文详细介绍了大模型增量预训练的完整流程,包括:
- 为什么需要增量预训练:为了让模型学习特定领域的知识
- 准备工作:选择模型底座、收集数据、数据清洗
- 训练框架:根据资源选择合适的并行策略和工具
- 训练流程:数据预处理→模型加载→训练→转换→测试
- 关键参数设置:学习率、warmup_ratio 的调整策略
- 实验结论:不同参数对上下游任务的影响
- 预训练原理:AR 模型、In-context Learning
- 后续微调:RLHF 的三个步骤(SFT→RM→PPO)
📝通俗理解:大模型增量预训练就像给一个已经读过很多书的人(基础模型)再上一门专业课。需要先选对教材(数据收集),用对学习方法(训练框架),注意学习节奏(学习率、warmup),最后还要检验学习效果(模型测试)。学完后如果还想进一步提升,还可以进行 RLHF 微调。