week22 LSH近似最近邻查找与用户购买预测

808 阅读6分钟

什么是近似最近邻查找,常用的方法有哪些

能简要说明近似最近邻查找(5point)

常用的方法(5point)

近似最近邻查找:

NN与ANN

NN,Nearest Neighbor Search,最近邻查找问题

KNN,K-Nearest Neighbor,k最近邻,查找离目标数据最近的前k个数据项

ANN,Approximate Nearest Neighbor,近似最近邻检索,在牺牲可接受范围内的精度的情况下提高检索效率

最近邻检索是线性复杂度的,当处理大规模数据时可以采用ANN方法

LSH,局部敏感哈希是ANN的一种

常用的方法:

LSH算法:

针对海量 and 高维数据如何进行查找:

如果数据是低维 and 小数据 => 通过线性的方式查找

数据不仅海量,而且高维 => 需要降维,采用索引方式查找

LSH,Locality-Sensitive Hashing,局部敏感哈希

需要查找与某个数据1个或多个相似的数据

最近邻查找方法(ANN,Approximate Nearest Neighbor)

传统的HashTable用于检索数据,无法将相似的数据放到同一个Bucket中,比如h=x mod w

LSH将相邻的数据,通过映射后依然保持相邻的关系,即保持局部的敏感度Locality-Sensitive

通过Hash Function,每个Bucket会落入一些原始数据,属于同一个桶内的数据有很大可能是相邻的(也存在不相邻的数据被hash到了同一个桶内)

将原始数据集合分成了多个子集合,每个子集合中的数据大概率是相邻的,而且子集合中的元素个数较少。

方便进行近邻查找 => 在一个很小的集合里查找相邻元素

MinHash算法:

文档相似度计算:

k-shingle,也称为k-gram,文档中任意长度为k的字符串。将每篇文档可以表示成文档中出现一次或者多次的k-shingle的集合

比如document="abcdabd",当2-shingle组成的集合为 {ab,bc,cd,da,bd}

如果两个文档相似,那么他们会有很多的shingles也是相同的

文本越长,K取值越大。K的经验值参考,短文本K=5,长文本K=10

Jaccard相似度

海量数据,高维 => 矩阵非常大的时候,目标需要找到一个Hash函数,将原来的Jaccard相似度计算,等同于降维后的相似度矩阵计算(Input Matrix => Signature Matrix)

原来文档的Jaccard相似度高,那么它们的hash值相同的概率高

原来文档的Jaccard相似度低,那么它们的hash值不相同的概率高。针对Jaccard相似度的为MinHashing(最小哈希)

什么是Hash函数

将原来的Jaccard相似度计算,等同于降维后的相似度矩阵计算(Input Matrix => Signature Matrix)

原来文档的Jaccard相似度高,那么它们的hash值相同的概率高

原来文档的Jaccard相似度低,那么它们的hash值不相同的概率高。针对Jaccard相似度的为MinHashing(最小哈希)

什么是k-shingle

也称为k-gram,文档中任意长度为k的字符串。将每篇文档可以表示成文档中出现一次或者多次的k-shingle的集合

比如document="abcdabd",当2-shingle组成的集合为 {ab,bc,cd,da,bd}

如果两个文档相似,那么他们会有很多的shingles也是相同的

文本越长,K取值越大。K的经验值参考,短文本K=5,长文本K=10

最小哈希值

MinHash执行

如何对海量数据进行排序 => 存储空间,计算时间

=> 有多个hash函数,通过hash i得到最新的行号,如果此时列上的元素为1,而且新行号比原来记录的M值小,那么更新M值

for each hash function hi do

compute hi (r);

for each column c

if c has 1 in row r

for each hash function hi do

if hi (r) is smaller than M(i, c) then

M(i, c) := hi (r);

对于hash函数:

h(x)= x mod 5

g(x)=(2x+1) mod 5

行数+1,每次进行h和g函数运算

如果列上的值为1,那么查看Hash得到的数值是否更小,更小则更新

=> 通过m个针对row index的Hash函数,完成m次行向量的置换(解决了行向量置换的问题)

MinHashLSH

除了要解决Ci和Cj两两之间相似度的计算问题,当数据量大的时候,两两之间相似度计算次数为

当数据量N很大(>100万),计算量非常大

=> 将可能相似的用户以较大概率分到同一个桶内,这样每一个用户的“相似用户候选集”就会少很多,大大降低计算复杂度

LSH是相似度的近似求解方式

在MinHash基础上,将Signature向量分成多段(band)

将Signiture矩阵分成b组,每组由r行组成

对每一组进行hash,各个组设置不同的桶空间。只要两列有一组的MinHash相同,那么这两列就会hash到同一个桶而成为候选相似项。

假设对于某行,两列签名值相同的概率为s(两列的相似度)

在某个band,值都相等的概率是

在某个band,值不相同的概率是

两个文档存在b个band,这b个band都不相同的概率是

b个band里,至少有一个相同的概率是

=> 两列成为候选相似对的概率是

称之为And then OR方法,先要求每个band的所有对应元素必须都相同,再要求多个band中至少有一个相同。符合这两条,才能发生hash碰撞。

假设s=0.8,20个band,每个band 5行,即b=20, r=5

在某个band,值都相等的概率是

在某个band,值不相同的概率是

b个band都不相同的概率是

b个band里,至少有一个相同的概率是

当s超过某个阈值后,两个用户成为candidate用户的概率会迅速增加并接近于1。这个阈值,也就是概率变化最陡的地方,近似为

MinHash与Jaccard相似度

C类行对于结果计算没有影响,可以删除

P(h(Ci)=h(Cj))=P(删掉C类后,第一行为A类)

=A类行的个数/所有行的个数=a/(a+b)

P(h(Ci)=h(Cj))= Jaccard(Ci,Cj)

用Ci,Cj的MinHash值相等的概率,对他们的Jaccard相似度进行估计

SimHash算法流程

SimHash算法:

Step1,设置SimHash的位数,比如32位,需要综合考虑存储成本以及数据集的大小

Step2,初始化SimHash,将各位初始化为0

Step3,提取文本中的特征,比如采用2-Shingles

"the cat sat on the mat"=>{"th", "he", "e ", " c", "ca", "at", "t ", " s", "sa", " o", "on", "n ", " t", " m", "ma"}

Step4,使用传统的hash函数计算各个word的hashcode

比如:"th".hash = -502157718 ,"he".hash = -369049682,……

Step5,对各word的hashcode的每一位,如果该位为1,则simhash相应位的值加它的权重(通常是出现的频率);否则减它的权重

Step6,计算最后得到的32位的SimHash,如果该位大于1,则设为1;否则设为0

如何通过SimHash算法得到每篇文档指纹

通过SimHash算法得到每篇文档的指纹(fingerprint)

计算两个文档指纹的海明距离

通常2篇文档的Hamming距离在3以内,就认为相似度比较高 => 两篇文档基本相同