一、 前言

    最近在工作中需要对海量数据进行相似性查找,即对微博全量用户进行关注相似度计算,计算得到每个用户关注相似度最高的TOP-N个用户,首先想到的是利用简单的协同过滤,先定义相似性度量(cos,Pearson,Jaccard),然后利用通过两两计算相似度,计算top-n进行筛选,这种方法的时间复杂度为\(O(n^2)\)(对于每个用户,都和其他任意一个用户进行了比较)但是在实际应用中,对于亿级的用户量,这个时间复杂度是无法忍受的。同时,对于高维稀疏数据,计算相似度同样很耗时,即\(O(n^2)\)的系数无法省略。这时,我们便需要一些近似算法,牺牲一些精度来提高计算效率,在这里简要介绍一下MinHashing,LSH,以及Simhash。

二、 MinHashing

    Jaccard系数是常见的衡量两个向量(或集合)相似度的度量:

\[
J(A,B)=\frac {\left | A\cap B \right |}{\left | A\cup B \right |}
\]

    为方便表示,我们令A和B的交集的元素数量设为\(x\),A和B的非交集元素数量设为\(y\),则Jaccard相似度即为\()\frac x {(x+y)}\)。

所谓的MinHsah,即进行如下的操作:

  1. 对A、B的\(n\)个维度,做一个随机排列(即对索引\(,i_1,i_2,i_3,\cdots,i_n\)随机打乱)

  2. 分别取向量A、B的第一个非0行的索引值(\(index\)),即为MinHash值
    得到AB的MinHash值后,可以有以下一个重要结论:
    \[
    P[minHash(A) = minHash(B)] = Jaccard(A,B)
    \]

以下是证明:
在高维稀疏向量中,考虑AB在每一维的取值分为三类:

  1. A、B均在这一维取1(对应上述元素个数为\(x\))

  2. A、B只有一个在这一维取1(对应上述元素个数为\(y\))

  3. A、B均取值为0

    其中,第三类占绝大多数情况,而这种情况对MinHash值无影响,第一个非零行属于第一类的情况的概率为\(()\frac x{(x+y)}\),从而上面等式得证。
    另外,按照排列组合的思想,全排列中第一行为第一类的情况为\(()(x*(x+y-1)!)\),全排列为\((x+y)!\),即将\(n\)维向量全排列之后,对应的minHash值相等的次数即为Jaccard相似度。

    但是在实际情况中,我们并不会做\((x+y)!\)次排列,只做\(m\)次(\(m\)一般为几百或者更小,通常远小于\(n\)),这样,将AB转为两个\(m\)维的向量,向量值为每次排列的MinHash值。
\[
sig(A)=[h_1(A),h_2(A),\cdots,h_m(A)]
\]

\[
sig(B)=[h_1(B),h_2(B),\cdots,h_m(B)]
\]

    这样计算两个Sig向量相等的比例,即可以估计AB的Jaccard相似度(近似保持了AB的相似度,但是不能完全相等,除非全排列,对于这种利用相似变换相似空间的方法,需要设计哈希函数,而一般的哈希函数无法将满足相似向量哈希后的值相似)。
在实际实现中,m次排列通常通过一个针对索引的哈希来达到hash的效果,即MinHashing算法(实现可参考Spark实现细节
http://spark.apache.org/docs/2.2.0/api/java/org/apache/spark/ml/feature/MinHashLSH.html)

三、LSH

    上面的MinHashing解决了高维稀疏向量的运算,但是计算两两用户的相似度,其时间复杂度仍然是O(n^2),显然这个计算量还没有得到改善,这时我们如果能将用户分到不同的桶,只比较可能相似的用户,即相似用户以较大可能分到同一个桶内,这样不相似的用户基本不会发生比较,降低计算复杂度,LSH即为这样的方法。

    LSH方法基于这样的思想:在原空间中很近(相似)的两个点,经过LSH哈希函数的映射后,有很大概率它们的哈希是一样的;而两个离的很远(不相似)的两个点,映射后,它们的哈希值相等的概率很小。

    基于这样的思想,LSH选择的哈希函数即需要满足下列性质:

    对于高维空间的任意两点,\(,x,y\):

  • 如果\(d(x,y)≤R\),则\(h(x)=h(y)\)的概率不小于\(P_1\)

  • 如果\(d(x,y)≥cR\),则\(h(x)=h(y)\)的概率不大于\(P_2\)。

    其中,\(c>1,P_1>P_2\)。满足这样性质的哈希函数,被称为 \((R,cR,P1,P2)-sensive\)。

    本文介绍的LSH方法基于MinHashing函数。

    LSH将每一个向量分为几段,称之为band,如下图\(^6\)


    每一个向量在图中被分为了\(b\)段(每一列为一个向量),每一段有\(r\)行(个)MinHash值。在任意一个band中分到了同一个桶内,就成为候选相似用户(拥有较大可能相似)。

    设两个向量的相似度为\(t\),则其任意一个band所有行相同的概率为\(t^r\),至少有一行不同的概率为\(1-t^r\), 则所有band都不同的概率为\(()(1-t^r)^b\),至少有一个band相同的概率为\(()1-(1-t^r)^b\)。其曲线如下图所示\(^6\)

    图中变化最抖的点s近似为\((\frac 1 b)^{\frac 1 r}\),其中,s作为阈值为具体为多少是我们才将其分到一个桶中,即人工设定s来确定这里的b和r。如图例,对于\(r=5,b=10\)时,其阈值为0.6,其中,绿色为假正例率(相似度很低的两个用户被哈希到同一个桶内),蓝色为假负例率(真正相似的用户在每一个band上都没有被哈希到同一个桶内),可以设置\(,b,r\)调整\(s\),\(s\)越大,效率越高,假正例率越低,假负例率越高。

四、后记

    接触LSH是一个很偶然的工作中的小需求,感慨其在海量高维稀疏数据中有很好的应用场景(文本,图片,结构数据均可以用),速度快,计算复杂度低,感慨其embedding转换的巧妙,鉴于本人水平和精力着实有限,没有搞懂的地方其实还很多,没有证明MinHashing方法满足LSH方法的性质,也没有搞懂BloomFilter算不算也是一种LSH方法的哈希函数。知乎用户@hunter7z的答案给了我不少的启发 ,感谢。
    查了很多资料,作此读书笔记,权且抛砖引玉。

参考文献:

  1. http://www.mmds.org/
  2. https://zhuanlan.zhihu.com/p/46164294
  3. http://spark.apache.org/docs/2.2.0/api/java/org/apache/spark/ml/feature/MinHashLSH.html
  4. http://mlwiki.org/index.php/Locality_Sensitive_Hashing
  5. https://www.cnblogs.com/wangguchangqing/p/9796226.html
  6. http://www.mmds.org/mmds/v2.1/ch03-lsh.pdf

    本文由飞剑客原创,如需转载,请联系私信联系知乎:@AndyChanCD

局部敏感哈希LSH(Locality-Sensitive Hashing)——海量数据相似性查找技术的更多相关文章

  1. [Algorithm] 局部敏感哈希算法(Locality Sensitive Hashing)

    局部敏感哈希(Locality Sensitive Hashing,LSH)算法是我在前一段时间找工作时接触到的一种衡量文本相似度的算法.局部敏感哈希是近似最近邻搜索算法中最流行的一种,它有坚实的理论 ...

  2. 局部敏感哈希算法(Locality Sensitive Hashing)

    from:https://www.cnblogs.com/maybe2030/p/4953039.html 阅读目录 1. 基本思想 2. 局部敏感哈希LSH 3. 文档相似度计算 局部敏感哈希(Lo ...

  3. LSH(Locality Sensitive Hashing)原理与实现

    原文地址:https://blog.csdn.net/guoziqing506/article/details/53019049 LSH(Locality Sensitive Hashing)翻译成中 ...

  4. 海量数据挖掘MMDS week7: 局部敏感哈希LSH(进阶)

    http://blog.csdn.net/pipisorry/article/details/49686913 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...

  5. [机器学习] 在茫茫人海中发现相似的你:实现局部敏感哈希(LSH)并应用于文档检索

    简介 局部敏感哈希(Locality Sensitive Hasing)是一种近邻搜索模型,由斯坦福大学的Mose Charikar提出.我们用一种随机投影(Random Projection)的方式 ...

  6. 局部敏感哈希LSH

    之前介绍了Annoy,Annoy是一种高维空间寻找近似最近邻的算法(ANN)的一种,接下来再讨论一种ANN算法,LSH局部敏感哈希. LSH的基本思想是: 原始空间中相邻的数据点通过映射或投影变换后, ...

  7. 局部敏感哈希-Locality Sensitive Hashing

    局部敏感哈希 转载请注明http://blog.csdn.net/stdcoutzyx/article/details/44456679 在检索技术中,索引一直须要研究的核心技术.当下,索引技术主要分 ...

  8. 在茫茫人海中发现相似的你——局部敏感哈希(LSH)

    一.引入 在做微博文本挖掘的时候,会发现很多微博是高度相似的,因为大量的微博都是转发其他人的微博,并且没有添加评论,导致很多数据是重复或者高度相似的.这给我们进行数据处理带来很大的困扰,我们得想办法把 ...

  9. 【期外】 (一)关于LSH :局部敏感哈希算法

    LSH是我同学的名字,平时我会亲切的称呼他为离骚,老师好,左移(leftshift),小骚骚之类的,最近他又多了一个新的外号:局部敏感哈希(Locally sensitive hashing). 好了 ...

随机推荐

  1. Toad客户端连接Oracle数据库报错 ORA-12170:TNS:连接超时

    Oracle 客户端连接Oracle数据库报错   ORA-12170:TNS:连接超时  排错步骤: 1. 查看网络是否畅通:  打开cmd,ping数据库IP 2. 查看端口是否畅通: 打开cmd ...

  2. ajax 发送json数据时为什么需要设置contentType: "application/json”

    1. ajax发送json数据时设置contentType: "application/json”和不设置时到底有什么区别? contentType: "application/j ...

  3. 通过Service访问应用 (2)

    目录 通过NodePort Service在外部访问集群应用 通过LoadBalancer Service在外部访问集群应用 Microsoft SQL Server数据库部署 为了便于理解和学习,请 ...

  4. FreeSql (二十九)Lambda 表达式

    FreeSql 支持功能丰富的表达式函数解析,方便程序员在不了解数据库函数的情况下编写代码.这是 FreeSql 非常特色的功能之一,深入细化函数解析尽量做到满意,所支持的类型基本都可以使用对应的表达 ...

  5. Python集训营45天—Day02

    目录 变量和运算符 1.1 初步介绍 1.2 使用案例 1.3 知识点梳理 1.4 练习 序言:这一章我们将学习变量以及常见的类型,我们将以案例和代码相结合的方式进行梳理,但是其中所有的案例和知识点 ...

  6. System类入门学习

    System类 System类代表系统,系统级的很多属性和控制方法都放置在该类的内部.该类位于java.lang包.其包含一些有用的字段和方法,不能被实例化 system中包含了in.out和err三 ...

  7. Java之BigDecimal详解

    一.BigDecimal概述 ​ Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算.双精度浮点型变量double可以处理16位有效数,但在实 ...

  8. NOIP2002 1.级数求和

    这题目...... 题目:已知:Sn= 1+1/2+1/3+…+1/n.显然对于任意一个整数K,当n足够大的时候,Sn大于K.现给出一个整数K(1<=k<=15),要求计算出一个最小的n: ...

  9. flink有什么优势值得大家这么热衷

    flink 通过实现了 Google Dataflow 流式计算模型实现了高吞吐.低延迟.高性能兼具实时流式计算框架. 同时 flink 支持高度容错的状态管理,防止状态在计算过程中因为系统异常而丢失 ...

  10. CSS——样式表的引入

    1.内部样式表 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...