LSH︱python实现局部敏感随机投影森林——LSHForest/sklearn(一)
关于局部敏感哈希算法。之前用R语言实现过,可是由于在R中效能太低。于是放弃用LSH来做类似性检索。学了python发现非常多模块都能实现,并且通过随机投影森林让查询数据更快。觉得能够试试大规模应用在数据类似性检索+去重的场景。
私觉得,文本的类似性能够分为两类:一类是机械类似性;一类是语义类似性。
机械类似性代表着,两个文本内容上的相关程度。比方“你好吗”和“你好”的类似性。纯粹代表着内容上字符是否全然共现,应用场景在:文章去重;
语义类似性代表着,两个文本语义上的类似程度。比方“苹果”和“公司”的类似性。本篇不做这一讨论
之前写关于R语言实现的博客:
R语言实现︱局部敏感哈希算法(LSH)解决文本机械类似性的问题(一,基本原理)
R语言实现︱局部敏感哈希算法(LSH)解决文本机械类似性的问题(二。textreuse介绍)
机械类似性python版的四部曲:
LSH︱python实现局部敏感随机投影森林——LSHForest/sklearn(一)
LSH︱python实现局部敏感哈希——LSHash(二)
类似性︱python+opencv实现pHash算法+hamming距离(simhash)(三)
LSH︱python实现MinHash-LSH及MinHash LSH Forest——datasketch(四)
.
一、随机投影森林
本节參考:论文《基于随机投影的场景文本图像聚类方法研究》与博客 随机投影森林-一种近似近期邻方法(ANN)
1、随机投影森林理论与实现伪代码
当数据个数比較大的时候,线性搜索寻找KNN的时间开销太大,并且须要读取全部的数据在内存中,这是不现实的。因此,实际project上,使用近似近期邻也就是ANN问题。
当中一种方法是利用随机投影树,对全部的数据进行划分,将每次搜索与计算的点的数目减小到一个可接受的范围,然后建立多个随机投影树构成随机投影森林,将森林的综合结果作为终于的结果。
建立一棵随机投影树的过程大致例如以下(以二维空间为例):
- 随机选取一个从原点出发的向量
- 与这个向量垂直的直线将平面内的点划分为了两部分
- 将属于这两部分的点分别划分给左子树和右子树
在数学计算上。是通过计算各个点与垂直向量的点积完毕这一步骤的,点积大于零的点划分到左子树,点积小于零的点划分到右子树。
注意一点。图中不带箭头的直线是用于划分左右子树的根据,带箭头的向量是用于计算点积的。这样,原有的点就划分为了两部分,图比例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjY5MTczODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
可是此时一个划分结果内的点的数目还是比較多。因此继续划分。再次随机选取一个向量。与该向量垂直的直线将全部点进行了划分。图比例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjY5MTczODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="这里写图片描写叙述" title="">
注意一点,此时的划分是在上一次划分的基础上进行的。
也就是说如今图中的点已经被划分成了四部分,相应于一棵深度为2。有四个叶节点的树。
以此类推继续划分下去,直到每一个叶节点中点的数目都达到一个足够小的数目。
注意这棵树并非全然树。
随机投影森林的建立须要两个參数。即单棵树的深度 + 森林数量。
这两个參数决定了数据集的分散程度以及随机投影后得到的向量维数。
利用这棵树对新的点进行近期邻计算时,首先通过计算该点与每次划分所用向量的点积。来找到其所属于的叶节点,然后利用这个叶节点内的这些点进行近期邻算法的计算。
这个过程是一棵随机投影树的计算过程。利用相同的方法。建立多个随机投影树构成随机森林,将森林的总和结果作为终于的结果。
.
2、相应拓展
Wright等人 已将随机投影的方法应用于视角变化的人脸识别,Nowak等人 採用随机投影的方法学习视觉词的类似度度量。Freund等人将随机投影应用于手写体识别上,取得了非常好的效果。
.
3、随机投影森林构造向量+聚类
论文《基于随机投影的场景文本图像聚类方法研究》中,将每一个叶子节点当成一维特征,用叶子节点的特征点个数作为叶子节点的描写叙述,最后得到測试图像的特征向量。
有点类似word2vec之中的霍夫曼树。
论文中的实验结果:
当中。森林规模10棵。
- 第一组实验。使用sift局部特征描写叙述。在不同的deep。树深度下识别的准确率。当中F=(2 * R *
P)/(R+P),大致来看深度deep=8来说。比較合理。 - 第二组实验,AP聚类和Kmeans聚类在不同深度的区别,实验数据是google图片集,局部特征描写叙述使用ASIFT方法,用AP和Kmeans分别进行聚类。由于AP聚类算法的类别数由类似矩阵的对角线元素值决定,所以须要多次測试,终于以类似度矩阵的中值为类似度矩阵对角线上的元素值,用来控制聚类的类别数。得到的AP聚类各项评价指标值是多次实验的平均值。
而K-means
聚类是多次实验不同的迭代次数与类别数,以最好的聚类结果作为终于结果
- 第三组实验实验数据是google图片集。聚类算法使用AP聚类,用不同的局部特征描写叙述法(ASIFT与SIFT)得到的聚类结果ASIFT局部特征描写叙述得到的结果比SIFT方法在各项指标上都高10%以上。
由此可见。ASIFT比SIFT对自然场景下的文本区域图像的局部特征描写叙述更好更准确。这是由于SIFT仅仅是具有尺度和旋转不变性。对于具有视角变化的相同文字却无法得到匹配描写叙述。而ASIFT不仅对图像具有尺度旋转不变性,还具有仿射不变性,这样的特性对自然场景下的文本处理有更好的有用性。
具体的ASIFT与SIFT对照可见论文。
.
二、LSHForest/sklearn
LSHforest=LSH+随机投影树
在python的sklearn中有LSHForest能够实现。
1、主函数LSHForest
class sklearn.neighbors.LSHForest(n_estimators=10, radius=1.0, n_candidates=50, n_neighbors=5, min_hash_match=4, radius_cutoff_ratio=0.9, random_state=None)
随机投影森林是近期邻搜索方法的一种替代方法。
LSH森林数据结构使用已排序数组、二进制搜索和32位固定长度的哈希表达。
随机投影计算距离是使用近似余弦距离。
n_estimators : int (default = 10)
树的数量
min_hash_match : int (default = 4)
最小哈希搜索长度/个数。小于则停止
n_candidates : int (default = 10)
每一颗树评估数量的最小值。反正至少每棵树要评估几次,雨露均沾
n_neighbors : int (default = 5)
检索时。最小近邻个数,就怕你忘记忘了设置检索数量了
radius : float, optinal (default = 1.0)
检索时。近邻个体的距离半径
radius_cutoff_ratio : float, optional (default = 0.9)
检索时,半径的下限,相当于类似性概率小于某阈值时,停止搜索,或者最小哈希搜索长度小于4也停止
random_state : int, RandomState instance or None, optional (default=None)
随机数生成器使用种子。默认没有
附带属性:
hash_functions_ : list of GaussianRandomProjectionHash objects
哈希函数g(p,x),每一个样本一个哈希化内容
trees_ : array, shape (n_estimators, n_samples)
Each tree (corresponding to a hash function)
每棵树相应一个哈希散列。且这个哈希散列是经过排序的。显示的是哈希值。
n_estimators棵树。n_samples个散列。
original_indices_ : array, shape (n_estimators, n_samples)
每棵树相应一个哈希散列,哈希散列是经过排序的。显示的是原数据序号index.
trees_ 和original_indices_ 就是两种状态,trees_ 是每棵经过排序树的散列,original_indices_ 是每棵经过排序树的序号Index.
.
2、LSHForeast相关函数
- fit(X[, y])
Fit the LSH forest on the data.
数据加载投影树
- get_params([deep])
Get parameters for this estimator.
获取树里面的相关參数
- kneighbors(X, n_neighbors=None, return_distance=True)
检索函数,n_neighbors代表所需近邻数。 不设置的话则返回初始化设置的数量。return_distance,是否打印/返回特定cos距离的样本。
返回两个array。一个是距离array。一个是概率array
- kneighbors_graph([X, n_neighbors, mode])
Computes the (weighted) graph of k-Neighbors for points in X
数量检索图,n_neighbors代表所需近邻数, 不设置的话则返回初始化设置的数量,mode=’connectivity’默认
- partial_fit(X[, y])
加入数据到树里面,最好是批量导入。
- radius_neighbors(X[, radius, return_distance])
Finds the neighbors within a given radius of a point or points.
半径检索。在给定的区间半径内寻找近邻,radius为半径长度。return_distance代表是否打印出内容。
- radius_neighbors_graph([X, radius, mode])
Computes the (weighted) graph of Neighbors for points in X
半径检索图
- set_params(**params)
Set the parameters of this estimator.
重设部分參数
.
3、案例一则
>>> from sklearn.neighbors import LSHForest
>>> X_train = [[5, 5, 2], [21, 5, 5], [1, 1, 1], [8, 9, 1], [6, 10, 2]]
>>> X_test = [[9, 1, 6], [3, 1, 10], [7, 10, 3]]
>>> lshf = LSHForest(random_state=42)
>>> lshf.fit(X_train)
LSHForest(min_hash_match=4, n_candidates=50, n_estimators=10,
n_neighbors=5, radius=1.0, radius_cutoff_ratio=0.9,
random_state=42)
>>> distances, indices = lshf.kneighbors(X_test, n_neighbors=2)
>>> distances
array([[ 0.069..., 0.149...],
[ 0.229..., 0.481...],
[ 0.004..., 0.014...]])
>>> indices
array([[1, 2],
[2, 0],
[4, 0]])
LSHForest(random_state=42)树的初始化,
lshf.fit(X_train)開始把数据加载初始化的树;
lshf.kneighbors(X_test, n_neighbors=2)。找出X_test每一个元素的前2个(n_neighbors)类似内容。
当中。这个是cos距离,不是类似性,假设要直观,能够被1减。
.
4、案例二则
来源于:用docsim/doc2vec/LSH比較两个文档之间的类似度
# 使用lsh来处理
tfidf_vectorizer = TfidfVectorizer(min_df=3, max_features=None, ngram_range=(1, 2), use_idf=1, smooth_idf=1,sublinear_tf=1)
train_documents = []
for item_text in raw_documents:
item_str = util_words_cut.get_class_words_with_space(item_text)
train_documents.append(item_str)
x_train = tfidf_vectorizer.fit_transform(train_documents)
test_data_1 = '你好。我想问一下我想离婚他不想离,孩子他说不要,是六个月就自己主动生效离婚'
test_cut_raw_1 = util_words_cut.get_class_words_with_space(test_data_1)
x_test = tfidf_vectorizer.transform([test_cut_raw_1])
lshf = LSHForest(random_state=42)
lshf.fit(x_train.toarray())
distances, indices = lshf.kneighbors(x_test.toarray(), n_neighbors=3)
print(distances)
print(indices)
一般lsh比較适合做短文本的比較
.
相关拓展:
相关属性获得
# 属性
lshf.trees_
# 每棵树,排序散列的哈希值
lshf.hash_functions_
# 每棵树的hash公式
lshf.original_indices_
# 每棵树,排序散列的序号index
近期邻检索的图:kneighbors_graph
lshf.kneighbors_graph(X_test, n_neighbors=5, mode='connectivity')
新增数据到树里面:
partial_fit(X_test)LSH︱python实现局部敏感随机投影森林——LSHForest/sklearn(一)的更多相关文章
- 局部敏感哈希Locality Sensitive Hashing(LSH)之随机投影法
1. 概述 LSH是由文献[1]提出的一种用于高效求解最近邻搜索问题的Hash算法.LSH算法的基本思想是利用一个hash函数把集合中的元素映射成hash值,使得相似度越高的元素hash值相等的概率也 ...
- 从NLP任务中文本向量的降维问题,引出LSH(Locality Sensitive Hash 局部敏感哈希)算法及其思想的讨论
1. 引言 - 近似近邻搜索被提出所在的时代背景和挑战 0x1:从NN(Neighbor Search)说起 ANN的前身技术是NN(Neighbor Search),简单地说,最近邻检索就是根据数据 ...
- [Algorithm] 局部敏感哈希算法(Locality Sensitive Hashing)
局部敏感哈希(Locality Sensitive Hashing,LSH)算法是我在前一段时间找工作时接触到的一种衡量文本相似度的算法.局部敏感哈希是近似最近邻搜索算法中最流行的一种,它有坚实的理论 ...
- 局部敏感哈希算法(Locality Sensitive Hashing)
from:https://www.cnblogs.com/maybe2030/p/4953039.html 阅读目录 1. 基本思想 2. 局部敏感哈希LSH 3. 文档相似度计算 局部敏感哈希(Lo ...
- [机器学习] 在茫茫人海中发现相似的你:实现局部敏感哈希(LSH)并应用于文档检索
简介 局部敏感哈希(Locality Sensitive Hasing)是一种近邻搜索模型,由斯坦福大学的Mose Charikar提出.我们用一种随机投影(Random Projection)的方式 ...
- 局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍
局部敏感哈希(Locality-Sensitive Hashing, LSH)方法介绍 本文主要介绍一种用于海量高维数据的近似近期邻高速查找技术--局部敏感哈希(Locality-Sensitive ...
- 海量数据挖掘MMDS week2: 局部敏感哈希Locality-Sensitive Hashing, LSH
http://blog.csdn.net/pipisorry/article/details/48858661 海量数据挖掘Mining Massive Datasets(MMDs) -Jure Le ...
- 图像检索(6):局部敏感哈希索引(LSH)
图像检索中,对一幅图像编码后的向量的维度是很高.以VLAD为例,基于SIFT特征点,设视觉词汇表的大小为256,那么一幅图像编码后的VLAD向量的长度为$128 \times 256 = 32768 ...
- 局部敏感哈希(Locality-Sensitive Hashing, LSH)
本文主要介绍一种用于海量高维数据的近似最近邻快速查找技术——局部敏感哈希(Locality-Sensitive Hashing, LSH),内容包括了LSH的原理.LSH哈希函数集.以及LSH的一些参 ...
随机推荐
- weblogic安装(无界面静默安装)
一.环境准备 1. 用户准备 Generic通用版weblogic不能用ROOT用户安装,如无其他用户需先创建用户,创建用户步骤此处略过 2. 下载weblogic 在官网下载weblogic,将下载 ...
- Win8.1恢复这台电脑里的6个文件夹
平台:win8.1 问题:网络下载的ghost版8.1,装好后“这台电脑”里没有6个常用的文件夹. 解决:导入下列注册表项即可 Windows Registry Editor Version 5.00 ...
- unity-unet-同步各个player唯一标识
Multiplayer Game 中所有 player 都有一个唯一标识.在unet中可以通过 Network Identity 组件获取到该 player 在整个网络整的 唯一 的连接 id 这里测 ...
- git提交代码到本地仓库和远程仓库
5.commit代码到本地git仓库 选中需要 Commit 的项目,右键->Team->Commit, 填写相关的 Commit message,并选择需要提交的 Files ...
- 14、序列化操作,类的保存和dict转JSON
在程序运行的过程中,所有的变量都是在内存中,比如,定义一个dict: d = dict(name='Bob', age=20, score=88) 可以随时修改变量,比如把name改成'Bill',但 ...
- GOROOT,GOPATH,GOBIN,project
GOROOT,GOPATH,GOBIN,project目录 我们接下来一个一个来看关于Go语言中的三个目录的详细解释先通过go env查看go的环境变量(我这里是mac的环境,所以可能和你的不同) ...
- JS学习笔记 - fgm练习 2-11- 改变图片路径 var img = new Image(); 图片预加载
<style> *{ margin: 0;padding: 0; list-style: none; } body{ background: black; } .outer{ margin ...
- 素数表(Eratosthenes)
怎么判断一个数是素数? 常规的方法是枚举从2开始的数,看看是否能被整除. 但是,如果要判断的数很多的时候,那么效率会十分低下.... 一个优化的方法是不用判断比这个数小的所有数(到平方根位置),而是判 ...
- 关于PyYAML报错问题解决
转自:http://www.fwqtg.net/%E5%85%B3%E4%BA%8Epyyaml%E6%8A%A5%E9%94%99%E9%97%AE%E9%A2%98%E8%A7%A3%E5%86% ...
- 怎样用Adobe Acrobat 7 Pro把PDF文档拆分成多个啊?
这个pdf文档里有多篇文章,我想把他们分开并分别保存在独立的pdf文档.怎么操作?我的电脑基础不太好,麻烦说得详细一些. Adobe Acrobat 7 Pro拆分PDF文档的方法: 1.点左边的“书 ...