MinHash(最小哈希)是一种把集合压成很短"指纹"的方法,让两个集合的相似度可以在不逐元素比对的情况下被快速估算。它是海量文本去重、近重复(near-duplicate)检测里最常用的底层技术之一。
它解决什么问题
比较两篇文章像不像,常见做法是把文章切成词的片段(比如每 5 个连续词一组,称为 shingle),得到一个集合,再用 Jaccard 相似度衡量:两篇文档共有的片段数 ÷ 两者片段并集的大小。这个值在 0 到 1 之间,越接近 1 越像。
问题在于,如果有一亿篇文档,两两比对就是天文数字。而且集合本身很大,存下来也贵。MinHash 的作用就是:把任意大的集合,压成固定长度(比如 128 个数字)的签名,并且让签名"保留"原来的相似度。
原理:换个比方
想象你要比较两个人的书架有多像,但不许逐本对照。办法是事先定好一批"抽书规则":按书名拼音排序取第一本、按作者姓氏排序取第一本、按出版年份取最早的一本……每人都按同一套规则各报出一组答案。
直觉上:两人的藏书重合度越高,用同一条规则抽出来的书越可能是同一本。MinHash 正是把这个直觉精确化——每条"规则"就是一个哈希函数,取集合中所有元素哈希值的最小值。数学上可以证明:两个集合的 MinHash 签名在任意一个位置上相等的概率,恰好等于它们的 Jaccard 相似度。所以只要签名够长,统计"有多少位置相同",就能得到一个无偏且误差可控的估计。
实践中不会真的设计几百个独立哈希函数,而是用一组形如 (a*x + b) mod p 的通用哈希函数来模拟,计算一次哈希即可复用到多个签名位。
签名拿到后,通常再配合分桶(banding):把签名切成若干段,只要有一段完全相同,就把这对文档列为候选,再精算。这样连"两两比对签名"这一步都省了,复杂度从平方级降到接近线性。
和相邻概念的区别
| 方法 | 相似度定义 | 输出 | 典型用途 |
|---|---|---|---|
| MinHash | 集合的 Jaccard 相似度 | 固定长度整数签名 | 文本去重、近重复检测 |
| SimHash | 向量AI 词典:余弦相似度">余弦相似度(近似) | 一个二进制指纹,比汉明距离 | 网页去重 |
| 普通哈希 | 不衡量相似度 | 精确查找的键 | 去重(完全相同才算) |
| 词嵌入 | 语义相似度 | 稠密向量 | 语义检索、聚类 |
关键差别在于:MinHash 和 SimHash 都是"字面相似",不理解语义。把"我今天很开心"改写成"今日心情不错",MinHash 基本看不出来;但同一个模板生成的网页、互相抄改的新闻稿、代码里的复制粘贴,它抓得非常准。真正的语义近重复要靠嵌入向量。
对实际工作的意义
对工程师来说,MinHash 是那种"成本极低、收益极大"的工具:训练语料清洗、爬虫结果去重、论文查重、推荐系统的相似物品召回,都能用它先把候选集砍掉九成以上。要注意两点:签名长度决定精度,太短会把不相似的判成相似;分桶参数决定召回与精度的权衡,需要按业务调。另外,它只对"集合重叠"敏感,对词序和语义不敏感,选它之前先想清楚你要的到底是哪一种"像"。
