本文主要介绍LLM预训练相关的笔记
- 参考链接
- [如何从零开始训练大模型(minicpm分享&讨论)](https : //zhuanlan.zhihu.com/p/686664720):minicpm模型训练分享
- [LLM训练-Pretrain](https : //zhuanlan.zhihu.com/p/718354385):非常详尽的一些实操笔记和思考,论文的许多笔记是参考了这篇博客
- [花费千万试出来的LLM预训练经验](https : //mp.weixin.qq.com/s/MF6MuZC_fvKu25S1MzXkCQ)
预训练的重要性
- 预训练阶段是知识注入的关键阶段
- 已有研究基本都证明了,预训练阶段是知识注入阶段,后续的 post-training 阶段主要是激发模型的能力
预训练一个大模型有哪些需要关注的点?
数据爬取和解析
- 数据需要上 T,甚至几十 T 才够用
- 爬虫不好做,容易被封 IP
- 很多论文是 PDF,使用 Python 解析可能不准确,使用 GPT4 等解析成本较高
- 最好多找开源的数据
数据清洗、去重、配比
- 清洗很重要
- 需要自己训练打分器,最好是使用 BERT 系列模型,而不是 Decoder-Only 模型训练打分器,分类器的 label 可以使用 GPT4 标注,或者按照优质源与劣质源作为正负label标记
需要注意的是,基本上大家都认同:同等 size 下,BERT 结构的模型的表征能力是强于 transformer-decoder 模型的,因此打分模型最好还是从 BERT 家族中选一个来训,效果好、速度还快
- 除了打分器,规则也很重要
- 需要做好数据脱敏,避免人名等隐私被侵犯出来
- 数据去重很重要,网页互相引用会造成爬取到的数据重复性太高,做不了 sentence 粒度的,就做 document 粒度的
- 可以训练一个文档分类器来对文档进行分类,不同类别使用不同的相似度阈值去重
- 数据配比一般是 中 : 英 : code = 4 : 4 : 2
数据顺序
- 同样大小的数据,按照不同顺序输入模型,结果也会不同,基本上可以类似课程学习的思想,想简单后复杂,先优质再劣质等
- 不同文档的句子之间应该互相看见吗?llama3.1 强调了不能看见,但是作者理解看见其实也还好
流水化数据线
- 数据需要提前 tokenization
- 训练和数据处理应该是两个进程
- 训练过程中多存 save_checkpoint,为了训练时决定是否即时保存,可以使用一些规则,比如“遇到存在 save 文件的文件夹就保存一下”
数据实验
- 训练前可以先用小模型验证一下,如何设置数据配比,顺序更合适
模型结构
- RoPE + GQA + RMS_Norm + SwiGLU
- 预训练不建议创新,试错成本太高,一般来说照抄开源的优秀的技术报告即可
模型大小
- 按照合适来选择,可以通过时间和数据来评估自己需要多少参数量的模型
- layer_num 和 hidden_size 同步增加或者减少更好些
- seq_len 不要上来就很大,RoPE 的 NTK 外推方法已经是各大厂标配的方案:4K/8K + RoPE 小 Base + 90% 数据量 –> 32K/64K + RoPE 大 Base + 10% 数据量
训练框架
- Megatron 和 DeepSpeed之间选:
Megatron 和 DeepSpeed 该怎么选?直接说结论:从零开始的 Pretrain 必须选 Megatron,Continue-Pretrain 可以考虑使用 DeepSpeed, 换句话说,T 级别的 token 训练量必须是 Megatron,B 的级别 token 训练量无所谓
- DeepSpeed 加载速度慢
- 其他:
无论是用哪个训练框架,都要记得把 attention 的默认方式换成 flash_attention
训练时评估
- loss 分不同种类观察,即 channel_loss,比如英文、中文、代码分开观察
训练后评估
- 可以使用 ACC 来衡量评估结果
概率探针评估
- 可以用于查看某个目标条件概率是否在增大
一个特别干货的分享
- 参考链接:[如何从零开始训练大模型(minicpm分享&讨论)](https : //zhuanlan.zhihu.com/p/686664720), 这个博客分享了包含了一些地数据集处理、清洗等
- 文中很有意思的一段话
但我们回到2020年,当大部分人都在基于 bert 做各种魔改的时候
OpenAI 发现了这么一个规律。数据,训练,参数一直增长下去,好像 loss 的确是在不断的下降哎?
于是,他们拿着这个 paper 去问微软的 CTO,你想不想看看这个 loss 下降到一定程度会发生什么?
会发生什么?
chatgpt 就出来了
LLM 预训练实战经验
- 以下内容参考自:[花费千万试出来的LLM预训练经验](https : //mp.weixin.qq.com/s/MF6MuZC_fvKu25S1MzXkCQ)
随机初始化的痛点
- 训练成本高 :早期使用 Qwen1.5-0.5B 结构,训练 8T+token 通用数据仅达勉强效果,相比 1-2T 训练量提升有限
- 核心问题 :能否复用已有模型?直接续训开源模型存在两大问题:
- 参数量不匹配(如业务需要 3B 模型,开源仅有 7B/4B/1.5B,则还是需要重头训练)
- 版权风险(如 Qwen2.5-4B 无商用许可),注:Qwen 的同一系列不同模型的开源许可也可能不同
模型初始化:大模型 to 小模型
- 适用场景 :当拥有可商用大模型(如14B),需初始化小模型(如3B)
- 主流方法对比 :
方法 核心原理 数据要求 初始化效果 限制条件 Sheared LLaMA 训练mask筛选重要参数 几B-几十B高质量数据(如代码/数学) 初始loss更低,几十步收敛至2.x 模块类型不可改(激活函数/attention类型固定) Weight Subcloning 计算神经元重要度裁剪 需输入数据获取激活值 后期loss略低,评测效果持平 同上 - 实践效果 :14B -> 3B 裁剪可行,结合蒸馏后 500B token 可达原 8T 效果
- 关键结论 :0.5B-72B 范围内,已有模型初始化效果优于随机初始化
模型初始化:小模型 to 大模型
- 代表方法 :Bert2BERT、Llama Pro
- 适用场景 :封闭域对话能力提升,训练数据充足
- 效果预期 :仅能带来1-2个点的提升,不适合大规模预训练
模型初始化:Dense to Sparse(MoE模型)
- 初始化挑战 :随机初始化易出现 loss spike,需 50k+step 恢复
- 理解:“loss spike”(损失激增)是指模型的损失函数值在训练过程中出现突然且显著的上升现象
- Sparse Upcycling 方案 :
- 1)用同结构 Dense 模型通过 FFN 复制生成 MoE
- 2)关键操作:
- 裁剪前打乱 neuron 顺序打破专家对称性
- 保留 50%-70% 原 FFN 参数,其余随机初始化
- 3)优化技巧:全单精度训练可提升稳定性,但 GPU 利用率 < 50%
通用预训练数据准备
基础清洗
- 清洗原则 :数据量充足时可严格筛选
- 具体规则 :
- 过滤 ppl 异常、格式混乱(多分行/短词)、长度过短数据
- 排除 url、安全词、重复内容(防 LLM 复读)
- 结合 fasttext 二分类模型筛除低质量数据
- 辅助工具 :
- 人工打标 + FastText 二分类模型筛选低质量数据
- 参考 Llama3.1 和 Qwen2 技术报告的清洗流程
去重
- 技术方案 :minhash 实现文章/段落粒度去重
- 执行原则 :宁杀错不放过,重复数据严重影响模型能力(重复数据会导致模型 “记忆偏差”)
- 理解:目前数据量已经很大了,可以多删除一些,对于数据量不大的场景,还是要小心错杀现象
分类与配比
- 数据类型 :代码、数学、高教育性数据(如 chinese-fineweb-edu )、通用数据(体育/音乐/时政等)
- 经验配比 :提高 education score、代码、数学数据比例,无需过度纠结具体数值(如 30% vs 40%)
- 关键逻辑 :通用数据先夯实语言基础,再切入专业领域数据
长文本预训练数据被准
- 数据要求 :几B-几十B 即可
- 质量排序 :
- 1)天然长文本(大学课本、GitHub 项目)【效果最好】
- 2)相关文档拼接(如带 reference 的论文)【效果次之】
- 3)无关文档拼接(仅训练位置编码)【这个方法效果不好,不建议使用】
- 注意事项 :避免领域分布集中(避免数据 Bias),构造阅读理解类长文本效果有限
退火阶段数据准备
合成数据核心原则
多样性优先 :
- 方法1:调整解码参数(温度/top k/top p)
- 方法2:Prompt 注入随机变量(如腾讯 Persona Hub 的 10亿 人物描述)
- 示例:生成数学题时,在 Prompt 中加入不同人物背景描述
1
2
3
4
5
6
7
8
9# 数学题生成示例
prompt = """
根据以下人物描述生成生活场景数学题:{persona}
"""
persona_list = [
"23岁卡车司机,身高178cm,单身,爱吃海鲜...",
"北京化学家小A,本科就读于...",
# 更多个性化描述
]
质量保障 :
- 模型规模:越大越好(专用模型 > 通用模型)
- 质量评估:LLM-as-judge 打分、代码可执行性验证(如 OpenAI 工具)
数据类型与来源
- 推理能力 :数学/代码数据(大量合成)
- 知识储备 :educational data(学科试题/教科书)
- 语言能力 :高质量网页数据(严格阈值筛选)
训练优化策略-蒸馏策略
- 适用场景 :大模型初始化的小模型训练
- 实施要点 :
- teacher 模型与初始化大模型同系列
- 温度策略:先高后低(前期广覆盖,后期精收敛)
- 效率优势 :训练 token 数可减少至直接训练的 10% 以下
超参迁移优化-MuP参数化
- MuP,即 Maximal Update Parameterization
- 核心价值 :
- 设计模型超参实现大小模型 LR/BS 通用
- 小模型调参与大模型训练超参一致性强
- 实践应用 :
- 小模型(如 10B 数据)网格搜索调参,直接迁移至大模型
- 搜参过程中关注 loss 下降速度而非绝对数值
学习率策略-WSD vs Cosine
- Cosine 衰减(余弦衰减) :
- 需预先设定总步数,收敛效果更稳定
- WSD(Warmup-Stable-Decay)学习率调度 :
- 分为预热阶段、稳定阶段和衰减阶段
- 优势:灵活调整阶段,适合实验场景,无需提前设定总步数
- 虽然平时也常将预热阶段设置为总步数的一定百分比,但也可以设定为固定值,且稳定阶段的步数一般没有特定要求
- 劣势:同 token 数下效果不如 Cosine(需足够长 Decay 阶段 + 低最终 LR)
多阶段退火训练(提升效果的核心模块)
Step1:学科能力提升
- 数据比例:教材 30%+合成选择题 50%+通用选择题 10%+通用数据 10%
- 关键参数:LR = 3e-4,训练量 120B+ token(最佳 checkpoint 在几十 B 时达成)
- 效果:MMLU/Ceval 超越 Qwen 官方模型
Step2:加入数学数据
- 数据比例:学科 40% : 数学 60%
- 关键发现:
- LR = 8e-5 时,效果优于 1e-4
- 数学数据超过 60% 会导致学科能力下降
- 效果:Ceval比基线高6分,学科能力稳定
Step3:加入代码数据
- 数据比例:学科 20% : 数学 40% : 代码 40%
- 关键参数:LR = 5e-5,训练量几十B token
- 代码和数学关联效应:数学与代码能力正相关,无需过高代码比例
Step4:综合能力提升
- 数据比例:学科15% : 数学 25% : 代码 25% : 通用 10% : SFT 30%
- 关键参数:LR = 3e-5 衰减至0 ,训练量几十B token
- 训练目标:
- 保持语言能力 + 引入 SFT 数据(如 Tool Use 的 function call)
- 数据特性:加入 Tool Use 等 SFT 数据
关键原则
- 数据不重复使用,预留充足退火数据
- 小阶段训练顺序:学科 > 数学 > 代码 > 通用(按最佳学习率排序)
- 单一数据训练时需优化内部配比(如代码数据中 Python 占比、GitHub 项目比例等)
Batch 内数据分配
- 实时跟踪各类数据 token 数,严格按预定比例混合
- 避免某类数据在 batch 中占比波动过大
评测数据集
- 通用能力:opencompass(代码/数学/语言/知识)
- 下游任务:业务相关数据集(如 Tool Use 评测集)
评测结果分析经验
- loss 与效果关系 :loss 低不一定效果好,但 loss 高效果一定差
- 通用与下游平衡 :两者指标并非总是正相关,需针对性优化