《 Mining of Massive Datasets》学习笔记之 Finding Similar Items

来源:互联网 发布:mac mail 设置模板 编辑:程序博客网 时间:2024/05/29 09:46

本文总结《Mining of Massive Datasets》一书中第三章所描述的Finding Similar Items 问题及其相关算法。


该算法所要解决的是数据挖掘中关于寻找相似对象的问题,比如在互联网中找到两个相似的网页,或者根据一张图片去寻找与之相似的图片,进而解决一些其他的问 题。本算法中所用的模型是在海量的文库中寻找相似的文章,它们有可能引用了大量相同的内容,或者是一篇剽窃的碰上了一篇正版的。文章中段落或者句子出现的顺序可以不尽相同,但它们包含了很多相似或者相同的内容。


算法的总体过程如下:将一篇文章看做是一个很长的字符串,为了寻找不同文章中的共同之处,将文章分解成长度为 K 的字符串的集合,包含了文章中所有长度为 K 的 连续字符串(多次出现的字符串只记作一次),通过数据压缩,把文章中每一个长度为 K 的字符串是否出现的情况表示成一个向量,通过比较向量相同的部分来判断 原文章中相同的部分,从而找出海量文库中相似的文章。以下是
具体过程。


   


一、 Shingling of Documents

  我们先考虑最直观的想法:依次选择文库中的两篇文章作为一对,比较他们两个的相似程度。这种方法会产生两个问题:其一,文库中的文章本就是大量的,如果直接两两配对那么数量将升至平方级,处理起来相当困难;其二,之前说过,两篇文章是否相似可能从人的直观角度比较容易判断,在阅读并理解文章内容后。但是计 算机并没有理解语义的能力,它只能单纯地通过词句逐一的比对来判断,而对于抄袭或者是盗版的文章,往往原文的顺序或者所用的一些词汇已经被有心之人修改, 所以计算机很难做出判断。基于此,我们需要找到一种方法来帮助计算机判断两篇文章是否相似,shingling 就是这样一种方法。它的思想是把一篇文章看成一个很长的字符串,定义一个 k-shingle 如下:

   k-shingle: any substring of length k found within the document

  然后,就可以把一篇文章看成是一个 k-shingle 的集合,进而可以将文库看作是一个二维的矩阵 Z,每一行表示一个 k-shingle,每一列表示一篇文章,矩阵中的第( i, j)个元素表示第 i 个 k-shingle 是否出现在第 j 篇文章对应的集合中。

在进行 Shingling 时的一个问题是对于 K 的大小如何选择,如果 K 太大,朝着原始的算法退化,降低效率;同时 K 也不能太小,比如假设 K = 1,那么显然几乎每一篇文章中都会包含所有的 1-shingle,也就是单个字母,这样得到的结果是所有的文章都是相似的,显然没有实际意义。对于 K 的取值,算法给出了一个准则:

   k should be picked large enough that the probability of any given shingle appearing in any given document is low.

  同时,算法还建议,对于日常处理的电子邮件以及工作文档等,K可以取 5;对于论文之类的专业性文档,K可以取9


二、 Minhashing

  在第一步之后我们得到了二维矩阵 Z,表示文库中每篇文章里 k-shingle 的出现情况,下面我们考虑如何利用该表来寻找相似文章。在此先考察一下矩阵Z的规模,对于 K=5 的情况,由于英文文本中经常出现的字母有 20 个,所以总共可能的 shingle 是 20^5 = 3,200,000,再加上纵轴文章的数量经常达到百万级别,所以矩阵的大小将会超过一般机器的内存,这样不利于后续的比较处理,所以我们要考虑对数据进行压缩。

   


  在给出解决方案之前,我们先来了解一下 Jaccard similarity 的概念。Jaccard similarity 用来描述集合间的一种属性,它的定义是两个集合的交集大小比上两个集合的并集大小,也就是:

   The Jaccard similarity of sets S and T is | S ∩ T | / | S ∪ T |

  显然,对于相似度越高的两个集合,也就是所含相同元素越多的集合,它们Jaccard similarity 的值也会越高,所以我们可以用 Jaccard similarity 来表征两个集合的相似程度。

  下面我们介绍 Minhashing 算法。 Minhashing 算法选取了 N 个哈希函数,每个函数都是一个对于横轴的置换,每一次置换之后,对于第 j 列,按照横轴从上往下的顺序寻找第一个出现 1 的矩阵元素,这个元素对应的横坐标所代表的shingle 就是第 j 列在本次哈希函数下的值。N 次置换每次都可以得到一行的值,N 次完成后即可得到一个 N 行 M 列的矩阵 S(其中 M 是文库中文章的数目),从而对于每一篇文章,也就是 S 矩阵的每一列,都得到了一个代表它的向量,称作signature。

  Minhashing 算法的特点是它没有破坏原文库中文章的相似性,这可以归结为:

    The probability that the minhash function for a random permutationof rows produces the same value for two sets equals the Jaccard similarity of those sets.

  该结论的证明如下:

If we restrict ourselves to the columns for sets S1 and S2, then rows can be divided into three classes:
  1)Type X rows have 1 in both columns.
  2)Type Y rows have 1 in one of the columns and 0 in the other.
  3)Type Z rows have 0 in both columns.

Since the matrix is sparse, most rows are of type Z. However, it is the ratio of the numbers of type X and type Y rows that determine both SIM(S1, S2) and the probability that h(S1) = h(S2). Let there be x rows of type X and y rows of type Y . Then SIM(S1, S2) = x/(x + y). The reason is that x is the size of S1 ∩ S2 and x + y is the size of S1 ∪ S2.

Now, consider the probability that h(S1) = h(S2). If we imagine the rows permuted randomly, and we proceed from the top, the probability that we shall meet a type X row before we meet a type Y row is x/(x + y). But if the first row from the top other than type Z rows is a type X row, then surely h(S1) = h(S2). On the other hand, if the first row other than a type Z

  值得注意的是, Minhashing 中的 N 不能取得太小, 这样有可能会产生很多偶然性与不准确性,必须要有足够大的 N,同时有随机选择的哈希函数,这样才能保证上述的推论成立。通常情况下, N 的值会取 100。经过 Minhashing 之后,矩阵的横轴大小从之前的 20^50 变成了 100,虽然矩阵所要保存的内容由之前的 0/1 变成了一个 k-shingle,但总体来说矩阵的规模还是大大地下降了。


三、 Locality-Sensitive Hashing for Documents(LSH)

  经过前面的两步,我们似乎可以进行相似文本的搜索了,但有一个问题仍然没有解决, 那就是文库本身包含的文章数目很多,如果要进行两两配对地比较,那么所需要处理的内容仍然是巨大的。可以参看以下例子:

   


      但有一个观察事实是,真正相似的文章实际上并不多,一些文章完全没有相关性,对于这些文章根本不需要进行比较。 所以我们需要一种方法来排除这些不必要的比较。 Locality-Sensitive Hashing(以下简称 LSH) 的思想是,对于第二步得到的代表每一篇文章的向量 signature 进行分段,分成 b 段,每段包含矩阵中的 r 行,对于每一个 r x M 的子矩阵,采用一个哈希函数进行哈希操作,将 r 行的值完全相同的两列(也就是两篇文章)映射到同一个篮子中(总共设置L 个篮子),对 b 段中的每一段选择一个不同的哈希函数,最终得到 bL 个篮子。然后我们只需要对出现在同一个篮子中的文章进行两两配对,并且在原始 Z 中印证这一对是否真的是相似的,比如 Jaccard similarity 大于某个值,这样就减小了算法的运算量。

      LSH 可行的原因基于两点,一是对于两篇真正相似的文章,它们的 b 个长度为 r 的向量均不出现在同一个篮子中的概率是很小的,而对于不相似的文章,它们有某个长为 r 的向量出现在同一个篮子中的概率也不是非常大,所以算法可以有效地找出绝大部分的相似文章,又不至于有太大的运算量。上述成立的原因需要进一步的说明,具体可以参看教材。


四、总结
      上述三个步骤基本解决了在海量文库中寻找相似文章的问题,同时这种算法的思想还可以扩展到对于其他相似对象的查找,通过分解对象和压缩数据,在有限的资源条件下实现有效查找,至于算法的效率以及优化等问题,还需要进一步讨论,若有机会深入学习再来更新

0 0
原创粉丝点击