🧠 图解记忆:MinHash 估 Jaccard,SimHash 比汉明距离,LSH 先召回再精判;点击图片可查看原图。
数据去重 = 移除训练数据集中重复或高度相似的文档,避免模型过度拟合重复内容。
为什么去重很重要?
现实情况:互联网爬取的网页中有大量重复内容
- Wikipedia 多语言镜像互相翻译 → 高度相似
- 新闻网站的转载链 → 同一篇新闻多次出现
- Reddit/StackOverflow → 同一个问题多次提出
不去重的后果:
- 某个热点话题的 1000 条重复帖子让模型过度偏向这个话题
- 模型记住的是「这篇文章出现过 1000 次」而非「这个知识点」
- 训练效率低下:大量 Token 浪费在了重复数据上常见的去重策略对比
| 方法 | 原理 | 速度 | 检测精度 | 适用规模 |
|---|---|---|---|---|
| Exact Dedup(精确去重) | MD5/SHA hash 完全相同的文档 | 最快 | 100% 精确 | 任何规模 |
| SimHash(局部敏感哈希) | 文档指纹比对,汉明距离 ≤ 3 判为相似 | 快 | 较高 | 百万~千万级 |
| MinHash + LSH(最佳实践⭐) | MinHash 估计 Jaccard 相似 + LSH 桶分组 | 中等 | 最高 | 十亿级(工业标配) |
| Semantic Dedup | 用 Embedding 相似度聚类 | 慢 | 最高 | 小规模精排 |
MinHash + LSH 流程(面试重点)
Step 1: MinHash — 将每篇文档转为固定长度的签名向量
- 将文档拆成 shingle(连续 n-gram,如 5-gram)
- 用多组哈希函数计算每组的 min hash 值
- 得到一个签名向量(如 128 个整数)
关键性质:两个文档签名的 Hamming 距离 ≈ Jaccard 相似度
两个文档的签名向量相等概率 = 它们的 Jaccard 相似度
Step 2: LSH(Locality-Sensitive Hashing)— 高效近似最近邻搜索
- 将签名向量分成 b 行 r 列(b 组 band,每组 r 个 signature)
- 对每个 band 计算 hash,同 band 内 hash 相同则进入同一桶
- 同一桶内的文档对视为候选重复对
参数权衡:
- r 越大 → 误报越少但漏报越多
- b 越大 → 漏报越少但计算量越大
行业经验:r=8~20, b=15~40,根据数据规模和硬件调整实际应用案例
python
# Gopher (Google 2022) 的数据去重策略
# 对 3T tokens 进行 MinHash dedup
# - 精确去重:消除完全重复
# - 语义去重:消除翻译镜像和高度相似页面
# - 结果:原始数据量减少了约 20%
# The Pile (EleutherAI) 的去重策略
# 使用了 MinHash + LSH 对每个数据集内部去重
# 跨数据集间也进行了粗略去重工程最佳实践
- 先精确再去近:先做 exact dedup 剔除完全重复,再做 MinHash 找相似
- 按域去重:Wikipedia 之间互相比,新闻站之间互相比,不跨域比对
- 保留高质版本:相似文档对保留质量更高/更新的一个(比如带日期戳的)
- 定期迭代:随着新数据入库,增量更新去重索引
面试话术:
示例表达(仅在能用本人经历或可复现实验佐证时使用): "去重看起来是个 boring 的工程活,但它直接影响模型质量和训练效率。工业界标配是 MinHash+LSH:先把每篇文档压缩成一个短签名向量,然后用 LSH 高效找出相似文档对。Google 的 Gopher 就是这么做到 3T tokens 的去重,直接减少了 20% 的训练数据。我们在企业知识库微调时也会用类似的思路做数据清洗,不然模型会过度拟合我们自己的 FAQ 重复条目。"
