我正在尝试寻找一个minhash开源实现,我可以利用它实现我的工作。
我需要的功能非常简单,给定一个输入,实现应返回其minhash。
首选python或C实现,以防万一我需要破解它才能为我工作。
任何指针都会有很大的帮助。
问候。
答案 0 :(得分:11)
您应该按顺序查看以下开源库。所有这些都是Python,并展示如何使用LSH / MinHash计算文档相似性:
lsh
LSHHDC : Locality-Sensitive Hashing based High Dimensional Clustering
MinHash
答案 1 :(得分:8)
看看datasketch library。它支持序列化和合并。它是在纯python中实现的,没有外部依赖。 Go version具有完全相同的功能。
答案 2 :(得分:3)
如果您有兴趣研究minhash算法,这是一个非常简单的实现并进行了一些讨论。
要为集合生成MinHash签名,我们创建一个长度为$N$
的向量,其中所有值均设置为正无穷大。我们还创建了$N$
函数,这些函数接受输入整数并将该值置换。 $i^{th}$
函数将全权负责更新向量中的$i^{th}$
值。给定这些值,我们可以通过将集合中的每个值传递给每个$N$
排列函数来计算集合的minhash签名。如果$i^{th}$
置换函数的输出低于向量的$i^{th}$
的值,我们用置换函数的输出替换该值(这就是为什么哈希称为“ min -hash”)。让我们在Python中实现它:
from scipy.spatial.distance import cosine
from random import randint
import numpy as np
# specify the length of each minhash vector
N = 128
max_val = (2**32)-1
# create N tuples that will serve as permutation functions
# these permutation values are used to hash all input sets
perms = [ (randint(0,max_val), randint(0,max_val)) for i in range(N)]
# initialize a sample minhash vector of length N
# each record will be represented by its own vec
vec = [float('inf') for i in range(N)]
def minhash(s, prime=4294967311):
'''
Given a set `s`, pass each member of the set through all permutation
functions, and set the `ith` position of `vec` to the `ith` permutation
function's output if that output is smaller than `vec[i]`.
'''
# initialize a minhash of length N with positive infinity values
vec = [float('inf') for i in range(N)]
for val in s:
# ensure s is composed of integers
if not isinstance(val, int): val = hash(val)
# loop over each "permutation function"
for perm_idx, perm_vals in enumerate(perms):
a, b = perm_vals
# pass `val` through the `ith` permutation function
output = (a * val + b) % prime
# conditionally update the `ith` value of vec
if vec[perm_idx] > output:
vec[perm_idx] = output
# the returned vector represents the minimum hash of the set s
return vec
仅此而已!为了演示如何使用此实现,我们仅举一个简单的示例:
import numpy as np
# specify some input sets
data1 = set(['minhash', 'is', 'a', 'probabilistic', 'data', 'structure', 'for',
'estimating', 'the', 'similarity', 'between', 'datasets'])
data2 = set(['minhash', 'is', 'a', 'probability', 'data', 'structure', 'for',
'estimating', 'the', 'similarity', 'between', 'documents'])
# get the minhash vectors for each input set
vec1 = minhash(data1)
vec2 = minhash(data2)
# divide both vectors by their max values to scale values {0:1}
vec1 = np.array(vec1) / max(vec1)
vec2 = np.array(vec2) / max(vec2)
# measure the similarity between the vectors using cosine similarity
print( ' * similarity:', 1 - cosine(vec1, vec2) )
这返回〜.9作为这些向量之间相似性的度量。
虽然我们只比较了上面的两个minhash向量,但是我们可以使用“ Locality Sensitive Hash”来更简单地比较它们。为此,我们可以构建一个字典,将$ W $ MinHash向量分量的每个序列映射到用于构造MinHash向量的集合的唯一标识符。例如,如果W = 4
并有一个集合S1
,我们从中得出一个MinHash向量[111,512,736,927,817...]
,我们将在每个四个MinHash值的序列中添加S1
标识符该向量:
d[111-512-736-927].append('S1')
d[512-736-927-817].append('S1')
...
对所有集合执行此操作后,我们可以检查字典中的每个键,并且如果该键具有多个不同的集合ID,则我们有理由相信这些集合是相似的。实际上,在字典的单个值中一对集合ID出现的次数越多,两个集合之间的相似性就越大。通过这种方式处理数据,我们可以将识别所有相似集合对的时间降低到大致线性的时间!
答案 3 :(得分:2)
我建议你this library,特别是如果你需要坚持。在这里,您可以使用redis来存储/检索所有数据。
您可以选择redis数据库,或者只使用内置的内存python词典。
使用redis的性能,至少在本地计算机上运行redis服务器时,几乎与通过标准python词典实现的性能相同。
您只需指定配置字典,例如
config = {"redis": {"host": 'localhost', "port": '6739', "db": 0}}
并将其作为参数传递给LSHash
类构造函数。