收集数据
从 Bit 到 AGI · 第十章:自己训练一个模型 · 收集数据
预训练语言模型的第一步不是写代码,而是拿到足够多、足够干净的文本。本篇教你从公开语料、本地文件和网页三种来源收集数据,并估算你需要多少 GB 才能训出一个可用的迷你 GPT。
直觉:燃料决定航程
训练 LLM 像烧煤开蒸汽船:模型架构是引擎,数据是煤。煤太少,船走不远(欠拟合);煤太脏,引擎会堵(学到垃圾模式)。一个 125M 参数的 GPT,业界经验是至少 1–10 GB 去重后的纯文本 才能看到像样的 loss 下降;想要对话能力,后面还要加 SFT 数据。
定义
预训练语料(pretraining corpus)指用于 next-token prediction 的无标注纯文本集合。常用度量:
| 指标 | 含义 |
|---|---|
| 原始字节数 | 磁盘占用,含重复与 HTML |
| 去重后 token 数 | 真正参与训练的 token 总量 |
| 领域覆盖 | 代码 / 百科 / 新闻 / 论坛等比例 |
目标规模(本章实验):
例子
例 1:从 HuggingFace 拉取 SlimPajama 子集
SlimPajama 是 RedPajama 的去重版,约 627 GB;我们只需抽样 5 GB 做实验。
# 创建项目目录
mkdir -p ~/mini-gpt-lab/{raw,processed,checkpoints,logs}
cd ~/mini-gpt-lab
# 安装依赖
python3 -m venv .venv && source .venv/bin/activate
pip install datasets huggingface_hub tqdm
# 下载并导出为纯文本(约 500 万行,视网络而定)
python << 'EOF'
from datasets import load_dataset
ds = load_dataset(
"cerebras/SlimPajama-627B",
split="train",
streaming=True,
)
out = open("raw/slimpajama_sample.txt", "w", encoding="utf-8")
count, max_bytes = 0, 5 * 1024**3 # 5 GB 上限
for row in ds:
text = row.get("text", "")
if not text.strip():
continue
out.write(text + "\n\n")
count += len(text.encode("utf-8"))
if count >= max_bytes:
break
out.close()
print(f"Wrote {count / 1024**3:.2f} GB")
EOF例 2:合并本地 Markdown / PDF 提取文本
# 假设你把 ~/docs 下的 .md 都拷到 raw/local/
find ~/docs -name "*.md" -exec cat {} \; >> raw/local_docs.txt
# 统计行数与字节
wc -l raw/local_docs.txt
du -h raw/local_docs.txt例 3:用 wget 镜像允许爬取的 Wiki 导出
# 仅示例:务必遵守 robots.txt 与站点 ToS
wget -r -l 1 -H -k -p -E -nc \
-A.html \
-P raw/wiki_mirror \
"https://example-wiki.org/export/latest/"量化
| 规模 | 原始文本 | 约 token 数 | 125M 模型训练步数(seq=2048, batch=32) |
|---|---|---|---|
| 玩具 | 100 MB | ~30M | ~460 steps/epoch |
| 实验 | 5 GB | ~1.7B | ~26k steps/epoch |
| 小型产品 | 50 GB | ~17B | ~260k steps/epoch |
存储估算:5 GB UTF-8 文本 + 10% 元数据 ≈ 5.5 GB 磁盘;建议预留 20 GB 给清洗中间文件。
爬取网站前必须检查 robots.txt、版权与隐私法规。不要用未授权的个人聊天记录、付费内容或泄漏数据库训练模型——法律风险远高于技术风险。
动手试一试
cd ~/mini-gpt-lab
# 快速生成 10 MB 合成语料(无网络时测试流水线)
python << 'EOF'
import random, pathlib
words = ["比特", "向量", "梯度", "Transformer", "token", "GPU", "loss"]
path = pathlib.Path("raw/synthetic.txt")
with path.open("w", encoding="utf-8") as f:
for _ in range(50_000):
sent = "".join(random.choice(words) for _ in range(random.randint(5, 20)))
f.write(sent + "。\n")
print(path.stat().st_size / 1024**2, "MB")
EOF检查 raw/ 目录结构:
tree raw/ # 或 ls -lh raw/数据来源合规矩阵
| 来源 | 许可证 | 商用 | 备注 |
|---|---|---|---|
| SlimPajama | 各子集不同 | 需逐条查 | 含 CommonCrawl |
| Wikipedia dump | CC-BY-SA | 可,需署名 | 每周更新 |
| 自写博客 | 自有 | 是 | 最佳可控 |
| 爬取新闻站 | 多数禁止 ML | 否 | 读 ToS |
下载前在 docs/data-inventory.md 记录来源 URL、日期、许可证链接——发布模型时 Model Card 要用。
分片与增量采集
大语料分片存储,避免单文件 >10 GB 难以传输:
split -b 1G raw/slimpajama_sample.txt raw/shard_
ls -lh raw/shard_*增量更新时只追加新 shard,清洗脚本 glob("raw/shard_*") 统一处理。
常见误区
- 「数据越多越好」:未经去重的 100 GB 可能不如去重后的 10 GB;重复样本浪费算力。
- 混用多种编码:务必统一 UTF-8;GBK 文件用
iconv -f GBK -t UTF-8转换。 - 忽略许可证:CC-BY、ODC-BY 等要求署名;GPL 语料可能影响模型发布策略。
- 未记录采集日期:语料会过时;Model Card 应写
data_cutoff: 2026-07。 - PII 未脱敏:日志、工单含手机号邮箱;正则或 NER 脱敏后再训。
端到端实践要点
收集阶段决定了模型能力的上限。再强的 Transformer 也只能从数据里学到统计规律;Garbage In, Garbage Out 在 LLM 时代依然成立。建议建立 docs/data-inventory.md:每份语料记录来源、许可证、采集日期、字节数、主题占比。五 GB 英文百科与五 GB 中文论坛训出的模型,下游表现完全不同——前者擅长 factual continuation,后者口语化但可能幻觉更多。
若你计划后续做 SFT,预训练语料不必追求对话格式,但应覆盖目标领域词汇。医学模型需要医学预训练或 CPT;仅通用语料 + 医学 SFT,专业术语拼写都会弱。采集时可预留百分之十语料作永不参与训练的 hold-out,用于最终 PPL 与生成评估,避免「用测试集洗数据」的泄露。
网络不稳定时,HuggingFace streaming=True 优于一次性 load_dataset 全量下载:中断后可从断点 shard 继续。本地文档合并后,用 shasum raw/* 记录哈希,清洗脚本变更时可对比输出是否变化。最后,raw/ 目录应进 .gitignore,只把清洗脚本与 inventory 进 Git;语料太大且可能有版权争议,不应 push 到公开仓库。
命令流水线复盘
从零开始依次执行:mkdir ~/mini-gpt-lab && cd ~/mini-gpt-lab;python3 -m venv .venv && source .venv/bin/activate;pip install datasets huggingface_hub tqdm;运行本篇 SlimPajama 抽样脚本或 find 合并本地 md;wc -l raw/* 与 du -h raw/ 确认体积在目标五 GB 附近;记录 shasum raw/* >> docs/data-inventory.md。若无 GPU 网络,先用合成语料脚本生成十 MB 占位,保证后续清洗与 Tokenizer 章节可练手。采集完成后再进入清洗数据,不要跳过体积与许可证检查。
与前后章衔接
本章每篇都假设你已读完第一至九章:比特与文件格式(第一章)解释 train.bin 为何是字节流;信息论(第三章)解释为何 PPL 衡量压缩效率;Transformer(第五章)解释预训练在优化什么;Tokenizer(第六章)与本章 BPE 训练一一对应;Training(第七章)给出 loss、LoRA、Checkpoint 理论;Inference(第八章)对应推理与部署;GPU(第九章)对应硬件与显存估算。若某命令报错,先查依赖版本(Python 3.11+、CUDA 驱动、PyTorch 与 vLLM 匹配),再查路径是否与 mini-gpt-lab 目录约定一致。整条流水线可在单卡 4090 上于一个周末跑通;失败时回到从失败中恢复对照症状表,不要跳过日志与 checkpoint 排查。
小结
- 预训练需要大规模纯文本;本章目标 ~5 GB 去重前原始语料。
- 三条路径:HuggingFace 数据集、本地文件、合规爬取。
- 用字节数与 token 数估算训练步数,提前规划磁盘与算力。
→ 下一篇:清洗数据