跳转到内容

训练数据管道与 tokenization

训练 step 的每一毫秒都在等两样东西:算力与数据。前面各卷讲算力,本卷讲数据。数据管道的任务只有一个:让 GPU 永远不断粮。本章讲清楚从原始语料到训练 token 流的完整管道:tokenization 的离线化、数据打包、以及"数据顺序"这个常被低估的因素。

原始语料(网页/书/代码)
↓ 清洗(去重、质量过滤、格式化)
tokenization(离线,一次性)
↓
token 文件(分片存储,见[存储系统](/storage-data/02-checkpoint/storage-systems/))
↓ 打包(packing/grouping)
训练流(按微批喂给 GPU,见[数据加载](/storage-data/01-pipeline/data-loading/))

每一步都是"离线做一次,在线反复用"的设计——训练时只做最后一步(读 token 流),前面全部离线预计算。

Tokenization:离线一次,终身受益

Section titled “Tokenization:离线一次,终身受益”

在线 tokenize 是反模式:训练循环里现做分词,CPU 瓶颈、GPU 断粮。标准做法:

  • 离线预 tokenize:全部语料一次性分词,存成 token 文件(二进制、分片、支持随机访问)
  • 并行化:tokenize 是 embarrassingly parallel 的,用数据管道框架(如 datatrove、开源工具链)多机并行
  • 存储格式:np.uint16/uint32 的裸数组或分片 bin(如 GPT 风格的 train.bin/val.bin),训练时 mmap 直接读——零解析开销

一个数字:1T token 的语料,在线 tokenize 每步都要现算(CPU 每秒数十万 token 的吞吐),离线做则训练时零成本。这就是"预处理一次、训练无数遍"的账。

变长文档直接按条训练,batch 内 padding 浪费算力(短句 pad 到最长)。packing 把多个文档拼成定长序列:

方式做法特点
简单拼接文档首尾相接切成定长文档边界处注意力泄漏(前文档看见后文档)
带边界 mask拼接 + attention mask 阻断跨文档干净但实现复杂
最优装箱按长度分组(first-fit 等)减少截断中等复杂度

实践中大模型预训练普遍用简单拼接(接受边界泄漏,实验显示影响很小)+ 数据打乱;SFT/微调用带 mask 的变长 batch(varlen/packing with masks)。

packing 的算力收益是真实的:变长 SFT 不 packing,padding 浪费 30–50% 的计算(见 Roofline:算的是 pad,全是浪费)。

数据顺序影响训练质量与稳定性:

一、混比(mixture):多来源语料按比例混合(网页 60% / 代码 20% / 书 10%...),比例是训练配方的一部分(Llama 的配比公开过)。实现上按"来源桶"采样。

二、课程(curriculum):训练后期上高质量数据(退火阶段上精选语料是标配);阶段切换用不同的数据集与混比。

三、shuffle 与去重:全局 shuffle(跨 epoch 不重复顺序);训练集与验证集的分离要在来源级(同源不泄漏)。

一个工程细节:恢复训练时数据位置要精确回到检查点(第几个分片第几个样本,见检查点)——数据管道的随机数与游标是容错的组成部分。

垃圾进、垃圾出:数据质量过滤是管道里最"值钱"的一步:

过滤目的常见手段
去重(dedup)消重复(记忆化风险 + 算力浪费)MinHash/精确哈希,文档级+段落级
质量过滤淘汰低质语料启发式(长度、符号率)+ 分类器打分
有害内容过滤安全合规分类器
语言/领域过滤配比控制fastText 分类器

去重的双重收益:质量(重复语料让模型记忆)与算力(重复 token 是白算的)。1T token 语料去重后常剩 60–70%——去重本身就是最便宜的"算力优化"。

  • 管道设计原则:预处理离线一次,训练时只读 token 流(mmap 裸数组,零解析开销)。
  • 在线 tokenize 是反模式;1T token 离线化省掉的是每步的 CPU 瓶颈。
  • packing 消 padding 浪费(变长 SFT 不 packing 浪费 30–50% 算力);预训练用简单拼接,SFT 用带 mask 的变长。
  • 混比与课程是训练配方的一部分;数据游标要进检查点,恢复时精确回位。
  • 去重是质量与算力的双重收益;过滤在来源级做,防泄漏。