什么是近似最近邻查找,常用的方法有哪些
能简要说明近似最近邻查找(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以内,就认为相似度比较高 => 两篇文档基本相同