过滤、去重与污染¶
过滤回答“内容是否适合进入候选语料”,去重回答“多少内容提供了重复信号”,污染检查回答“训练数据是否泄漏了评测对象或答案”。三者可以共享索引与相似度工具,但目标、阈值和错误成本不同。
问题分解¶
| 操作 | 比较对象 | 主要风险 |
|---|---|---|
| 规则过滤 | 单文档与明确约束 | 规则过宽、语言偏置 |
| 质量评分 | 文档与训练目标 | 评分器风格偏好、分布漂移 |
| Exact dedup | 规范化后完全相同内容 | 规范化过强或过弱 |
| Near dedup | 局部改写、模板、镜像 | 阈值误删合理相似内容 |
| Decontamination | 训练候选与冻结评测资产 | 改写、翻译、答案与解析泄漏 |
安全过滤也不等于模型安全训练。移除明确不允许的内容是数据边界;研究模型如何处理风险输入,则需要另行设计受控训练集与评测集。
数据契约¶
每个过滤决定应保存:
document_id
input representation and normalizer version
rule / model / index version
score and threshold
decision and reason codes
dedup cluster and representative
review status
不得只保存最终 keep/drop。阈值变化、评分器升级或误删申诉都需要原始分数和原因重放。
近重复与污染至少保留两种表示:
- 适合复核的原始结构和文本;
- 用于匹配的规范化 token、shingle 或 fingerprint。
匹配表示不能覆盖原文,否则无法判断“高相似”来自公共模板、代码样板还是实质重复。
过滤机制¶
硬规则¶
编码错误、空页、模板占比、极端重复、非法控制字符和明确不在范围内的来源适合用确定性规则处理。规则应返回可解释原因,并在每种语言和文档类型上测量保留率。
学习式质量评分¶
分类器或语言模型可以学习比规则更细的质量信号,但其训练集定义了“质量”的偏好。常见失效包括:
- 偏好百科式或自身生成风格;
- 把短文本、方言、低资源语言或专业符号误判为噪声;
- 使用与下游 benchmark 重叠的正例;
- 在新 crawl 或新域上分数失准。
阈值应根据保留预算和 slice-level precision/recall 选择,而不是追求全局分数最大。DataComp-LM 通过固定训练预算比较不同数据筛选方案,说明过滤器的价值最终要由受控训练结果验证。
去重机制¶
Exact dedup¶
在明确的规范化函数 \(f\) 下计算
相同 \(h_d\) 的文档进入同一 cluster。规范化通常可统一换行、Unicode 和确定的空白,但不应默认删除所有标点、数字或代码格式;过强规范化会把不同事实和程序合并。
Near dedup¶
把文档映射为 \(k\)-shingle 集合 \(S(d)\),Jaccard 相似度为
MinHash 满足单个最小哈希碰撞概率等于 Jaccard:
将 signature 分成 \(b\) 个 band、每个 \(r\) 行时,候选对概率近似为
LSH 只负责召回候选,最终仍应使用精确相似度、长度比和结构信息确认。Deduplicating Training Data Makes Language Models Better 展示了训练语料重复与记忆、评测之间的联系,并提供了官方实现。
最小语义实现¶
下面的实现接收两段文本,返回 shingle Jaccard 分数与阈值判断。它对应的是 LSH 召回之后的 精确候选确认:规范化、token 边界、\(k\) 和阈值都显式可见,空文本也有确定语义。
import re
def shingles(text, k=3):
tokens = re.findall(r"\w+|[^\w\s]", text.casefold())
if len(tokens) < k:
return {tuple(tokens)} if tokens else set()
return {tuple(tokens[i:i + k]) for i in range(len(tokens) - k + 1)}
def jaccard(left, right):
union = left | right
return len(left & right) / len(union) if union else 1.0
def confirm_near_duplicate(left, right, threshold=0.8):
score = jaccard(shingles(left), shingles(right))
return score, score >= threshold
assert confirm_near_duplicate("a b c d", "a b c d") == (1.0, True)
score, duplicate = confirm_near_duplicate("a b c d", "a b c e")
assert 0 < score < 1 and not duplicate
真实流水线还要在不同语言与文档结构上校准 tokenizer、长度比和阈值,并用 MinHash/LSH 或倒排索引缩小候选集;这段代码不能替代来源级分组、语义改写检测和人工复核。污染率的置信区间与切片统计可接到评测工具:Cluster bootstrap。
代表样本¶
cluster 代表不应简单取第一条。可按来源使用条件、解析完整度、时间、结构保留和文本质量排序。cluster 成员及理由必须保留,否则删除或来源撤回时无法重选代表。
污染检查¶
benchmark decontamination 的匹配对象至少包括:
- 题干、选项、参考答案和解释;
- 同源题、模板题、翻译与改写;
- 公开 solution、代码测试、仓库 issue 和 harness;
- teacher 或检索系统可访问的答案;
- 开发阶段用于选模板、阈值和 checkpoint 的样本。
只做 exact string match 会漏掉改写污染。Investigating Data Contamination in Modern Benchmarks 表明,经过释义的 benchmark 内容也可能影响测量。匹配结果应分成 exact、near、semantic candidate 和 unknown,语义候选必须抽样人工复核,不能把模型相似度直接当删除真值。
训练内部去重不能替代评测污染检查:一个答案在训练集中只出现一次,仍然足以使对应测试题失去独立性。
正确性与失效¶
- 先切分后去重:同一文档族跨越 train/test,形成泄漏。
- 全语料一个阈值:代码模板、法规、诗歌和网页正文的合理重复结构不同。
- 只看全局保留率:低资源语言可能被几乎清空。
- 保留 cluster 却丢成员:无法处理来源撤回和阈值回溯。
- 质量分数参与 benchmark 选题:评分器可能把答案外观当质量信号。
- 过度去重:删除有意义的多来源证据与语言变体,降低覆盖。
- 去重不足:重复数据抬高某些模式的梯度权重,增加逐字记忆。
何时不应使用近重复删除¶
当重复本身是任务信号,例如日志频率建模、固定格式解析、拼写变体研究或代码模板学习时,不应直接删除全部近重复。可改为 cluster-level weighting、限制每簇上限或在评测切分时分组隔离。小型高质量集合也可先 exact dedup,再用人工 review 处理 near duplicates。
验证¶
- 构造 exact、局部复制、模板相同、语义相同但事实不同的对照对。
- 按语言、领域、长度、来源和文档类型报告候选率、确认率与删除率。
- 对阈值两侧样本做盲审,估计 false positive 与 false negative。
- 比较去重前后的 token 频率、cluster size、验证损失与记忆化切片。
- 用冻结 benchmark 的题干、答案、解释和释义版本分别检索。
- 在新快照上复用相同规则时检查分数漂移,而不是只比较通过率。
过滤后的真实训练权重见数据混合与课程,记忆与抽取风险见记忆化、隐私与删除,污染统计实现见评测工具。