从0训练LLM · 现代大模型体系 阅读 + 实验 ≈ 35 分钟 页内实验 ×1
C7 数据:从哪来、怎么洗、怎么配 第 3 课

规则都过了、也不重复,没营养的文本怎么筛?

质量分类器
规则看长相,营养不在长相里。拿「好文本」训语言模型、按困惑度筛?我们模型写的胡话困惑度 93,比真原文还低。现代做法是先把「好」写成打分细则,让强模型标一小批,再蒸馏成便宜的分类器——筛得越狠,留下的 token 越少。
❓

本课一问:规则删掉了乱码和样板,去重删掉了拷贝。剩下的文本全都「合法」、也不重复——但其中大量是没什么内容的:关键词堆砌的推广页、东拼西凑的问答、语句通顺却什么也没说的段落。怎么把它们也筛掉?

这一课先不碰:筛完之后各类数据按什么比例混(第 4 课)、好数据不够时怎么办(第 5 课)。

从已有出发

从已有出发 · 累计数据流 点已学环节看形状与参数
解码层

模型这条流水线上,本章始终停在最左边的「文字」一格;把这一格展开,就是下面这条数据管线:

从已有出发 · 数据管线 本课其他环节点环节看它做什么、真实数字

第 1 课的规则逐条检查文本的长相:长度、句末标点、虚词。第 2 课比较文本之间是否重复——在整本《三國志演義》上一对近重复也没找到。两者都回答不了「这段话有没有营养」。

本课换一部分例子,原因写在这里:一部编校过的名著里找不到真正「没营养」的段落,所以三国演义在本课改当「好文本」的参考语料;要被筛的对象换成我们自己模型写的续写(真实输出)和标明「教学构造」的网页文字。

先自己设计:继续加规则

最自然的想法是规则再细一点。先看两段文本在第 1 课那 4 条中文规则上的实测值:左边是验证集里的真原文(模型训练时没见过),右边是我们项目基线模型(训练 400 步、val loss 4.626)写的一段续写——真实的模型输出,不是编的。

  1. ① 朴素方案
  2. ② 它在哪失败
  3. ③ 改进方案
朴素方案继续加规则:长度、句末标点、虚词、乱码……
规则验证集原文模型续写
字数 ≥ 50135 字 ✓114 字 ✓
以中文句末标点结尾「。」✓「。」✓
文言虚词 ≥ 2 个4 个:之曰於以 ✓3 个:之而於 ✓
不含 ASCII 字母0 个 ✓0 个 ✓

原文:於是姜維領敕辭朝,同夏侯霸逕到漢中,計議起兵。維曰:「可先遣使去羌人處通盟,然後出西平,近雍州。先築二城於麴山之下,令兵守之,以為犄角之勢。我等盡發糧草於川口,依丞相舊制次第進兵。」是年秋八月,先差蜀將句安、李歆同引一萬五千兵,往麴山前連築二城。句安守東城,李歆守西城。

模型续写(提示词「卻說曹操」,温度 0.8、top-k 50):卻說曹操自領大軍來。曹操自引大軍從小百,守巇城。操令軍將馬一千,伏於山坡之邊,望風而去。行不時,操方纔行過門,只聽得一將旗上喊聲大震,徐晃軍大開,各自相離。兩軍相持木,操兵到處,操自引兵追趕。曹操在山上殺將來,見袁軍山坡前塢中。

改进一:用「好文本」上训的语言模型打分

CCNet(Wenzek 2019)在每种语言的维基百科上训一个 5-gram 语言模型,给 Common Crawl 的每一段算困惑度,再按三分位切成 head / middle / tail 三档 。我们在三国演义的训练集上做同一件事,只是把 5-gram 换成更小的字级 bigram:

字级 bigram 语言模型的困惑度(与 unigram 插值)
= exp(− Σt log ), p = · + (1−λ)·
👆 公式里带下划线的每一项都可以点——点哪项,讲哪项。
浏览器里的组件用同一个公式重算每段文本的困惑度,并在旁边显示 Python 预计算的值,逐位一致。
算法模拟器 · 困惑度过滤器(逐字着色 = 惊奇度)
验证集 段真原文的困惑度分布(横轴对数;红线 = 当前阈值)

🎯

试三件事:① 读排在最上面的是谁:我们模型写的续写,困惑度 93.417,比两段真原文(273.209、322.761)都低;② 看那段现代白话科普(困惑度 3,390):一段讲清了雨怎么形成的好文字,被染成一片红——每个字都在说「我不像三国演义」;③ 往右拖阈值直到科普段落被留下,读下方直方图:同一个阈值要么放进样板文字,要么先删掉验证集里的诗(最高的一首 3629.71)。

它在哪失败?困惑度衡量的是「像不像参考语料」,不是「有没有营养」:

参考语料选什么,过滤器就偏向什么。拿维基百科当参考,就偏向「像维基的网页」,其余一概打低分。

改进二:先把「好」写成细则,再让模型学会打分

现代做法把判据说清楚。FineWeb-Edu 的流程分三步:

  1. 写打分细则、让强模型标一小批。用 Llama-3-70B-Instruct 给 46 万个网页打 0–5 分。细则是累加式的:有一些和教育相关的基本信息,加 1 分;涉及教育要素但没对准,再加 1 分;适合教学、覆盖课程里的关键概念,再加 1 分;对小学到初中阶段高度有用、写得连贯,再加 1 分;堪称范文,再加 1 分。提示词特意要求关注中小学层次的知识,避免模型偏爱 arXiv 摘要这类高度技术化的页面 。
  2. 蒸馏成便宜的分类器。在 Snowflake-arctic-embed-m 的句向量上训一个线性回归(41 万条训练、5 万条验证,冻结编码器),输出四舍五入成 0–5 的整数;阈值取 3 时,相对 Llama 3 的标注 F1 = 82%。
  3. 筛全量。给 FineWeb 的 15T token 打分用了 6,000 个 H100 小时,留下 ≥ 3 分的 1.3T token。
阈值留下的 token占 FineWeb 15T
不筛15T100%
≥ 25.4T36.0%
≥ 3(FineWeb-Edu)1.3T8.7%(数据卡:删掉 92%)

效果:在 350B token 上训同样的 1.71B 模型,MMLU 从 33% 到 37%、ARC 从 46% 到 57%;在 MMLU 上,FineWeb-Edu 训到 38B token 就达到 33.6%,另一个数据集 Matrix 要 300B token 才到同样水平 。

同一个思路的其他版本:

新的失败:筛得越狠,剩得越少

阈值 3 删掉了 92% 的数据,DCLM 只留前 10%。对一次几百 B token 的消融这没问题;可 C6 讲过,生产模型要训十几甚至几十 T token——筛完只剩 1.3T,就只能重复很多遍(第 5 课讲重复的代价)。

Nemotron-CC 把问题摆到了台面上:它用多个分类器的集成代替单一分类器、少用启发式规则,再用模型改写(第 5 课)扩充数据,得到 6.3T token(4.4T 真实 + 1.9T 合成)。用其中 1.1T 的高质量子集训 8B 模型 1T token,MMLU 比 DCLM 高 5.6;全量与 DCLM 持平,但真实的唯一 token 是 DCLM 的 4 倍 。质量和数量要一起算,不能只看质量。

⚠

常见误解一:「困惑度低 = 质量高。」困惑度低只说明「像参考语料」。我们模型的胡话困惑度 93.417,低于真原文;章末套话是全书困惑度最低的段落之一。

常见误解二:「分类器阈值越高越好。」FineWeb-Edu 选 3 而不是 4、5,是在知识类基准和常识类基准(HellaSwag)之间折中;阈值越高,剩下的 token 越少,长程训练就得重复越多遍。

常见误解三:「LLM 标注就是真值。」82% 的 F1 是分类器相对 Llama 3 标注的一致程度,不是相对人。细则是人写的偏好(「中小学层次的教育价值」),标注模型也有自己的偏好,两者都会原样传给分类器。

放回演进图里

从这一课开始,判断数据好坏的不再是人写的规则,而是模型。

预训练数据的演进:每一代都被上一代的某个真数字逼出来
  1. 起点 有多少用多少:原始网页直接进训练 Common Crawl 原始快照
    解决了量几乎无限:Common Crawl 定期抓取全网,FineWeb 用了 96 个快照。
    卡在WET 纯文本里样板和菜单太多(FineWeb §3.2);我们的原始文件不还原硬换行就跑 C4 句末规则,整本书只剩 17.02% 的字。
  2. 第一代 让人当过滤器:只取被点过赞的链接 GPT-2 WebText,2019
    解决了Reddit 上至少 3 karma 的外链,4,500 万个链接,清洗后约 800 万文档、40 GB。
    卡在量太小:C6 算出的需求是十几 T token;而且只覆盖被分享过的那一小部分网页。
  3. 第二代 只看长相的规则过滤 C4 2019 · Gopher 2021
    解决了句末标点、词数、平均词长、停用词、重复行……便宜,能在全网快照上跑。
    卡在绑语言、绑求值单位:英文原版在整本《三國志演義》3,697 段上通过 0 段;C4 句末标点规则删掉约 30% 的 token,FineWeb 最后没用它。
  4. 第二代 近重复去重:MinHash + 分桶 Broder 1997 → Lee 2021 → FineWeb 2024
    解决了C4 里一句话重复 61,036 次;去重后模型复述训练文本的频率降到 1/10。MinHash 把两两比较变成查桶。
    卡在去得越狠未必越好:跨 96 个快照全局去重只剩 4T,训不出更好的模型;每快照独立去重留 20T,才追平 RefinedWeb。
  5. 第三代 让模型给数据打分 CCNet 2019 · GPT-3 2020 → FineWeb-Edu、DCLM 2024 你在这里
    解决了判断「有没有营养」:FineWeb-Edu 让 Llama-3-70B 标 46 万页、蒸馏成分类器,MMLU 33% → 37%。
    卡在参考语料的困惑度偏向「像参考」:我们模型写的胡话困惑度 93.417,低于真原文 273.209;阈值 3 删掉 92%,长程训练不够用。
  6. 第四代 配比:从手工权重到代理模型搜索 The Pile 2020 → DoReMi 2023
    解决了DoReMi 用 280M 代理模型搜域权重,8B 模型下游平均 +6.5 个点,达到基线快 2.6 倍。
    卡在权重一变就要重复:按 DoReMi 的权重花完 The Pile 的有效体量,YouTube 字幕要走约 16.9 遍(按字节近似 token,只看量级)。
  7. 第五代 数据墙:重复与合成 Muennighoff 2023 · WRAP 2024 · Phi-4 2024
    解决了重复 4 遍以内几乎等于新数据;改写真实网页(WRAP)预训练约快 3 倍;Phi-4 约 10T token 里合成占 40%。
    卡在让模型只吃自己生成的数据,分布的尾巴一代代消失:在三国演义真实字频上重采样,只出现 1 次的字每一代有约 36.8% 的概率丢掉,丢了就回不来。
  8. 第六代 按时机投放:退火 → mid-training MiniCPM、Llama 3 2024 → OLMo 2、Qwen3、GLM-5
    解决了最好的数据放到学习率衰减段(C5 的 WSD)加量;再发展成独立阶段,顺便拉长上下文。
    卡在同名不同方:Qwen3 的高质量阶段占 13.9%,Llama 3 的退火只占 2.6e-6;收益与学习率调度缠在一起,很难单独归因。
数字口径:我们语料上的数字由 gen_c07_corpus.py 在《三國志演義》上实算(c07-*.json);FineWeb、GPT-2 数字出自本地 PDF;DoReMi、Muennighoff、WRAP、Phi-4、Qwen3、Llama 3 出自原文(核实记录见设计卡);「约 16.9 遍」「36.8%」「13.9%」在构建时现算。

同一原则在后训练:LIMA

「质量比数量重要」不只出现在预训练。LIMA(Zhou 2023)只用 1,000 条精心挑选的问答示范对 LLaMA 65B 做 SFT,不做任何强化学习;人类评估里,它的回答与 GPT-4 相比「一样好或更好」的比例是 43%,对 Bard 是 58%,对用人类反馈训练过的 DaVinci003 是 65%。而用了 52 倍数据(52,000 条)训练的 Alpaca 65B,反而不如 LIMA 受欢迎 。

论文由此提出「表层对齐假设」:模型的知识和能力几乎全部在预训练里学到,SFT 教的只是表层行为——用什么格式、以什么角色、回答还是续写。这一条同时解释了三件事:

  1. 为什么预训练模型只会续写(它只学过续写,没学过「回答」这个格式);
  2. 为什么 1,000 条就够(知识早就有了,重塑行为不需要很多数据);
  3. 为什么 SFT 有天花板(它改不了预训练里没有的知识和推理能力——所以还需要强化学习,C12 讲)。

和预训练的区别要分清:预训练里「质量 > 数量」是因为好数据每个 token 教给模型更多东西;SFT 里是因为要教的东西本来就少。两者都不是「数据越少越好」——FineWeb-Edu 也要 1.3T token。

证据三问

问本课的回答
① 它解决什么问题?在「合法、不重复」的文本里,再筛出信息密度高、对训练有用的部分
② 数学上为什么可能有效?没有证明。有一个理论动机:好数据的每个 token 带来更多可学的规律;分类器是把人写的偏好压缩成一个便宜的打分函数
③ 实验上为什么选了它?FineWeb-Edu、DCLM 的消融都显示基于模型的过滤是提升最大的一步;Nemotron-CC 又显示筛得太狠会在长程训练里吃亏

一句话

📌

规则管长相,分类器管营养:先把「好」写成打分细则,让强模型标一小批,再蒸馏成便宜的分类器去筛全网——但筛得越狠,剩下的 token 越少。

🚦

先停在这里:记住「困惑度 ≠ 质量」「阈值是质量与数量的折中」。
再深一层:在过滤器里输入你自己写的一段文言、一段白话,看同一个模型给它们的困惑度差多少;再想想如果把参考语料换成维基百科,哪些好文本会被误删。

下一个缺口

筛完剩下网页、代码、数学、书,各按多少比例混? → 第 4 课:网页、代码、数学、书,按什么比例混?

你可能会问