LSH系列2:MinHash&LSH——文档(集合)相似性

MinHash 原理

前言

MinHash 用于比较集合的相似度。

在数据挖掘中,一个最基本的问题就是比较两个集合的相似度。通常通过遍历这两个集合中的所有元素,统计这两个集合中相同元素的个数,来表示集合的相似度;这一步也可以看成特征向量间相似度的计算(欧氏距离,余弦相似度)。

当这两个集合里的元素数量异常大(特征空间维数很大),同时又有很多个集合需要判断两两间的相似度时,传统方法会变得十分耗时,最小哈希(minHash)可以用来解决该问题

Jaccard 相似度

Jaccard 相似度:通过计算交集的相对大小来获得集合之间的相似度。
J a c c a r d ( A , B ) = ∣ A ∩ B ∣ ∣ A ∪ B ∣ Jaccard(A,B) = \frac{|A \cap B|}{|A \cup B|} Jaccard(A,B)=ABAB

Jaccard相似度在如下问题取得较好效果:在大的语料库中寻找文本内容相似的文档,这里主要指字面上的相似,而非语义上的相似。为了识别字面上相似的文档,需要将文档表示为文档中的短字符串集合,Shingling 是构建表示文中的短字符串集合的方法。

  • 文档的 k-shingle 就是文档中出现过的长度为 k 的字符串。
  • 一篇文档表示成 k-shingle 的集合,如文档为字符串”abcdabd“,k = 2,则所有 2-shingle 组成的集合为 {ab,bc,cd,da,bd}。
  • 如果 k 取得太小,大部分长度为 k 的字符串会出现在大部分的文档中,这就会导致相似度较高。对于论文来说,k = 9较为合适。

Shingle 集合非常大,一个 4-shingle 组成的集合也是原始文件的 4 倍,所以集合相似度计算代价很大,MinHash 可以解决这个问题。

MinHash值计算

假设现在有4个集合,分别为S1,S2,S3,S4,其中 S1={a,d}, S2={c}, S3={b,d,e}, S4={a,c,d},所以全集U={a,b,c,d,e}。我们可以构造如下0-1矩阵(特征矩阵),矩阵的列表示各个集合,行表示所有可能的元素:

元素是什么对最后的结果没有什么影响。所以索性用行号来代表Item,行号跟Item是一一相应的,如下:

行号S1S2S3S4
01001
10010
20101
31011
40010

为了得到各集合的最小哈希值,首先对矩阵进行随机行打乱,则某个集合的最小哈希值就等于打乱后的这一列的第一个值为1的行所在的行号(即置换后哪个元素在最前),举例说明,定义一个最小哈希函数 h,用于模拟对矩阵进行随机行打乱,打乱后的0-1矩阵(特征矩阵)为:

如图所示,h(S1)=a,h(S2)=c,h(S3)=b,h(S4)=a。

变换后也可以表示为行号的形式:

行号S1S2S3S4
10010
40010
01001
31011
20101

如图所示,h(S1)=0,h(S2)=2,h(S3)=1,h(S4)=0。

行号也可以是固定不变的,其实是等价的,只不过是一个标志而已,而且一般说行号的话,都是从上往下递增的:

行号S1S2S3S4
00010
10010
21001
31011
40101

这样的话,h(S1)=2,h(S2)=4,h(S3)=0,h(S4)=2。下面都采用这种行号固定的方式。

可以看出,无论是用元素作为第一列,还是用变换的行号作为第一列,还是用固定的行号作为第一列,结果是等价的。因为无论行号是否固定,只是一个标志而已。

在经过随机行打乱后,两个集合的最小哈希值相等的概率等于这两个集合的Jaccard相似度。证明如下:

  • S1和S2的值都为1,记为X;
  • 只有一个值为1,另一个值为0,记为Y;
  • S1和S2的值都为0,记为Z;
  • S1和S2交集的元素个数为x,并集的元素个数为x+y,所以sim(S1,S2) = Jaccard(S1,S2) = x/(x+y)。接下来计算h(S1)=h(S2)的概率,经过随机行打乱后,从上往下扫描,在碰到Y行之前碰到X行的概率为x/(x+y),即h(S1)=h(S2)的概率为x/(x+y)。

MinHash签名及签名矩阵

用一个单词来代表一个文档偶然性会比较大,那么这个时候我们的想法是,能够随机地产生多次变换,取出多个单词来进行比较,也就是进行多次行打乱。

对于每个行打乱方式,每一个集合(文档)都有一个最小哈希值。如果有n个行打乱方式(n一般是一百到数百),每个集合就能产生 n 个最小哈希值,把这些哈希值写成一个列向量,也称为MinHash签名

每个集合(文档)的列向量组合在一起,写成一个矩阵,称为MinHash签名矩阵

当特征矩阵很大,打乱很耗时且需要多次打乱。为了解决这个问题,可以通过一些随机哈希函数来模拟打乱的效果(哈希函数用h1,h2,……,hn表示,一个哈希函数为每个集合产生一个 MinHash 值,所有的 n 个 MinHash 值组成的就是这个集合的 MinHash 签名)。

之前计算 MinHash 值的时候,都是变换矩阵的内容而行号不变,但我们知道运动是相对的,也可以不变矩阵,仅仅变换行号,这样计算量就少了很多,模拟打乱效果时,就采用的这种思想。

模拟打乱效果,生成 MinHash签名矩阵的处理过程如下:

  • S I G ( i , c ) SIG(i,c) SIG(i,c) 表示签名矩阵中第 i 个哈希函数在第 c 列上的元素。
  • 开始时,将所有的 S I G ( i , c ) SIG(i,c) SIG(i,c) 都初始化为 I n f Inf Inf,然后对每一行进行如下处理:
    • 计算 h1®,h2®,……,hn®(这是关于行号的函数).
    • 对于每一列c(每一列对应一个集合):
      • 如果 c 所在的第 r 行为0,则什么都不做;
      • 如果 c 所在的第 r 行不为1,则对于每个 i=1,2,……,n,将 S I G ( i , c ) SIG(i,c) SIG(i,c)置为 m i n { S I G ( i , c ) , h i ( r ) } min\{SIG(i,c), h_i(r)\} min{SIG(i,c),hi(r)}.

举例说明:

这里使用两个哈希函数, x + 1   m o d   5 x + 1 \ mod \ 5 x+1 mod 5 以及 3 x + 1   m o d   5 3x+1\ mod\ 5 3x+1 mod 5.

行号S1S2S3S4 x + 1   m o d   5 x + 1 \ mod \ 5 x+1 mod 5 3 x + 1   m o d   5 3x+1\ mod\ 5 3x+1 mod 5
0100111
1001024
2010132
3101140
4001003

初始化:

哈希函数S1S2S3S4
h 1 h_1 h1 ∞ \infty ∞ \infty ∞ \infty ∞ \infty
h 2 h_2 h2 ∞ \infty ∞ \infty ∞ \infty ∞ \infty

处理第 0 行,其中列 S1 以及 S4 是 1,例如 S I G ( h 1 , S 1 ) > h 0 ( 0 ) SIG(h_1,S1)>h_0(0) SIG(h1,S1)>h0(0),将 S I G ( h 1 , S 1 ) SIG(h_1,S1) SIG(h1,S1)置为 h 0 ( 0 ) = 1 h_0(0)=1 h0(0)=1

哈希函数S1S2S3S4
h 1 h_1 h1 1 1 1 ∞ \infty ∞ \infty 1 1 1
h 2 h_2 h2 1 1 1 ∞ \infty ∞ \infty 1 1 1

处理第 1 行:

哈希函数S1S2S3S4
h 1 h_1 h1 1 1 1 ∞ \infty 2 2 2 1 1 1
h 2 h_2 h2 1 1 1 ∞ \infty 4 4 4 1 1 1

处理第 2 行:

哈希函数S1S2S3S4
h 1 h_1 h1 1 1 1 3 3 3 2 2 2 1 1 1
h 2 h_2 h2 1 1 1 2 2 2 4 4 4 1 1 1

处理第 3 行:

哈希函数S1S2S3S4
h 1 h_1 h1 1 1 1 3 3 3 2 2 2 1 1 1
h 2 h_2 h2 0 0 0 2 2 2 0 0 0 0 0 0

处理第 4 行:

哈希函数S1S2S3S4
h 1 h_1 h1 1 1 1 3 3 3 0 0 0 1 1 1
h 2 h_2 h2 0 0 0 2 2 2 0 0 0 0 0 0

这就是最终的签名矩阵(MinHash签名矩阵),里面每一列都代表对应集合(文档)的哈希签名(MinHash签名),可以计算集合之间的相似度。

S i m ( S 1 , S 3 ) = 0.5 , S i m ( S 1 , S 4 ) = 1 Sim(S1,S3)=0.5,Sim(S1,S4)=1 Sim(S1,S3)=0.5,Sim(S1,S4)=1

局部敏感哈希算法(LSH)

问题来源

这里主要说的是判断文档(集合)相似性中的LSH。

对于集合中元素个数很多,而且有很多集合需要判断相似性的情况,MinHash解决了元素个数很多的集合判断相似性的问题,但是还剩下集合个数很多的问题没有解决,那么给定一组文档,还有MinHash签名矩阵,不去一一计算Hash签名的相似性,怎么快速地寻找与一个查询文档(最)相似的文档呢?

LSH 基本思想

Locality Sensitive Hashing(LSH)。

即使可以使用 MinHash 将大文档压缩成小的哈希签名,当文档数目太大时寻找相似文档对仍然是不可能的,因为需要计算出所有文档的哈希签名,然后两两计算相似度。那么我们能不能只比较那些相似度可能很高的文档,而忽略那些相似性很低的文档之间的比较?

实际上,只需要寻找那些相似性可能很高的文档对,而不是全部文档对。这就是局部敏感哈希

假设文档先表示成 Shingle 集合,通过 MinHash 处理,变成最小哈希签名,所有文档的最小哈希签名组成签名矩阵。基本想法:

  • 把签名矩阵分成子矩阵(行条),使用多次哈希函数。
  • 具有相同部分(某行条中的值相等)的列将被哈希到同一个桶中。
  • 只考察那些哈希到同一个桶里面的列的相似性(这样相似的可能性较大)。

Banding for LSH

把签名矩阵分成 b 个行条(band),每个行条由 r 行组成(假设签名矩阵中有 n 行,那么n = br)。对于每个行条,存在一个哈希函数能够将行条中的每 r 个整数组成的列向量(行条中的每一列)映射到某个桶中,可以对所有行条使用相同的哈希函数,但是每个行条都有独立的桶数组

只要两个集合在某个行条中有落在同一个桶数组中的列,这两个集合就认为可能相似度比较高,就作为后续计算的候选对。

例:现在有一个12行签名矩阵,把这个矩阵分为4个行条,每个行条有3行;为了方便,这里只写出行条1的内容(n = 12, b = 4, r = 3)。

可以看出,行条1中第2列和第4列的内容都为[0,2,1],所以这两列会落在行条1下的相同桶中,因此不论在剩下的3个行条中这两列是否有落在相同桶中,这两个集合都会成为候选对。在行条1中不相等的两列还有另外的3次机会成为候选对,因为他们只需在剩下的3个行条中有一次相等即可。
对于S2,我们仅需要寻找那些桶相同的集合来计算相似度,例如:

我们仅需要计算sim(S2, S3),sim(S2, S4),sim(S2, S5),因为这些集合出现过与S2桶相同的情况。

参考

2018-11-15-MinHash原理

  • 11
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
MinHashLSH是一种基于MinHash算法和LSH(局部敏感哈希)技术的方法,用于实现文本去重。 MinHash是一种用于计算集合相似度的方法。它通过对集合进行随机排列得到一个特征向量,然后针对这个特征向量计算哈希值,从而实现对集合之间的相似度比较。MinHash具有较高的计算效率和较好的近似性能。 MinHashLSH是在MinHash基础上结合了LSH技术。LSH是一种用于处理高维数据的哈希技术,它能将相似的数据映射到同一个桶中,从而加速相似度搜索的过程。MinHashLSH利用多个MinHash哈希函数,将数据划分为多个桶,相似的文本被映射到相同的桶中。这样,在文本去重的过程中,我们只需要对同一个桶中的文本进行完全比较,大大减少了计算量。 实现文本去重的步骤如下: 1. 将文本分词,得到词的集合。 2. 对每个词进行哈希函数映射,得到固定长度的特征向量。 3. 根据特征向量计算MinHash签名,得到每个文本的MinHash特征集合。 4. 将MinHash特征集合划分为多个桶,相似的文本被映射到相同的桶中。 5. 对同一个桶中的文本进行完全比较,判断是否为重复文本。 MinHashLSH能够高效地处理海量的文本数据,通过适当调整参数,能够实现较高的去重效果。但需要注意的是,由于使用了哈希函数和近似计算,存在一定的误差率。因此,在实际应用中,需要根据具体需求和性能要求来确定参数设置,以获得满足要求的文本去重效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值