章节导航 第 5 章 / 共 23 章
质量过滤——从规则到模型
质量定义、分类器过滤、困惑度过滤与质量 Scaling Law
“到底什么是’高质量’数据?这个问题的答案,在过去四年里变了至少三次。“
5.1 质量的定义:到底什么是”高质量”?
这是数据工程中最根本也最困难的问题。在花大量篇幅讨论”如何过滤低质量数据”之前,我们必须先回答:你到底要过滤掉什么?保留什么?
不同视角的”质量”
语言流畅性视角:文本是否语法正确、表达自然、没有乱码?
- 这是最容易衡量的维度
- 但”语言流畅”不等于”有价值”——一篇流畅的 SEO 垃圾文章,语言流畅性满分,信息价值为零
信息密度视角:每个 token 包含多少有用的信息?
- 维基百科的信息密度很高——几乎每句话都传递知识
- 论坛闲聊的信息密度很低——大量的寒暄、重复、离题
- 但论坛闲聊对模型的”对话能力”有独特的训练价值
知识准确性视角:文本中的事实是否正确?
- 学术论文经过同行评审,准确性较高
- 社交媒体上的信息可能包含大量错误和误导
- 但准确性检测极其困难——需要知识图谱或事实验证系统
多样性视角:数据是否覆盖了足够多的主题、风格、观点?
- 全是维基百科风格的数据会让模型的输出变得”百科全书腔”
- 需要不同领域、不同写作风格、不同复杂度的混合
教育价值视角:这段文本能教给模型什么?
- 这是近年来兴起的重要视角
- 一段”教育价值高”的文本可能不是最流畅的(如一个详细解释编程概念的StackOverflow回答),但对模型的学习最有帮助
认知变化:从”像维基百科就是好的”到”好数据是目标函数的结果”
认知演变:
2019-2020: "像维基百科就是好的"
→ GPT-3 的质量分类器用维基百科作为正例
→ 结果:倾向于保留百科全书风格的文本,过滤掉口语化、非正式、但可能有价值的内容
2022-2023: "教育价值才是关键"
→ FineWeb-Edu 引入"教育价值分类器"——用 LLM 判断文本的教育价值
→ 效果显著优于传统的质量分类器
→ 但仍然有偏差:过度偏好"教材式"的内容
2024: "好数据 = 让下游任务表现好的数据"
→ DCLM 框架:好的数据过滤策略的衡量标准是最终模型在 benchmark 上的表现
→ 数据质量不是数据本身的属性,而是 (数据, 目标) 的联合函数
2025-2026: "多维度质量 + 动态评估"
→ 不同训练阶段需要不同"质量"标准的数据
→ 质量评估需要和训练目标紧密绑定
→ 没有"万能"的质量过滤器
5.2 基于分类器的质量过滤
GPT-3 的维基百科分类器
GPT-3 的做法是训练一个二分类器来判断网页文本的”质量”:
- 正例:维基百科文章、高质量参考资料
- 负例:随机采样的 Common Crawl 网页
使用 logistic regression 或 fastText 分类器,基于 n-gram 特征。
问题:
- 分类器学到的实际上是”像维基百科”而非”高质量”
- 结果会过滤掉大量非百科体裁但有价值的内容(如口语化的教程、个人经验分享、技术论坛的讨论)
- 关键认知:分类器的偏差来自正例的选择——正例的特征会被放大
fastText 质量分类器
这是目前最常用的质量过滤方案之一。
训练流程:
# 1. 准备训练数据
# 正例:从维基百科、精选网站抽取的文本
# 负例:Common Crawl 的随机样本
# 2. 特征工程
# fastText 使用字符 n-gram 作为特征
# 通常使用 bigram (n=2) 到 trigram (n=3)
# 3. 训练
import fasttext
model = fasttext.train_supervised(
input='quality_training_data.txt',
lr=0.1,
epoch=5,
wordNgrams=2,
dim=100,
)
# 4. 推理(极快,CPU 上每秒可处理数万条)
label, score = model.predict("一段待评估的文本")
优点:
- 速度极快,适合万亿 token 级别的数据
- 实现简单,易于迭代
缺点:
- 依赖于正例的选择——如果正例有偏差,分类器就有偏差
- 基于 n-gram 特征,对语义理解有限
- 无法区分”语言流畅但信息为空”和”语言流畅且信息丰富”
改进方向:验证驱动的种子数据优化。Ultra-FineWeb 针对 fastText 分类器的核心痛点——“种子数据选择依赖人工经验”——提出了系统性的解决方案。其核心思路是:引入高效验证策略,以最小计算成本评估不同种子数据选择对下游 LLM 训练效果的影响,从而将种子数据优化从”拍脑袋”变成”有数据支撑的决策”。具体来说,Ultra-FineWeb 通过优化正负样本的选择来改善分类器的鲁棒性,最终构建了约 1T 英文 token + 120B 中文 token 的高质量数据集。这代表了 fastText 质量分类器从”一次性训练”到”迭代验证优化”的范式演进。
高效验证策略:从”训练验证”到”注入验证”
传统上,验证一个数据过滤策略是否有效的黄金标准是:用过滤后的数据训练一个完整的 LLM,然后在 benchmark 上评估。但这个验证流程极其昂贵——一次完整的预训练可能需要数千 GPU 小时。这使得过滤策略的搜索空间被极大压缩,很多潜在的好策略因为”验证不起”而从未被尝试。
Ultra-FineWeb(OpenBMB/清华/ModelBest, arXiv: 2505.05427)提出的高效验证策略改变了这个局面:
核心方法:用一个近训练完成的 LLM(而非从头训练),在训练的最后若干步中注入候选语料,观察性能提升幅度来评估数据质量。
传统验证流程:
从头训练完整LLM → 评估benchmark → 数千GPU小时/次
高效验证流程:
取近完成的LLM → 注入候选语料训练少量步 → 评估增量 → 数十GPU小时/次
加速比:约 50-100x
三个关键设计决策:
-
为什么用近完成的 LLM 而非从头训练? 近完成的 LLM 已经学会了大部分通用知识,对数据质量的敏感性更高——高质量数据能带来可观测的增量提升,而低质量数据则不会。这类似于”味觉灵敏度”——空腹时对食物质量的判断比饱腹后更准确。
-
公正种子选择(Fair Seed Selection):基于”高质量种子数据有益于 LLM 训练”这一基本假设,自动选择正负样本,减少人工主观性。具体做法是:将验证策略的评估结果回传指导种子数据的选择,形成闭环优化。
-
fastText 分类器的选择:Ultra-FineWeb 最终选择了 fastText 而非 LLM 分类器(如 FineWeb-Edu 使用的),理由是:
- 推理效率远超 LLM 分类器(CPU 上即可运行,无需 GPU)
- 质量过滤效果相当——在高效验证的指导下,fastText 分类器可以迭代优化到接近 LLM 分类器的效果
- 在万亿 token 级别的数据上,推理效率的差异意味着数天的计算时间节省
数据集成果:Ultra-FineWeb-en (~1T tokens) + Ultra-FineWeb-zh (~120B tokens),已成为 MiniCPM4 核心预训练 Web 数据。在 MMLU/ARC/C-Eval 等多个基准上显著超越 FineWeb 和 FineWeb-Edu。
实践启示:高效验证策略将”数据质量探索”从昂贵的一次性实验变成了可快速迭代的搜索过程。对于数据预算有限的团队,这意味着可以用更少的计算资源找到更优的数据配方。
FineWeb-Edu 的教育价值分类器
FineWeb-Edu 是 FineWeb 团队的一个重要创新。他们不是用传统的”质量”标签来训练分类器,而是用 LLM 来评估文本的”教育价值”。
训练方法:
- 从 FineWeb 中抽取大量文本样本
- 用 LLM(如 Llama 3 70B)给每个样本打”教育价值”分数(0-5 分)
- 用这些标注训练一个轻量级的分类器(如 BERT-small)
打分标准:
- 0 分:垃圾内容、广告、SEO 文本
- 1 分:有基本信息但组织混乱
- 2 分:有一定教育价值但不系统
- 3 分:有明确的教育价值,解释清晰
- 4 分:高质量的教育内容,有深度和结构
- 5 分:教科书级别的内容
效果:
- 使用教育价值 ≥ 3 的数据训练的模型,在多个 benchmark 上显著优于使用全量数据的模型
- 特别在推理和知识密集型任务上提升明显
- 即使训练 token 数减少了 50%+,模型性能反而提升
但也有局限:
- 过度偏好”教材式”内容——模型的输出可能变得过于”说教”
- 对话风格的内容几乎全被过滤掉——但这些内容对模型的对话能力很重要
- LLM 标注的一致性有限——同一段文本可能被评为 2 分也可能被评为 4 分
DCLM 的 Model-based Filtering
DCLM(DataComp for Language Models)框架提出了一个更系统的方法:
- 使用预训练的 LLM 直接对每段文本打分
- 分数反映的是”这段文本对训练有多大帮助”
- 通过可控实验验证不同过滤策略的效果
与 FineWeb-Edu 的区别:
- DCLM 使用更大的模型来打分,精度更高但成本也更高
- DCLM 的评估标准更直接——“对下游任务的帮助”而非”教育价值”
损失驱动的目标导向选择:CoLoR-Filter
除了基于分类器和困惑度的方法,CoLoR-Filter 提出了一种从损失角度直接建模数据价值的方法。其核心思想是:对于目标领域(如 Books),用 auxiliary 模型评估每条数据在该领域的损失,相对损失最低的数据(即 auxiliary 模型最容易预测的)往往是最有价值的目标域数据。实验表明,150M 模型选择的 1B token 数据可以让 1.2B 目标模型达到随机选择 25B token 的效果(Books),下游多选问答任务上数据量减少 11 倍。
这提供了一类新的筛选范式:“损失驱动”而非”特征驱动”——不是判断数据”看起来好不好”,而是判断数据”对目标模型的贡献有多大”。
多语言质量分类器:跨语言迁移方案
对于非英文语言(如中文),高质量本地数据量可能不足以训练可靠的本地质量分类器。Turki 等人(2026)提出跨语言质量分类器方法,通过跨语言迁移或对齐技术,用英文或其他资源丰富语言的质量信号辅助目标语言的数据选择。实践策略包括:
- 使用多语言 fastText 模型:用多语言预训练模型统一建模多语言质量信号
- 用 LLM 评估文本的教育/信息价值(与 FineWeb-Edu 方法类似),适用于任意语言
- 基于翻译增强的种子数据构建:将英文高质量数据的质量标签通过翻译迁移到目标语言
FineWeb-2:统一多语言过滤框架
EPFL 团队在 NeurIPS 2025 上发表的 FineWeb-2 是目前最系统性的多语言数据过滤工作,首次实现了跨 20 种语言的统一模型驱动过滤框架。
技术架构:
FineWeb-2 多语言过滤管线:
1. FastText 初始过滤
└─ 语言特定规则 → 去除明显低质量内容
2. XLM-RoBERTa 嵌入分类器(核心创新)
└─ 用 XLM-RoBERTa 编码文本 → 嵌入空间中定义质量边界
└─ 质量标准:"结构化 + 知识丰富"
└─ 跨语言共享分类器参数 → 利用高资源语言的知识辅助低资源语言
3. 统一评估
└─ 各语言独立评估 + 跨语言一致性检查
关键结果:仅用 15% 的 token 即可匹配 FineWeb-2 基线的 MMLU 分数。这意味着 85% 的多语言 Web 数据对模型训练的贡献为零或为负——在多语言场景下,质量过滤的收益比英文场景更加显著。
覆盖范围:20 种语言(中/德/法/阿拉伯/丹麦等),数据集已在 HuggingFace 公开发布。
需要注意的局限: EPFL 团队在后续研究(arXiv:2604.20549, ICLR 2026 DATA-FM Workshop)中发现,仅靠扩大语言池规模并不能自动保证低资源语言的过滤稳定性。大规模的跨语言迁移可能带来 rank instability——不同规模的池化产生的质量排序显著不同。推荐的补救手段包括:(1) 第三四分位数采样(Q3)——取质量分数前 25% 而非简单阈值切分;(2) retention rate 逐语言调优——不是使用统一的保留率,而是为每种语言单独校准。这对中文团队尤为重要——中文的过滤稳定性不能仅依赖英文大规模池化的迁移信号。
与单语言方法的对比:FineWeb-2 的核心优势在于跨语言迁移——高资源语言(如英语)的质量判断知识可以通过 XLM-RoBERTa 的共享表示传递给低资源语言,使得即使训练数据有限的语种也能获得可靠的质量过滤。
模型自感知质量评估:CPQS-Tuning
CPQS-Tuning 提出了一个不同思路:不依赖外部质量分类器,而是利用目标模型对每条数据的”学习损失”作为质量信号。核心假设是:模型在某些数据上训练 loss 下降快(“容易学”),说明这些数据与模型的当前知识状态匹配度高;而过度简单(loss 极低)或过度困难(loss 极高)的数据价值都有限。
在实践中,这种方法需要用目标模型对候选数据做一次小规模 forward pass,计算 per-sample loss,代价较高,但可以更精确地捕捉”数据-模型匹配度”。这与 5.3 节讨论的”困惑度景观”方法形成互补——PPL 用参考模型评估,CPQS 用目标模型评估。
CQF 的根本困境:质量幻觉
上面介绍的所有分类器方法——从最早的维基百科分类器到最新的 DCLM——都属于基于分类器的质量过滤(Classifier-based Quality Filtering, CQF)范式。2026 年初,Apple 联合牛津大学发表的 “The Data-Quality Illusion” 对这整个范式提出了根本性挑战。
核心发现:CQF 的有效性可能不是我们以为的那个原因。
传统理解:分类器学会了区分”高质量”和”低质量”数据 → 过滤后保留的是”真正高质量”的数据 → 模型训练效果更好。
Apple 的发现揭示了一个悖论:
-
分类器学到的是”分布差异”而非”语义质量”。当我们用维基百科作为正例、Common Crawl 作为负例训练分类器时,分类器学到的是”像维基百科”vs”像 Common Crawl”的分布差异,而非通用的”质量”概念。
-
CQF 在过滤预训练数据的同时,也隐式地过滤了高质量数据集本身。如果你把分类器反过来应用于正例数据(如维基百科),会发现相当一部分正例也会被判为”低质量”——这说明分类器并没有真正理解”质量”。
-
下游性能提升不代表模型在高质量数据上的语言建模能力提升。经过 CQF 过滤后训练的模型,在特定 benchmark 上表现更好,但在高质量数据集上的困惑度并没有相应降低。
风格 vs 质量的混淆——Wikipedia 格式化逆转实验: Klimaszewski & Andruszkiewicz(arXiv:2605.23721, 2026-05)提供了一个更直观的定量证据。他们在 FineWeb-Edu 的 CQF 分类器上做了一个简单实验:仅将文档重新格式化为 Wikipedia 风格——添加 infobox 标记、章节标题、引用格式等 Wikipedia 标记——就能逆转分类器对约 7% 文档的过滤决策。原本被判定为”低质量”的内容,穿上 Wikipedia 的”外衣”后即可通过质量阈值。这说明 CQF 分类器学到的是”看起来像 Wikipedia”而非”具有教育价值”。
这个实验的价值在于它可复现、可理解——任何读者都能立即想象一个 SEO 垃圾页面用 Wikipedia 格式包装后”洗白”进入训练集的场景。需强调:这并非 FineWeb-Edu 的固有缺陷,而是整个 CQF 范式的系统性局限——任何以特定参考集为”高质量标准”的分类器都面临同样的”风格污染”风险。
这对实践意味着什么? CQF 仍然是有效的——经过过滤的数据训练出的模型确实表现更好。但我们需要认识到,CQF 的有效性可能源自”选择了特定分布的数据子集”,而不是”选择了真正高质量的数据”。这意味着:
- 不要过度依赖单一分类器。不同分类器捕捉不同的分布特征,多分类器组合可以缓解单一偏差
- 误杀恢复更加重要。既然分类器不是在判断”质量”,那么被过滤掉的数据中存在大量有价值内容就不奇怪了(与 5.7 节发现 3 呼应)
- 关注数据的多样性。CQF 本质上是在压缩数据分布,过度过滤会损害多样性
5.3 基于困惑度的过滤
基本思想
用一个已训练好的语言模型计算每段文本的困惑度(Perplexity, PPL)。PPL 反映的是文本在该模型看来的”意外程度”——PPL 越低,模型认为文本越”正常”。
直觉:高 PPL 的文本可能是乱码、外语混入、OCR 错误等低质量内容。
KenLM 方案
KenLM 是一个高效的 n-gram 语言模型工具,可以快速计算 PPL。
# 训练一个 KenLM 模型(用维基百科作为参考语料)
lmplz -o 5 -S 80% -T /tmp < wiki_zh.txt > wiki_zh.arpa
build_binary wiki_zh.arpa wiki_zh.binary
import kenlm
model = kenlm.Model('wiki_zh.binary')
def compute_ppl(text: str) -> float:
"""计算文本的困惑度"""
# KenLM 需要分词后的文本
words = list(text) # 中文按字分
log_prob = model.score(' '.join(words))
ppl = 10 ** (-log_prob / max(len(words), 1))
return ppl
# 使用
ppl = compute_ppl("大语言模型的训练数据质量非常重要。")
print(f"PPL: {ppl:.2f}") # 正常中文文本的 PPL 通常在 50-500 之间
ppl = compute_ppl("asdfgh 乱码内容 #$%^")
print(f"PPL: {ppl:.2f}") # 乱码的 PPL 通常在 5000+ 以上
优点:
- 速度极快——比分类器还快
- 不需要标注数据——只需要一个参考语料
缺点:
- 基于 n-gram,对语义理解有限
- 严重依赖参考语料的选择——用维基百科训练的 KenLM 会给非百科体裁打高 PPL
PPL 过滤的反直觉发现
发现 1:太低的 PPL 不意味着”高质量”
PPL 极低(< 30)的文本往往是:
- 重复内容(如”是的是的是的是的…”)
- 模板化内容(如法律声明、标准条款)
- 模型训练数据的”记忆”(如果参考语料中有这段内容)
这些文本”符合模型预期”,但对训练几乎没有价值。
发现 2:中等 PPL 的文本可能最有价值
PPL 在 100-500 之间的文本,通常是正常但有一定信息量的内容。太低说明模型已经”知道”了(没有新信息),太高说明内容可能有问题。
建议的 PPL 过滤策略:
过滤 保留 过滤
←──────────→ ←─────────────────→ ←──────────→
PPL: 0 30 50 500 1000 ∞
|_____|_____|___________________|_____|_______|
重复/模板 最佳区间 可疑 乱码/错误
也就是说:PPL 过滤应该是双边的——既过滤极高 PPL 也过滤极低 PPL。
PPL 的范式升级:从过滤到选择
上面讨论的 PPL 过滤本质上是”去坏”——设定阈值,过滤掉 PPL 异常的数据。但 PPL 的潜力不止于此。一项关于困惑度感知数据 Scaling Law 的研究提出了一种更积极的用法:将 PPL 从过滤工具升级为选择工具。
核心思想:PPL 不仅反映数据质量,还反映数据对当前模型的信息价值。
- 低 PPL 数据:模型已经”知道”的内容,训练价值有限(冗余信号)
- 中高 PPL 数据:模型尚未充分掌握的知识,蕴含”知识鸿沟”——这可能恰恰是最有训练价值的内容
- 极高 PPL 数据:超出模型理解范围的噪声(乱码、外语等)
通过构建困惑度景观(PPL Landscape)——对候选数据集中每条数据计算基础模型的 PPL,形成一张”信息价值地图”——可以实现自适应数据子集选择:优先选择能最大化知识吸收、最小化冗余的内容。
适用场景:这一方法在持续预训练(Continual Pre-training)和领域适应中尤其有效,因为在这些场景下,“模型已知”和”模型未知”之间的界线更清晰。对于从零开始的预训练,PPL 选择的效果取决于用什么模型来计算 PPL——如果用一个已有的通用模型作为参照,仍然可以从中获得”信息增量”的信号。
5.4 多维度质量评分
综合评分框架
实际生产中,最好不要依赖单一的质量指标,而是构建一个多维度的质量评分体系。
class QualityScorer:
def __init__(self):
self.ppl_model = load_kenlm_model()
self.edu_classifier = load_edu_classifier()
self.safety_classifier = load_safety_classifier()
def score(self, text: str) -> dict:
"""多维度质量评分"""
# 维度1: 语言流畅性 (基于PPL)
ppl = self.compute_ppl(text)
fluency_score = self.ppl_to_score(ppl) # PPL越低分越高,但极低也扣分
# 维度2: 教育价值
edu_score = self.edu_classifier.predict(text)
# 维度3: 信息密度 (简单启发式)
density_score = self.compute_info_density(text)
# 维度4: 安全性
safety_score = self.safety_classifier.predict(text)
# 综合分数 (加权平均)
weights = {
'fluency': 0.2,
'education': 0.35,
'density': 0.25,
'safety': 0.2,
}
overall = (
weights['fluency'] * fluency_score +
weights['education'] * edu_score +
weights['density'] * density_score +
weights['safety'] * safety_score
)
return {
'fluency': fluency_score,
'education': edu_score,
'density': density_score,
'safety': safety_score,
'overall': overall,
}
def compute_info_density(self, text: str) -> float:
"""启发式信息密度评估"""
# 唯一词比例(type-token ratio的简化版)
chars = list(text)
unique_ratio = len(set(chars)) / max(len(chars), 1)
# 命名实体密度(简化:用数字和英文的比例作为代理)
knowledge_markers = len(re.findall(r'[\d]|[a-zA-Z]{3,}', text))
knowledge_density = knowledge_markers / max(len(text), 1)
# 段落结构(有结构的文本通常信息密度更高)
paragraphs = [p for p in text.split('\n') if p.strip()]
structure_score = min(len(paragraphs) / 10, 1.0)
return (unique_ratio * 0.4 + knowledge_density * 0.3 +
structure_score * 0.3)
安全维度的工业实践:上面代码中的 safety_classifier 看起来只是一行调用,但实际生产中安全过滤的设计远比这复杂。Anthropic 2025 年发表的预训练安全过滤研究提供了一个完整的工业案例:
- 分类方法对比:他们实验了 6 种分类方法——包括微调语言模型、宪法分类器(Constitutional Classifier)、FastText、字符串匹配等。最终选择了微调宪法分类器作为精度与成本的最佳平衡方案
- 效果验证:在中等规模模型上,安全过滤将有害能力评估得分降低了 33%,同时标准基准测试性能无显著下降
- 反直觉发现:单一高质量分类器优于多分类器组合策略。多个分类器组合虽然覆盖面更广,但引入了更多的假阳性(把正常内容误判为有害),反而降低了整体效果
这个发现与 CQF 质量幻觉的研究(5.2 节)形成了有趣的对比——在安全过滤领域,“少即是多”可能是更好的策略。
质量评估的人工抽样方法论
模型打分归模型打分,人工抽样评估是不可替代的验证手段。
抽样策略:
1. 从质量分数的不同区间各抽取样本:
- 高分区 (>0.8): 100 条 → 验证"好数据确实好"
- 中分区 (0.5-0.8): 200 条 → 这是最关键的区间
- 低分区 (<0.5): 100 条 → 验证"差数据确实差"
- 边界区 (0.45-0.55): 100 条 → 检查过滤阈值的合理性
2. 每条样本由 2-3 人独立评估
- 使用标准化评估表(1-5分,多维度)
- 计算标注一致性(Cohen's Kappa ≥ 0.6 为可接受)
3. 分析结果
- 分类器在每个区间的准确率
- 假阳性分析(被过滤掉的好数据 → 损失)
- 假阴性分析(通过过滤的差数据 → 风险)
Cohen’s Kappa 的解读:
| Kappa 值 | 一致性水平 | 建议 |
|---|---|---|
| < 0.2 | 几乎没有一致性 | 标注指南需要重写 |
| 0.2-0.4 | 一般 | 需要改善标注指南 |
| 0.4-0.6 | 中等 | 可以接受但需要改善 |
| 0.6-0.8 | 较好 | 标注质量合格 |
| > 0.8 | 很好 | 标注质量优秀 |
从独立评分到联合优化:QuaDMix 范式
上面的评分框架将质量评估分解为多个独立维度,然后用加权平均得到综合分数。但这种”先打分、再过滤”的两阶段方法有一个隐含假设:质量和多样性可以分开处理——先用分类器过滤出高质量数据,再在后续的数据混合阶段(第 6 章)考虑多样性。
字节跳动提出的 QuaDMix 框架挑战了这一假设:单纯最大化质量分数会牺牲多样性,而质量和多样性需要在同一框架下联合优化。
QuaDMix 的核心设计:
- 参数化采样函数:不是用固定阈值过滤,而是为每条数据计算一个采样概率,该概率同时考虑质量标签和多样性标签
- 多维度质量评估 + 领域分类:用多个质量评估器打分,同时对数据进行领域分类以度量多样性
- 高效参数搜索:用 LightGBM 在小模型上快速搜索最优的质量-多样性平衡参数,然后将策略迁移到大模型
实验结果:联合优化策略在下游任务上平均提升 7.2%,显著优于先过滤后混合的两阶段策略。
实践启示:从”评分 → 阈值过滤”到”评分 → 概率采样”的转变意味着,质量过滤的输出不一定是”保留/丢弃”的二元决策,也可以是一个采样权重,让高质量数据有更高的采样概率,但不完全排除中等质量数据——这天然地在质量和多样性之间取得平衡。
关于隐式过滤风险(2026 新发现):Nait Saada 等人的研究在机制层面解释了上述现象——CQF 训练的分类器会隐式过滤掉参考集中约 5-15% 的样本(具体数字因数据集而异,详见 §5.7 发现 6)。这意味着过滤后的数据并不等同于”真正的高质量数据”加上”被过滤掉的部分”——分类器在参考集上同样会产生假阴性。QuaDMix 的概率采样策略相比硬阈值,在缓解”隐式过滤参考集”问题上更具鲁棒性。
5.5 质量过滤的 Scaling Law
数据量 vs 质量的 Trade-off
质量过滤本质上是一个数据量和数据质量的权衡:过滤越严格,保留的数据质量越高,但量越少。
这个权衡不是线性的。它遵循一个类似 S 曲线的规律:
模型性能
↑
│ ╭─────── 质量上限
│ ╱
│ ╱
│ ╱
│ ╱
│ ╱
│ ╱
│╱
├────────────────→ 过滤严格程度
│
│ ← 此区间过滤收益大 → ← 过度过滤,收益递减甚至为负 →
关键拐点:存在一个”甜蜜点”(sweet spot),在这个点上过滤带来的质量提升恰好平衡了数据量减少带来的损失。超过这个点,继续加严过滤会导致模型性能反而下降。
质量感知 Scaling Law:从定性直觉到数学框架
上面的 S 曲线提供了定性直觉,但长期以来缺乏数学化的描述。2026 年,ICLR 2026 上的一项研究首次将数据质量作为显式变量纳入了 Scaling Law 框架。
经典的 Chinchilla Scaling Law 描述的是 Loss = f(N, D),即模型损失是模型规模 N 和数据量 D 的函数。质量感知 Scaling Law 将其扩展为:
Loss = f(N, D, Q)
其中 Q 是一个无量纲的数据质量参数。论文提出了两种实用的 Q 估算方法:
| 方法 | 思路 | 适用场景 |
|---|---|---|
| 损坏率代理 | 向数据中注入已知比例的噪声,观察损失变化 | 受控实验、数据管线评估 |
| 缺陷度量 | 用一组质量指标的加权组合估算 Q | 大规模生产环境 |
关键发现:
- 有效数据随质量下降呈次线性衰减。这意味着少量低质量数据的影响并不严重——模型不会因为 5% 的噪声而崩溃
- 模型对中等程度的数据损坏具有鲁棒性。这为”适度放宽过滤标准以保留更多数据”提供了理论支撑
- 质量投资的边际效益可量化。通过 f(N, D, Q),可以计算将数据质量从 Q₁ 提升到 Q₂ 带来的损失降低,并与获取更多数据或增加模型规模进行成本比较
这个框架的实际意义是:当你面临”提升数据质量”还是”获取更多数据”的决策时,不再只能靠直觉,而是有了定量分析的工具。
发现 5(补充):合成数据的过度重复会引发性能回退。标准质量感知 Scaling Law 未充分考虑重复(over-training)效应。InfoLaw(arXiv: 2605.02364, 2026)提出,质量加权数据混合 + 重复次数的联合 Scaling Law 表明:在数据受限的过度训练场景下,增加高质量数据的上采样权重会加剧重复,反而降低性能。这为合成数据的最佳配比提供了更精确的决策边界——最优配比不仅取决于质量分数,还取决于是否处于过度训练区间。
“数据墙”(Data Wall)的概念
随着模型规模和训练 token 数的持续增长,一个越来越严峻的问题是:高质量数据可能不够用了。
这就是所谓的”数据墙”:
- 互联网上的高质量英文文本总量约在 10-15T token
- 中文的高质量文本可能只有 2-3T token
- 经过严格质量过滤后,可用的高质量数据可能更少
应对数据墙的策略:
- 放宽质量过滤标准——接受”中等质量”的数据,扩大数据量
- 合成数据混入——Meta 团队训练了超 1000 个 LLM(超 10 万 GPU 小时),发现了明确的实践指导:
- 最佳配比:约 1/3 改写型合成数据 + 2/3 自然数据,可将训练效率提高 5-10 倍
- 类型很重要:改写型合成数据(对自然文本进行改写润色)是安全的,但纯生成型(如纯教科书风格数据)在小数据预算下会导致多领域验证损失升高,甚至引发模型崩溃
- 生成器规模:8B 参数的生成器是性价比最优选择——更大的模型并不一定带来更好的合成数据
- 关键区分:改写型不导致模型崩溃(因为保留了自然文本的统计特征),但纯生成型会(因为合成数据的分布会逐代收窄)
- 更详细的合成数据讨论见第 17 章
- 多次 epoch——在高质量数据上多次训练(但有记忆化风险)
- 数据回收——重新审视被过滤掉的数据,恢复被误杀的内容
- 高效验证策略 ——通过降低数据质量探索的成本(如 Ultra-FineWeb 的高效注入验证,加速比 50-100x),使得在有限数据预算下更高效地搜索最优数据配方成为可能。验证效率的提升间接缓解数据墙问题——同样的计算资源可以评估更多候选数据策略,找到质量与数量的更优平衡点
FineWeb 团队的三代过滤范式
FineWeb 团队在大量消融实验后,总结了质量过滤范式的演变:
第一代:纯启发式规则
- 代表:C4、OSCAR
- 方法:长度阈值、字符比例、坏词列表等规则
- 优点:简单、快速、可解释
- 缺点:粗糙,大量误杀和遗漏
第二代:模型打分
- 代表:DCLM、FineWeb-Edu
- 方法:用分类器或 LLM 给文本打质量分,按分数过滤
- 优点:比规则更精准
- 缺点:依赖打分模型的偏差,可能导致数据多样性下降
第三代:混合式 + 被误过滤数据的恢复
- 代表:FineWeb(最终版)
- 方法:
- 宽松的启发式规则做初筛(去掉明显的垃圾)
- 质量分类器做精筛(保留高分数据)
- 关键创新:从被过滤掉的数据中恢复误杀的好数据
- 用不同的分类器或不同的标准重新审查被过滤的数据
- 把其中被错误过滤的数据加回来
- 优点:在质量和多样性之间取得更好的平衡
- 这个”恢复”步骤是 FineWeb 团队的重要发现之一
Ultra-FineWeb:新一代数据集标杆
在 FineWeb 之后,Ultra-FineWeb(OpenBMB/清华/ModelBest, 2025)代表了高质量预训练 Web 数据集的最新进展:
数据集规模:
- Ultra-FineWeb-en:~1T tokens(英文)
- Ultra-FineWeb-zh:~120B tokens(中文)
与 FineWeb/FineWeb-Edu 的关键区别:
| 维度 | FineWeb-Edu | Ultra-FineWeb |
|---|---|---|
| 分类器 | LLM 教育价值分类器(需 GPU) | fastText 轻量分类器(CPU 可运行) |
| 验证方法 | 完整训练验证 | 高效注入验证(50-100x 加速) |
| 种子选择 | 人工标注 | 验证驱动的自动优化 |
| 多语言 | 仅英文 | 英文 + 中文 |
| 实际应用 | 开源基准 | MiniCPM4 核心预训练数据 |
实践意义:Ultra-FineWeb 的 fastText 分类器选择特别值得注意——它证明了在高效验证策略的指导下,轻量分类器可以达到与 LLM 分类器相当的效果。这对于计算资源有限的团队是一个重要信号:关键不在于分类器有多强,而在于验证策略有多高效。
分类器和数据集已在 HuggingFace 发布(openbmb/Ultra-FineWeb-classifier),2025 年 5 月曾登上 HuggingFace Datasets Trending #1。
5.6 过滤管线的组合与评估
将质量过滤融入完整管线
质量过滤不是孤立的步骤。它需要与第3章的清洗和第4章的去重协调工作。
推荐的管线顺序:
原始数据
│
▼
[第3章] 文本提取 + 基础清洗 + 语言过滤
│
▼
[第4章] 精确去重 + 模糊去重
│
▼
[第5章] 质量过滤
│ ├─ 启发式初筛(去掉明显垃圾)
│ ├─ 模型精筛(质量分类器 / PPL 过滤)
│ └─ 误杀恢复(从被过滤的数据中恢复好数据)
│
▼
高质量训练数据
为什么质量过滤在去重之后?
- 去重后数据量显著减少(通常减 20-40%),质量过滤的计算量也相应减少
- 去重后每条文档的”代表性”更强——一条文档不再代表多个重复副本
- 避免”去重保留了低质量副本而丢弃了高质量副本”的问题
消融测试:确认每个步骤的贡献
方法:逐步关闭管线中的各个步骤,观察最终模型性能的变化。
实验设计示例:
基准管线(完整): 模型分数 = 65.2
去掉启发式过滤: 模型分数 = 63.7 → 贡献 +1.5
去掉质量分类器: 模型分数 = 62.1 → 贡献 +3.1
去掉PPL过滤: 模型分数 = 64.8 → 贡献 +0.4
去掉误杀恢复: 模型分数 = 64.5 → 贡献 +0.7
全部去掉(只做基础清洗): 模型分数 = 60.3 → 质量过滤总贡献 +4.9
分析:
- 质量分类器贡献最大 (+3.1)
- 启发式过滤仍有价值 (+1.5)
- PPL 过滤在分类器之上的增量较小 (+0.4) → 可以考虑简化
- 误杀恢复是值得做的 (+0.7)
5.7 反直觉发现合集
本章结束前,总结几个在质量过滤领域被反复验证的反直觉发现:
发现 1:训练 token 减半,模型更好
在多项研究中,用质量过滤器过滤掉 40-60% 的数据后,模型在 benchmark 上的表现反而优于用全量数据训练的版本。不是所有 token 都平等——低质量的 token 不仅没有贡献,还会拖累模型。
发现 2:过滤器自身的偏差会被放大
如果你的质量分类器是用维基百科作为正例训练的,它会倾向于保留”像维基百科”的文本。然后用这些数据训练出的模型会产出”百科全书腔”的回答。分类器的偏差 → 训练数据的偏差 → 模型的偏差,形成放大效应。
发现 3:被过滤掉的数据中有宝藏
FineWeb 团队在检查被过滤掉的数据时发现,其中约 10-20% 其实是有价值的。这些数据被过滤是因为它们的”形式”不符合分类器的预期(如论坛帖子的格式、口语化的表达),但”内容”是有信息量的。
发现 4:PPL 太低比太高更危险
高 PPL 的文本你一眼就能看出问题(乱码、外语)。但低 PPL 的文本看起来”正常”,可能逃过人工审查。然而这些文本可能是高度模板化、重复度高的内容,对模型的训练贡献为负。
发现 5:最优过滤策略随模型规模变化
小模型(如 400M)上的最优过滤策略,扩展到大模型(如 70B)上可能不是最优的。大模型对噪声的容忍度更高(能从噪声中提取信号的能力更强),但也更容易记忆重复内容。因此,proxy 实验的结果不能盲目外推。
发现 6:CQF 范式的根本性质疑(Removing Noise, not Finding Gold)
2026 年 6 月,Nait Saada、Bethune、Klein、Grangier、Cuturi、Ablin(Apple + 巴黎萨克雷大学,arXiv:2510.00866v3)发表 “Removing Noise, not Finding Gold” 工作,从更深的层次挑战了 CQF 范式:
- 核心实验:他们训练”通过随机 token 排列获得质量递增的合成数据”的模型,与 CQF 过滤后的模型对比,观察语言建模能力随质量分数的变化
- 反直觉结论:CQF 虽然能提升下游任务表现,但不一定能提升高质量数据上的语言建模能力。当 perplexity 在真正的高质量 holdout 集上测量时,CQF 模型的”质量优势”部分消失
- 机制解释:CQF 会隐式地把”高质量参考集”中的部分样本也过滤掉——质量分数是相对于训练集分布的,而非绝对的”高质量”度量。换句话说,CQF 捕获的更像是”与高质量分布的相似度”,而非”真正的质量”
这一发现与 §5.2 提到的 Apple 牛津 “The Data-Quality Illusion” 工作形成证据链:
- Apple 工作:CQF 捕获的是”分布差异”而非”语义质量”
- Nait Saada 工作:CQF 隐式过滤了高质量参考集本身,CQF 模型的”质量提升”在高质量 holdout 上部分消失
对实践的影响:
- FineWeb-Edu、CPQS-Tuning、Ultra-FineWeb 等基于 CQF 的工作仍然是有效的——它们训练出的模型在下游任务上确实更好
- 但 CQF 提升的可能是”下游任务适配度”而非”对高质量内容的建模能力”
- 在评估”质量过滤收益”时,建议同时报告下游 benchmark 和高质量 holdout 的 PPL 变化
ScalingFilter(Li et al., 2024)通过两个 LLM 在同数据上的困惑度差异作为质量信号,是一次不依赖参考集的尝试——但目前看仍属”度量相似度”的范畴,未能完全跳出”相对性”陷阱。
发现 7:MIRA 框架——把 CQF 思想推广到中训练
2026 年 5 月,北航/上海交大/UBC/IQuest/澜舟科技(Wang et al.)发表 MIRA(Mid-training Rubric Anchoring for Source-Aware Data Selection) 框架,把”质量分类器 + 多维评分”思想推广到中训练数据筛选:
- 核心创新是”自锚定 rubric 发现”——自动发现每个数据源组应该评估的特定维度,再蒸馏到可扩展的学生评分器
- 在 21 个数据源 / 5 个源组的代码中训练上,使用半量 token 即可匹配全量训练效果
- 对 CQF 范式的”全球统一标准”局限是直接回应——评分标准本身随数据源变化而调整
MIRA 的”自锚定”思路与本章 CQF 讨论的”相对性陷阱”形成方法学对照:MIRA 承认”高质量是数据源相关的”,并在机制层面解决了这个问题。详见 Ch08 §8.x MIRA 框架。
5.8 局限与开放问题
本章最后,把当前质量过滤领域尚未解决的关键开放问题做一份清单,供后续研究者参考:
| 开放问题 | 当前最优应对 | 局限 |
|---|---|---|
| ”质量”的 intrinsic 度量 | ScalingFilter、困惑度差异 | 仍是”相对性”度量 |
| CQF 的”伪影”问题 | 多分类器组合、误杀恢复 | 仍未根除 |
| 中训练场景的源特定质量 | MIRA 自锚定 rubric | 仅在代码中训练验证 |
| 多语言质量度量 | 跨语言迁移(XLM-R 等) | 低资源语言仍薄弱 |
| 质量过滤与多样性权衡 | QuaDMix 联合优化 | 多样性度量本身不统一 |
本章核心提示:质量过滤不是”找到金子”,而是”减少噪声”。认识到这一点,是从”调阈值”走向”理解系统”的开始。
动手环节:构建一个数据质量评分器并验证过滤效果
目标:实现一个多维度的文本质量评分器,并通过消融实验验证不同过滤策略的效果。
练习 1:多维度质量评分器
"""
实现本章介绍的多维度质量评分框架
不需要外部模型,用纯启发式方法实现
"""
import re
import math
from collections import Counter
from typing import List
class SimpleQualityScorer:
"""基于启发式的多维度质量评分器"""
def score(self, text: str) -> dict:
scores = {
"fluency": self._score_fluency(text),
"info_density": self._score_info_density(text),
"structure": self._score_structure(text),
"repetition": self._score_repetition(text),
}
# 加权综合分
weights = {"fluency": 0.25, "info_density": 0.35,
"structure": 0.2, "repetition": 0.2}
scores["overall"] = sum(scores[k] * weights[k] for k in weights)
return scores
def _score_fluency(self, text: str) -> float:
"""语言流畅性(基于标点和句子结构)"""
sentences = re.split(r'[。!?.!?]', text)
sentences = [s.strip() for s in sentences if len(s.strip()) > 5]
if not sentences:
return 0.1
# 句子长度的合理性(太短或太长都扣分)
lengths = [len(s) for s in sentences]
avg_len = sum(lengths) / len(lengths)
if 10 <= avg_len <= 100:
len_score = 1.0
elif avg_len < 10:
len_score = avg_len / 10
else:
len_score = max(0.3, 1 - (avg_len - 100) / 500)
# 标点密度(正常中文约 5-15% 标点)
punct_count = len(re.findall(r'[,。!?、;:""''()【】]', text))
punct_ratio = punct_count / max(len(text), 1)
if 0.03 <= punct_ratio <= 0.15:
punct_score = 1.0
else:
punct_score = 0.5
return (len_score * 0.6 + punct_score * 0.4)
def _score_info_density(self, text: str) -> float:
"""信息密度评分"""
chars = list(text)
if len(chars) < 10:
return 0.1
# Type-Token Ratio
ttr = len(set(chars)) / len(chars)
# 知识标记密度(数字、英文术语、专有名词特征)
knowledge_markers = len(re.findall(
r'\d+|[a-zA-Z]{3,}|[A-Z]{2,}', text
))
marker_density = min(knowledge_markers / (len(text) / 100), 1.0)
return ttr * 0.6 + marker_density * 0.4
def _score_structure(self, text: str) -> float:
"""结构性评分"""
lines = text.split('\n')
non_empty = [l for l in lines if l.strip()]
if len(non_empty) < 2:
return 0.3
# 段落存在性
has_paragraphs = len(non_empty) >= 3
# 标题存在性
has_headers = any(l.strip().startswith('#') for l in non_empty)
# 列表存在性
has_lists = any(re.match(r'\s*[-•·\d]+[.、)]', l) for l in non_empty)
score = 0.4 # 基础分
if has_paragraphs: score += 0.2
if has_headers: score += 0.2
if has_lists: score += 0.2
return min(score, 1.0)
def _score_repetition(self, text: str) -> float:
"""重复度评分(越不重复越好)"""
# 基于 3-gram 的重复率
chars = list(text)
if len(chars) < 10:
return 0.5
trigrams = [tuple(chars[i:i+3]) for i in range(len(chars)-2)]
unique_ratio = len(set(trigrams)) / max(len(trigrams), 1)
return min(unique_ratio * 1.2, 1.0)
# === 测试 ===
scorer = SimpleQualityScorer()
test_texts = {
"高质量文章": (
"大语言模型的训练数据质量是决定模型性能的关键因素。\n\n"
"## 三个关键维度\n\n"
"1. 数据的多样性:覆盖不同领域和主题\n"
"2. 数据的准确性:事实正确、逻辑自洽\n"
"3. 数据的清洁度:无噪声、无重复、无 PII\n\n"
"FineWeb 团队的研究表明,精心设计的数据管线可以让模型在 MMLU 上提升 3-5 个百分点。"
),
"SEO垃圾": (
"最好的减肥方法 快速减肥 如何减肥 减肥食谱 减肥运动 "
"最有效减肥方法 减肥秘诀 减肥方法大全 快速减肥秘诀 "
"减肥食谱推荐 减肥运动推荐 减肥方法 减肥 减肥 减肥"
),
"正常论坛": (
"我最近在用 PyTorch 训练一个 NLP 模型,遇到了一个问题。"
"训练 loss 一直在震荡,不收敛。学习率用的是 1e-3,"
"batch size 是 32。有人知道可能是什么原因吗?"
),
}
print(f"{'类型':<12} {'流畅':>6} {'信息':>6} {'结构':>6} {'重复':>6} {'综合':>6}")
print("-" * 50)
for name, text in test_texts.items():
s = scorer.score(text)
print(f"{name:<12} {s['fluency']:>6.2f} {s['info_density']:>6.2f} "
f"{s['structure']:>6.2f} {s['repetition']:>6.2f} {s['overall']:>6.2f}")
练习 2:PPL 双边过滤实验
"""
验证本章 5.3 节的核心发现:PPL 过滤应该是双边的
用字符级 n-gram 模型模拟困惑度计算
"""
def char_bigram_ppl(text: str, reference_text: str) -> float:
"""用参考文本的 bigram 模型计算目标文本的 PPL"""
# 训练 bigram 模型
chars = list(reference_text)
bigram_counts = Counter()
unigram_counts = Counter()
for c in chars:
unigram_counts[c] += 1
for i in range(len(chars)-1):
bigram_counts[(chars[i], chars[i+1])] += 1
# 计算 PPL
vocab_size = len(unigram_counts)
target_chars = list(text)
log_prob = 0
n_tokens = 0
for i in range(len(target_chars)-1):
bg = (target_chars[i], target_chars[i+1])
prob = (bigram_counts.get(bg, 0) + 1) / (unigram_counts.get(target_chars[i], 0) + vocab_size)
log_prob += math.log2(prob)
n_tokens += 1
return 2 ** (-log_prob / max(n_tokens, 1))
# 参考语料(模拟维基百科风格的正常中文)
reference = ("自然语言处理是人工智能的重要分支。"
"深度学习技术推动了该领域的快速发展。"
"预训练语言模型如 BERT 和 GPT 取得了突破性进展。") * 50
texts = {
"正常文本": "机器学习是从数据中自动学习规律的方法。深度学习是机器学习的一个分支。",
"模板化文本": "是的是的是的是的是的是的是的是的是的是的是的是的是的是的。",
"乱码文本": "asdfgh jklqwe rtyuio zxcvbn 123456 !@#$%^ 乱码内容随机字符",
"高质量技术": "Transformer 的自注意力机制允许模型在 O(n²) 复杂度下捕获长距离依赖关系。",
}
print(f"{'类型':<12} {'PPL':>10} {'建议':<15}")
print("-" * 40)
for name, text in texts.items():
ppl = char_bigram_ppl(text, reference)
if ppl < 30:
advice = "⚠️ PPL 过低(可能模板化)"
elif ppl > 1000:
advice = "⚠️ PPL 过高(可能乱码)"
else:
advice = "✅ PPL 适中(保留)"
print(f"{name:<12} {ppl:>10.1f} {advice}")
# 思考题:为什么 PPL 过低反而是问题?
# 参考本章 5.3 节的"反直觉发现 1"。
练习 3:过滤阈值消融实验
设计一个实验:准备 100 条文本样本(50 条好、50 条差),用你的质量评分器在不同阈值下过滤,统计准确率、召回率和 F1:
# 伪代码框架
thresholds = [0.3, 0.4, 0.5, 0.6, 0.7, 0.8]
for threshold in thresholds:
# 用 scorer.score(text)["overall"] > threshold 来判断
# 统计 TP, FP, FN, TN
# 计算 Precision, Recall, F1
pass
# 画出 Precision-Recall 曲线,找到你的"甜蜜点"
思考题:如果你的过滤器在”好数据”上的 recall 从 95% 提高到 99%,但 precision 从 80% 降到 60%,这个交换在万亿 token 场景下值得吗?(提示:考虑 FineWeb 的”被过滤数据中有 10-20% 的宝藏”这一发现。)
本章要点回顾
- “高质量”没有统一定义——它取决于你的训练目标。数据质量是 (数据, 目标) 的联合函数
- 三代过滤范式:纯规则 → 模型打分 → 混合式+误杀恢复
- 质量分类器的选择:fastText 快但粗,教育价值分类器精但有偏差,DCLM 方法论最严谨但成本高
- CQF 的”质量幻觉”——分类器学到的可能是分布差异而非语义质量,CQF 仍然有效但原因可能不是我们以为的那样
- PPL 过滤要双边——既过滤高 PPL(乱码)也过滤极低 PPL(模板化/重复内容);更进一步,PPL 可以从”过滤工具”升级为”选择工具”
- 质量和多样性需要联合优化——先打分再过滤的两阶段方法可能不如联合优化(如 QuaDMix)
- 质量感知 Scaling Law——Loss = f(N, D, Q) 首次将数据质量 Q 作为显式变量纳入 Scaling Law,为决策提供数学支撑
- 合成数据混入有明确配比——约 30% 改写型合成数据 + 70% 自然数据是当前最佳实践,但纯生成型有模型崩溃风险
- 人工抽样不可替代——模型打分只是自动化手段,最终的质量判断需要人来做
- 核心反直觉:训练数据减半但模型更好;被过滤的数据中有宝藏;分类器的偏差会被放大
- 高效验证策略将数据质量探索从昂贵实验变为快速迭代——关键不在分类器多强,而在于验证策略多高效
- 多语言过滤进入统一框架时代——FineWeb-2 用 15% 的 token 即可匹配基线,跨语言迁移使低资源语言也能获得可靠过滤