大模型(LLMs)增量预训练篇
1. 为什么要增量预训练?
增量预训练的目的是使大模型获得更多的领域知识,而不是仅依赖于指令微调学习格式。通过增量预训练,大模型可以更好地在特定领域进行推理和生成。LIMA等论文表明,靠指令微调来学习知识是不可靠的,尤其是当训练数据量不足时,增量预训练能够有效填补这一空白。
2. 进行增量预训练需要做哪些准备工作?
模型底座选型
主流的模型基座是LLaMA,因为其在预训练时遵循了Scaling法则,预训练效果较好。其他备选模型包括BLOOM(但效果稍差)、Falcon、CPM-bee、Aquila、Baichuan等,这些模型在版权和许可上较为友好,尽管它们在生态和效果上有待考察。
数据收集
最经典的开源数据集包括Wudao的200G和ThePile,合起来约1T文本量,适合用来进行初期的增量预训练。如果刚开始实践,可以先收集GB量级的领域文本进行实验。
数据清洗
数据治理是增量预训练中的关键部分。最基础的清洗任务包括去除网页爬取数据中的广告,此外可以参考Falcon论文中的数据清洗方法。
3. 增量预训练所用训练框架?
超大规模训练
对于大规模训练,可以使用3D并行化方案,例如Megatron-Deepspeed,这已经有多个成功案例。LLaMA的训练可以参考LydiaXiaohongLi大佬的实现。
少量节点训练
对于资源有限的小规模训练,3D并行可能不太适用,但可以采用Deepspeed ZeRO,尤其适合在单节点或多节点环境下运行。如果是多节点环境且节点间通信较快,可以直接使用Deepspeed ZeRO。
少量卡训练
对于显存不足的情况,可以使用LoRA(Low-Rank Adaptation),它能有效减少显存占用,适合显存较小的硬件。
4. 增量预训练训练流程是怎么样?
数据预处理
将训练数据处理成符合预训练长度的格式,参考LLaMA的预训练长度,通常是2048。如果数据不够长,可以进行补全。
分词器
在分词器方面,可以参考LLaMA的中文词表,尽管目前没有定论说明增加中文词表会更好,建议先使用原版词表(500k的tokenizer.model)。
原始模型
可以使用已经增量预训练过的中文版本模型。由于不同框架的模型层名称可能不同,需要进行模型转换以适应新的框架。
训练参数
如果显存不足,可以使用zero3+offload来减轻负担。训练过程中,参数可以适当调整,通常采用默认设置即可。对于多机训练,可以通过Deepspeed的hostfile进行配置。
观测训练进展
监控训练进度非常重要。可以使用wandb来记录训练的loss、flops、吞吐速度、已消耗的token数和测试ppl等信息。
模型转换
训练完成后,模型需要进行转换以适配不同框架。以ZeRO为例,转换流程如下:
- 从ZeRO格式转换到F32格式
- 从F32转换到FP16格式
- 从FP16转换到HuggingFace格式
模型测试
将模型转换为HuggingFace格式后,可以使用支持LLaMA的前端工具(如text-generation-webui)进行简单的生成测试,验证模型的正常运行。
5. 增量预训练一般需要多大数据量?
增量预训练所需的数据量通常取决于预训练任务的目标。经典的开源数据集如Wudao(200G)和ThePile(1T)已经足够进行初期的增量预训练,但对于更复杂的应用,可能需要更大的数据集。
6. 增量预训练过程中,loss上升正常么?
在增量预训练过程中,loss上升是可能出现的情况,尤其是在模型调整阶段。如果模型在某些训练阶段无法收敛,可能会导致loss上升。需要根据训练进展及时调整参数。
7. 增量预训练过程中,lr如何设置?
学习率(lr)的设置对增量预训练至关重要。通常,初始学习率设置较低,在训练过程中逐渐增加,避免初期震荡。建议根据训练数据和模型规模进行调试,适当调整lr。
8. 增量预训练过程中,warmup_ratio如何设置?
warmup_ratio通常设置在0.1到0.2之间。具体数值根据模型的规模、训练数据以及计算资源的不同可以做适当的调整。
9. warmup的步数对大模型继续预训练是否有影响?
warmup的步数对大模型的预训练有较大影响,合理的warmup能够帮助模型更平稳地进入训练阶段,减少训练初期的震荡。过短的warmup步数可能导致训练不稳定。
10. 学习率大小对大模型继续预训练后上下游任务影响?
学习率的大小直接影响大模型的预训练效果。较大的学习率可能导致训练不稳定,而较小的学习率可能使模型收敛缓慢。合理的学习率可以加速模型训练并提高其在下游任务中的表现。
11. 在初始预训练中使用Rewarmup对大模型继续预训练性能影响?
Rewarmup可以帮助模型更好地适应新的训练数据和任务。对于大模型,Rewarmup可以提高其训练稳定性和精度,有助于在增量预训练时保持较好的性能。
5. 增量预训练一般需要多大数据量?
首先要确保你有足够大量的数据集,至少有几 B 的 token;否则几十条数据的情况我更推荐模型微调。
6. 增量预训练过程中,loss 上升正常么?
通常增量预训练开始的阶段会出现一段时间的 loss 上升,随后慢慢收敛。
7. 增量预训练过程中,lr 如何设置?
学习率是一个很重要的参数,因为 lr 的大小会出现以下问题:
- 如果 lr 过大,那 loss 值收敛会更困难,旧能力损失的会更大;
- 如果 lr 过小,那可能难以学到新知识。
当你数据集比较小(例如 100B 以下?),那建议使用较小的学习率。例如可以使用 pre-train 阶段最大学习率的 10%。通常 7B 模型 pre-train 阶段的学习率大概是 3e-4,所以我们可以选择 3e-5。
并且需要根据你的 batch size 做相应缩放。通常 lr 缩放倍数为 batch size 倍数的开方。例如 batch size 增大 4 倍,学习率对应扩大 2 倍即可。
8. 增量预训练过程中,warmup_ratio 如何设置?
warmup_ratio 也很重要。通常 LLM 训练的 warmup_ratio 是 epoch * 1% 左右。例如 pre-train 阶段一般只训一个 epoch,则 ratio 是 0.01;SFT 通常 3 个 epoch,ratio 对应为 0.03。
但是如果做 CPT,建议 warmup_ratio 调大一点。如果你的数据集很大,有几百 B,那 warmup 其实不影响最重的模型效果。但通常我们的数据集不会有那么大,所以更小的 ratio 可以让模型“过渡”得更平滑。
学习率和 warmup_ratio 是两个相辅相成的概念,二者通常是成正比的关系。或者说如果你正在用一个较大的学习率,那你或许可以同时尝试增加 warmup 来防止模型“烂掉”。
9. warmup 的步数对大模型继续预训练是否有影响?
warmup 介绍:warmup 是一种 finetune 中常用的策略,指学习率从一个很小的值慢慢上升到最大值;
对比实验设计:使用不同 4 种不同预热步数(eg:0%, 0.5%, 1%, 2%)来进行实验。
不同预热百分比步数的性能图,上图为下游任务 loss,下图为上游任务 loss。
实验结果:当模型经过「充分」训练后,不管多长的预热步数最后的性能都差不多。
注:但,这种前提是「充分训练」,如果只看训练前期的话,使用更长的预热步数(黄色的线),无论是「上游任务」还是「下游任务」,模型的 Loss 都要比其他预热步数要低(下游学的快,上游忘的慢)。
10. 学习率大小对大模型继续预训练后上下游任务影响?
对比实验:使用了 4 种不同的最大学习率进行对比实验。
实验结论:
经过充分训练后,学习率越大(紫色),下游性能最好,上游性能最差(忘得最多)。
未经过预训练的模型(蓝色)无论是上游任务还是下游任务,都不如预训练过的模型效果。
注:前期训练,尽管紫色线条在最后的 loss 是最低的,但在前期 loss 会增加的非常大,随后下降。
解释一下这里为什么这么关注训练前期,是因为在真实训练中,我们可能不一定会增强图中所示的 250B 这么多的 tokens,尤其是在模型参数很大的情况中。所以,当资源不允许充分训练的情况下,较小的学习率和较长的 warmup 步数可能是一个不错的选择。
11. 在初始预训练中使用 Rewarmup 对大模型继续预训练性能影响?
对比实验:不切换数据集,而是继续在之前的「预训练数据集(The Pile)」上继续训练:
实验结果:无论使用多大学习率的 warmup 策略,效果都不如使用常量学习率。
这进一步证明,在原数据集上使用 warmup 接着训练会造成性能损伤,学习率越大则损伤越大,且这种损伤是无法在后续的训练中被找回的。
注:PS:这里提示我们,当预训练中遇到了训练中断需要继续训练时,我们应该在重新开始训练时将学习率恢复到中断之前的状态(无论是数值还是衰减率)。