一、 前言

    最近在工作中需要对海量数据进行相似性查找,即对微博全量用户进行关注相似度计算,计算得到每个用户关注相似度最高的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. Python中流程控制语句之IF语句

    生活中经常遇到的各种选择和判断在程序中也会遇到,比如玩色子,猜大小,比如选择哪条路回家?Python程序中同样也会遇到.IF语句就是用作条件判断的控制语句. 语法一: if 条件: # 引号是将条件与 ...

  2. 如何完美激活pycharm2019.2.2

    本号持续关注pycharm的更新,这不本月11号迎来新版本,为防走丢,请关注公众号,让我们携手并行!有道是"予人玫瑰手留余香",分享的确是件令人愉快的事,这也是我创建公众号的初心. ...

  3. Mysql高手系列 - 第9篇:详解分组查询,mysql分组有大坑!

    这是Mysql系列第9篇. 环境:mysql5.7.25,cmd命令中进行演示. 本篇内容 分组查询语法 聚合函数 单字段分组 多字段分组 分组前筛选数据 分组后筛选数据 where和having的区 ...

  4. java静态代码块/静态属性、构造块、构造方法执行、main方法、普通代码块的顺序

    java静态代码块/静态属性.构造块.构造方法执行.main方法.普通代码块的顺序 这也是在笔试中的一个重要的考点,就有一个输出语句让你写出输出的结果. 理论知识: 静态代码块是:属于类的,在类加载时 ...

  5. 【学习笔记】第七章 python3核心技术与实践--输入与输出

    [第六章]思考题答案,仅供参考: # coding:utf-8import time#方法一start_time = time.perf_counter()s = ''for n in range(0 ...

  6. JavaScript中的this到底是怎样的?

    this是困惑JavaScript开发者的一大‘毒瘤’,在开发过程中,但凡用到this的时候,我们都会很头疼,那么这个this在JavaScript中到底是怎么样的?身为一个前端coder,这是一个避 ...

  7. 在C#一个程序中,将一个窗体中的数据传送到另一个窗体

    使用多个窗体搭建的程序,需要用到窗体间的数据传递,常用两种方法: 方法一 1,进入子窗体的Designer.cs,将子窗体中的私有控件控件定义为public 2.在主窗口程序Form1.cs中将子窗口 ...

  8. [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher 题解报告

    来刷kuangbin字符串了,字符串处理在ACM中是很重要的,一般比赛都会都1——2道有关字符串处理的题目,而且不会很难的那种,大多数时候都是用到一些KMP的性质或者找规律. 点击标题可跳转至VJ比赛 ...

  9. ORA-08102异常重现及恢复

    现象: 在表上面新建主键报ORA-08102的异常: SQL> alter table t add primary key(id); alter table t add primary key( ...

  10. 从零开始入门 K8s | 应用编排与管理(酒祝)

    一.需求来源 背景问题 首先来看一下背景问题.如下图所示:如果我们直接管理集群中所有的 Pod,应用 A.B.C 的 Pod,其实是散乱地分布在集群中. 现在有以下的问题: 首先,如何保证集群内可用 ...