☰
LLM预训练训练计划设计指南:数据配比、学习率调度与显存优化
2026/10/13 15:35:48 网站建设 项目流程

1. 预训练训练计划到底在规划什么

很多人第一次接触大模型训练,注意力都放在模型结构、参数量、注意力机制这些"看得见"的东西上,但真正决定一个模型能不能训出来、训得好不好的,往往是那份看起来最枯燥的训练计划。我接触过几个从零预训练的小团队,踩的最大的坑不是代码写错了,而是训练计划没设计好——要么学习率曲线设得离谱导致loss震荡不收敛,要么batch size和序列长度配比失衡导致显存爆掉或者吞吐低得可怜,要么数据配比没想清楚导致模型偏科严重。

所谓训练计划,说白了就是回答几个问题:用多少数据、按什么顺序喂、学习率怎么变、batch怎么组、训练多久停、中间怎么存。这几个问题看起来简单,但每一个背后都有一堆权衡。这篇文章我就把预训练阶段训练计划的完整设计思路拆开讲,从数据配比到学习率调度,从batch组织到checkpoint策略,尽量把"为什么这么设"讲透,让你看完能自己动手排一份靠谱的训练计划。

适合读这篇的人:正在做或者准备做LLM预训练的工程师、想理解大模型训练全流程的算法同学、以及需要评估训练成本和时间的技术负责人。不需要你有分布式训练的经验,但最好对Transformer和梯度下降有基本概念。

2. 训练计划的核心组成与设计逻辑

2.1 训练计划包含哪些关键要素

一份完整的预训练训练计划,我习惯把它拆成六个模块来看,每个模块都有独立的决策点,但又互相牵制:

  • 数据计划:总token预算、数据来源配比、数据顺序、重复策略
  • 优化计划:优化器选择、学习率峰值、warmup步数、衰减策略、权重衰减、梯度裁剪
  • 批次计划:全局batch size、单卡micro batch、梯度累积步数、序列长度
  • 并行计划:数据并行、张量并行、流水线并行的切分方式
  • 检查点计划:保存频率、保留策略、断点续训机制
  • 停止计划:总步数、验证指标、早停条件

这六个模块不是孤立的。比如你增大了序列长度,显存占用上去了,就得减小micro batch,那为了维持全局batch size不变,梯度累积步数就得增加,训练总步数也会跟着变,学习率调度曲线也得重新算。所以训练计划是一个联立方程,改一个参数往往要动一串。

2.2 为什么训练计划比模型结构更影响成败

我见过太多案例,模型结构照搬公开论文,参数量、层数、头数都对齐,结果训出来的模型就是不如人家。问题往往出在训练计划上。模型结构决定了"能力上限",训练计划决定了"你能不能摸到这个上限"。

打个比方,模型结构像是给了一个运动员的身体素质,训练计划就是他的训练方案。身体素质再好,训练方案瞎搞——今天练马拉松明天练举重,强度忽高忽低——照样出不了成绩。LLM预训练里,学习率调度就是那个"训练强度曲线",数据配比就是"训练科目安排",两者配合不好,模型要么学偏要么学废。

更现实的一点是,模型结构一旦定了基本不动,但训练计划在整个训练过程中是可以动态调整的。很多团队在训练中途发现loss异常,第一反应是改训练计划而不是改结构,因为改结构意味着从头再来,成本太高。

2.3 训练计划设计的三条底层原则

在展开细节之前,先把三条我总结的底层原则摆出来,后面所有具体决策都围绕它们:

第一,稳定性优先于速度。预训练动辄几周甚至几个月,中途崩一次可能损失几天算力。所以学习率峰值宁可保守一点,warmup宁可长一点,梯度裁剪宁可严一点。快那一点点收敛速度,不值得冒训练发散的风险。

第二,显存和吞吐要平衡。显存用满不代表效率高,micro batch太小会导致GPU利用率上不去,太大又会OOM。找到那个"显存占用85%左右、吞吐接近峰值"的甜点区,比一味追求大batch更有意义。

第三,可恢复性是一等公民。训练计划里必须包含完整的断点续训设计,包括优化器状态、数据加载器位置、随机种子、学习率调度器状态。我吃过亏,有一次checkpoint只存了模型权重没存优化器状态,续训之后loss直接跳了一截,白跑了两天。

3. 数据计划:token预算与配比怎么定

3.1 总token预算的估算方法

总token预算决定了训练规模,业界有个经验公式叫Chinchilla最优,大致是参数量和训练token数按1:20配比。也就是说一个10B参数的模型,理想训练token数在200B左右。但这个比例不是铁律,实际中要看你的目标——如果追求推理时的极致性能,可以训更多token(比如1:100甚至更高),代价是训练成本线性增长。

估算token预算的实操步骤:

  1. 确定模型参数量N(比如7B)
  2. 按目标比例确定token数T(比如按1:20,T=140B)
  3. 估算单步处理的token数:全局batch size × 序列长度
  4. 计算总步数:T ÷ 单步token数
  5. 结合吞吐估算总时间,判断是否可接受

举个例子,7B模型,全局batch size设为4M token(约2000条2048长度的序列),那总步数就是140B ÷ 4M = 35000步。如果实测吞吐是每秒处理15000 token,那总时间约140B ÷ 15000 ≈ 259万秒 ≈ 30天。这个数字一出来,你就知道要不要调整预算了。

注意:token预算不是越多越好。超过某个点之后,模型性能提升会明显放缓,而成本是线性的。我建议先用小规模实验跑出loss曲线,找到边际收益开始下降的拐点,再决定最终预算。

3.2 数据来源配比的设计思路

预训练数据通常来自多个来源:网页文本、书籍、代码、学术论文、对话数据等。配比直接决定模型的能力偏向。配比设计没有标准答案,但有几条经验:

  • 网页文本是主力,通常占60%-80%,提供广度和多样性
  • 高质量书籍和论文占10%-20%,提升深度和逻辑性
  • 代码数据占5%-15%,增强推理和结构化能力
  • 对话数据占比不宜过高,预训练阶段太多对话数据会让模型过早"对话化",影响通用能力

配比的核心矛盾是广度vs深度。网页数据广度够但噪声大,书籍数据质量高但覆盖窄。我的做法是分阶段调整配比:训练前期多用网页数据打基础,后期提高高质量数据比例做"精修"。这种数据课程学习的思路,实测比固定配比效果好。

3.3 数据顺序与重复策略

数据顺序影响训练动态。如果前期就喂大量高质量数据,模型可能过早收敛到局部最优;如果一直喂噪声数据,模型学不到精细模式。常见策略是从易到难、从粗到精。

重复策略要谨慎。同一份数据重复训练超过4轮(epoch),模型容易过拟合,表现为训练loss继续降但验证loss回升。如果token预算不够而数据有限,宁可减小模型规模也不要过度重复。我见过为了凑token预算把数据重复8轮的,结果模型在验证集上表现还不如重复2轮的。

4. 优化计划:学习率调度是灵魂

4.1 优化器选择与超参基线

预训练主流用AdamW,少数场景用Lion或Sophia。AdamW的默认超参基线:

超参典型值说明
beta10.9一阶矩估计衰减
beta20.95二阶矩估计衰减,比CV任务常用的0.999更激进
eps1e-8数值稳定项
weight decay0.1权重衰减,防止过拟合
grad clip1.0梯度裁剪阈值

beta2设0.95而不是0.999,是因为LLM训练中梯度方差较大,0.999会让二阶矩估计滞后太多,导致有效学习率偏低。这个细节很多教程不讲,但实测影响不小。

4.2 学习率峰值与warmup

学习率峰值通常在1e-4到3e-4之间,具体取决于模型规模和batch size。经验规则:batch size越大,学习率可以越大。有个粗略的线性缩放规则——batch size翻倍,学习率也翻倍,但超过某个点后要开方缩放。

warmup步数一般占总步数的0.5%-2%。warmup的作用是让模型在训练初期慢慢适应,避免一开始就用大学习率把参数打飞。warmup太短容易初期震荡,太长浪费训练步数。我一般设总步数的1%作为warmup。

4.3 衰减策略的选择与对比

衰减策略决定了学习率从峰值怎么降下来,常见的有三种:

  • 余弦衰减:从峰值按余弦曲线降到接近0,平滑,适合大多数场景
  • 线性衰减:从峰值线性降到0,简单,但后期学习率下降太快
  • 逆平方根衰减:按步数的逆平方根衰减,适合超长训练

余弦衰减是我最常用的,因为它前期降得慢、后期降得快,符合"先探索后收敛"的直觉。具体公式是:

lr(t) = lr_min + 0.5 * (lr_max - lr_min) * (1 + cos(pi * t / T))

其中t是当前步数,T是总步数,lr_min通常设为峰值的10%左右,不设0是为了避免训练末期完全停滞。

实操心得:如果训练中途要调整总步数(比如发现loss还没收敛想多训一会),余弦衰减的曲线要重新算。我建议一开始就把总步数设得略大于预期,留出调整空间,而不是训到一半临时改。

4.4 梯度裁剪与数值稳定性

梯度裁剪阈值一般设1.0,意思是把梯度向量的L2范数限制在1.0以内。这个操作能有效防止梯度爆炸,尤其在训练初期。但阈值设太小会拖慢收敛,设太大又起不到保护作用。1.0是个经过大量实践验证的平衡点。

除了梯度裁剪,还要监控loss scale(如果用了混合精度)。混合精度训练中,梯度可能下溢成0,需要用动态loss scale来放大。如果发现loss scale频繁降到最低值,说明数值不稳定,要检查学习率是不是太大了。

5. 批次计划:显存与吞吐的平衡术

5.1 全局batch size的确定

全局batch size影响训练稳定性和收敛速度。太小会导致梯度噪声大、训练不稳;太大则泛化性可能下降,且显存吃不消。LLM预训练的全局batch size通常在1M到4M token之间。

确定方法:先在小规模上试,找到"loss曲线最平滑"的batch size。我一般从1M token起步,如果loss震荡明显就加倍,如果显存不够就减半。注意这里说的是token数不是序列数,因为序列长度会变。

5.2 micro batch与梯度累积的配合

单卡显存放不下全局batch,就要靠梯度累积。计算关系是:

全局batch token数 = micro_batch_size × seq_len × 数据并行度 × 梯度累积步数

比如全局要4M token,序列长度2048,数据并行度8,那micro_batch_size × 梯度累积步数 = 4M ÷ (2048 × 8) ≈ 244。如果micro_batch_size设4,梯度累积步数就是61。

micro_batch_size的选择要看显存。一般从2或4起步,逐步往上加直到显存占用到85%左右。梯度累积步数则是凑数用的,不影响显存但影响训练速度——步数越多,每步之间的空闲时间越长。

5.3 序列长度与打包策略

序列长度直接影响显存和计算量,因为注意力机制是O(n²)复杂度。常见长度有2048、4096、8192。长度翻倍,显存占用大约翻四倍(注意力部分)。

为了不浪费padding,实践中用序列打包:把多条短序列拼成一条长序列,用attention mask隔开。这样能把GPU利用率从50%左右提到80%以上。打包的难点是mask的正确构造,搞错了会导致跨序列注意力泄漏,模型学到错误关联。

踩过的坑:有一次打包时mask写错了,模型在验证集上表现异常好,排查半天才发现是数据泄漏——模型能看到"未来"的token。所以打包后一定要做mask的单元测试。

6. 并行计划与检查点策略

6.1 并行方式的组合选择

单卡放不下模型时,要用并行。三种主要方式:

  • 数据并行:每卡一份完整模型,处理不同数据,梯度同步。适合模型能单卡放下时
  • 张量并行:把单层内的矩阵切分到多卡,适合单层太大时
  • 流水线并行:把不同层分到不同卡,适合层数多时

实际中常组合使用,比如"数据并行×张量并行×流水线并行"。组合方式取决于模型规模和集群拓扑。我的经验是:优先用数据并行,不够再叠张量并行,最后才上流水线并行,因为流水线并行的气泡(bubble)会浪费算力。

6.2 检查点保存与断点续训

检查点要保存的不只是模型权重,还包括:

  • 优化器状态(AdamW的momentum和variance)
  • 学习率调度器状态
  • 数据加载器位置(当前epoch和batch索引)
  • 随机数生成器状态
  • 梯度累积的中间状态

保存频率一般每几百到几千步一次。太频繁拖慢训练,太稀疏崩了损失大。我一般设每1000步存一次,同时保留最近3个checkpoint加一个"最佳"checkpoint。

断点续训的验证方法:存完checkpoint后立刻重启一次,确认loss能从断点平滑接上。这个测试很多人省了,结果真崩的时候才发现续训有问题。

6.3 训练监控与异常处理

训练过程中要盯几个关键指标:

指标正常表现异常信号
训练loss平滑下降突然飙升或变NaN
验证loss跟随训练loss下降回升(过拟合)
梯度范数稳定在裁剪阈值附近持续为0或爆炸
学习率按调度曲线变化卡住不动
吞吐稳定突然下降(可能OOM)

loss变NaN是最常见的异常,原因通常是学习率太大、数据有脏样本、或者混合精度溢出。排查顺序:先降学习率,再查数据,最后查数值精度设置。

7. 常见问题与排查技巧实录

7.1 训练不收敛的排查清单

遇到loss不降或震荡,按这个顺序排查:

  1. 学习率:是不是太大了?先降10倍试试
  2. warmup:是不是太短了?加长到总步数的2%
  3. 数据:有没有脏数据、重复数据、格式错误?
  4. 初始化:参数初始化是不是有问题?检查std是否合理
  5. 梯度:梯度范数是不是异常?开梯度裁剪
  6. batch size:是不是太小导致噪声大?适当增大

我遇到过一次loss死活不降,最后发现是数据里混了一批空文本,模型一直在学"预测空"。所以数据清洗这步不能省。

7.2 显存溢出的解决路径

OOM是预训练最常见的报错。解决路径按优先级:

  • 减小micro batch size
  • 开启梯度检查点(用时间换显存)
  • 开启混合精度(fp16或bf16)
  • 减小序列长度
  • 增加并行度(张量并行或流水线并行)
  • 使用更省显存的优化器(如8-bit Adam)

梯度检查点能把激活值显存降一半以上,代价是计算量增加约30%。如果显存实在紧张,这是最有效的手段。

7.3 训练速度慢的优化方向

吞吐上不去,先定位瓶颈:

  • GPU利用率低:可能是数据加载慢,用多进程预取
  • 通信占比高:并行度太高,通信开销大,考虑减少并行或换更快的互联
  • 计算密集:检查是不是用了低效的算子,换FlashAttention等优化实现
  • 频繁同步:梯度累积步数太多导致同步频繁,适当调整

我一般用profiler跑一遍,看时间花在哪。十有八九是数据加载或通信,真正卡在计算上的反而少。

7.4 断点续训的坑

续训最常见的坑是状态不一致。比如只存了模型没存优化器,续训后优化器的momentum从0开始,等效于换了优化器,loss会跳。还有数据加载器位置没存,续训后数据顺序变了,影响训练动态。

我的做法是写一个统一的save_state和load_state函数,把所有需要保存的状态列个清单,每次加新状态就更新清单。这样不会漏。

8. 一份可直接参考的训练计划模板

把上面所有内容整合成一份模板,你可以直接抄去改:

model: params: 7B seq_len: 4096 data: total_tokens: 140B mix: web: 0.70 books: 0.15 code: 0.10 dialogue: 0.05 repeat_limit: 2 optimizer: type: AdamW beta1: 0.9 beta2: 0.95 eps: 1e-8 weight_decay: 0.1 grad_clip: 1.0 lr_schedule: peak_lr: 2e-4 warmup_steps: 2000 total_steps: 35000 decay: cosine min_lr_ratio: 0.1 batch: global_tokens: 4M micro_batch_size: 4 grad_accum_steps: 61 data_parallel: 8 parallel: tensor_parallel: 1 pipeline_parallel: 1 checkpoint: save_every_steps: 1000 keep_last: 3 keep_best: true monitoring: log_every_steps: 10 eval_every_steps: 1000

这份模板里的数字都是基于7B模型、140B token预算的常见配置,你换成自己的规模时,重点调整total_tokens、peak_lr、global_tokens这三项,其余按比例微调即可。

最后分享一个我自己的习惯:每次开新训练前,先用1%的数据量跑一个"迷你训练",把整个流程走一遍,确认loss能正常下降、checkpoint能正常存取、续训能正常接上。这个迷你训练花不了多少时间,但能提前暴露90%的配置问题。等真开跑几周的训练时,心里就有底了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询