大规模近似去重背后的 BigCode
Hugging Face 实现了一个使用 MinHash 和局部敏感哈希(LSH)的大规模近似去重流水线,以提升 BigCode 项目训练数据的质量。该过程通过减少基准污染、降低隐私风险,并通过让模型在更小的数据集上实现相似或更好的性能,从而提升训练效率。
去重在大语言模型训练中的重要性
在大语言模型(LLM)训练中,数据重复会导致多个关键问题,包括模型倾向于逐字输出训练数据以及对隐私攻击的脆弱性增加。有效的去重提供了三大主要优势:
- 训练效率: 模型可以在更少的训练步骤下实现相同或更优的性能。
- 评估完整性: 删除重复数据可防止数据泄漏和基准污染,确保性能提升是真实的,而非模型在训练期间已见过测试数据的结果。
- 可访问性: 缩小数据集的物理规模,使其更易于存储、传输和协作。
技术实现:MinHash 与 LSH
BigCode 使用三步工作流来大规模识别并移除近似重复文档。
1. 分片与指纹生成
该过程从将文本分词为 n-gram(即 shingle)开始。例如,使用词级别的三元组来表示文档。每个 shingle 随后被多次哈希和置换。通过在文档的所有 shingle 上对每次置换取最小哈希值,生成一个 “MinHash” 指纹。此操作的时间复杂度为 $\mathcal{O}(NM)$(其中 $N$ 为文档数量,$M$ 为文档长度),通过并行化实现线性可扩展。
2. 局部敏感哈希(LSH)
为避免对每对文档进行比较的计算成本,LSH 将 MinHash 指纹数组划分为若干 band。共享同一 band 中相同哈希值的文档被归入同一 bucket,并标记为去重的候选对。
3. 重复移除与聚类
一旦识别出候选对,BigCode 使用基于图的方式将重复项聚类为连通分量。虽然流水线的初始版本会再次检查 Jaccard 相似度以过滤误报,但在 “The Stack” 数据集上的实验表明,将所有 LSH 候选对视为真阳性往往能获得最佳的下游模型性能。
使用 Spark 扩展流水线
为处理 TB 级别的数据,Hugging Face 将本地 Python 框架迁移至 Apache Spark。这使得能够进行分布式的 groupBy 操作并实现连通分量检测算法。借助 GCP DataProc,团队在不到四小时的时间内成功去重了 1.4 TB 数据,成本约为每小时 $15。
对模型性能的影响
近似去重对代码模型的质量有显著影响。关键发现包括:
- 数据集规模 vs. 性能: 近似去重使模型在更小的数据集上(例如 3 TB 对比 6 TB)也能取得更好表现。
- 积极去重: 通过降低相似度阈值并增大 shingle 大小(例如从 unigram 到 5-gram),可以进一步提升性能,同时降低误报率。
- 召回率: 降低相似度阈值会提升对高相似度对的召回率,去除更多冗余数据。
局限性与未来方向
近似去重是基础步骤,但并不能取代对有毒性、偏见或个人身份信息(PII)等数据质量的过滤需求。此外,团队指出基准污染仍是一个挑战;例如,MBPP 基准与 GitHub 上常见的 Leetcode 题目有显著相似性。
未来的研究方向包括探索代码的子串去重、检测单篇文档中重复的段落,以及利用模型嵌入进行语义去重,以在多样性和冗余之间取得平衡。