Node.js/javascript minhash模块,用于为类似文本输出类似的哈希字符串

Node.js/javascript minhash模块,用于为类似文本输出类似的哈希字符串,javascript,node.js,minhash,Javascript,Node.js,Minhash,我正在寻找一个node.js/Javascript模块,它将minhash算法应用于字符串或更大的文本,并通过testring或Hexstring返回该文本的“标识”或“特征”。如果我将该算法应用于另一个类似的文本字符串,则哈希字符串也应该类似。这样的模块已经存在了吗 到目前为止,我正在检查的模块只能直接比较文本,并计算某种jaccard数字相似性,直接与比较的文本进行比较,但我想为每个文档存储某种哈希字符串,以便以后如果我有类似的文本,我可以比较字符串的相似性 本质上,我要寻找的是以下代码(J

我正在寻找一个node.js/Javascript模块,它将minhash算法应用于字符串或更大的文本,并通过testring或Hexstring返回该文本的“标识”或“特征”。如果我将该算法应用于另一个类似的文本字符串,则哈希字符串也应该类似。这样的模块已经存在了吗

到目前为止,我正在检查的模块只能直接比较文本,并计算某种jaccard数字相似性,直接与比较的文本进行比较,但我想为每个文档存储某种哈希字符串,以便以后如果我有类似的文本,我可以比较字符串的相似性

本质上,我要寻找的是以下代码(Java):在Javascript中:

例如,对于以下字符串:
“敏捷的棕色狐狸跳过了懒狗”
“敏捷的棕色狐狸跳过了懒狗”
它会为第一句话创建一个哈希,如下所示:

"KV5rsUfZpcZdVojpG8mHLA=="
对于第二个字符串,类似于:

KV5rsSfZpcGdVojpG8mGLA==
两个哈希字符串没有太大区别。。。这就是minhash算法的要点,但是,我不知道如何创建类似的hashstring。。到目前为止,我发现的所有库只直接比较了2个文档并创建了一个相似系数,但它们没有创建一个哈希字符串,这是文档的特征。。。
与所有算法的相似之处在于,它们为单词标记(或木瓦)数组创建一个哈希crc32(或类似)哈希值。但是我仍然不知道他们如何比较这些散列…

需要Douglas Duhaime的实现,但是任何其他计算散列值数组的实现都可以以相同的方式使用

const str1=“敏捷的棕色狐狸跳过懒惰的狗”;
const str2=“敏捷的棕色狐狸跳过懒惰的d”;
控制台日志(str1);
控制台日志(str2);
变量s1=str1.拆分(“”);
var s2=标准差分(“”);
//为要比较的每组单词创建哈希
//默认的numPerm是128,但它给出了很长的散列
//在8以下,几乎相似的字符串将给出完全相同的哈希值
var m1=新的Minhash({numPerm:8});
var m2=新的Minhash({numPerm:8});
//更新每个散列
s1.map(函数(w){m1.update(w)});
s2.map(函数(w){m2.update(w)});
//估计两个Minhash之间的jaccard相似性
console.log('jaccard相似度:',m1.jaccard(m2));
//现在要将哈希值转换为字符串,我们使用一种base64
//编码,但由于hasvalues是32位整数的数组,因此
//必须首先将其分解为8位整数的数组
//对于给定的int32,返回4个字节
函数int32ToBytes(num){
//最大32位无符号整数的十六进制表示形式为0xFFFFFF
//最大无符号整数(8位===一个字节)的十六进制表示形式为0xFF
//因此,可以将32位uint(无符号整数)视为48位uint的串联。
//按位&运算符是按位AND运算符
//它的真值表是0&0=0,0&1=0,1&0=0和1&1=1
//例如8&1 0b111&0b001 0b001 1
//十六进制表示法也可以这样做:
//65535和255 0xFFFF和0x00FF 0x0FF 255
//65535和65280 0xFFFF和0xFF00 0xFF00 65280
// 255 + 65535 = 65535
//现在介绍按位>>移位运算符
//a>>n将数字a向右移动n位
//在十六进制中,FF是8位,所以'0xFF00>>8=0xFF`
//此操作是可逆的`0xFF>8+(int16&0x00FF)>>0
//没有丢失任何信息,因为我们可以执行反向操作
//下面使用相同的原理将32位整数编码为4字节(8位整数)
//最大uint32=0xFFFFFFFF=
//0xFF 16,
(num&0x0000ff00)>>8,
(num&0x000000ff)
];
返回arr;
}
//4字节的容错base64编码
功能Uint8ToString(u8a){
var CHUNK_SZ=0x8000;
var c=[];
对于(变量i=0;i{
var u8=新的UINT8阵列(int32ToBytes(i));
var b64encoded=btoa(Uint8ToString(u8));
str+=B64编码;
});
返回str;
}
//替换不重要的“==”以缩短哈希
log(base64EncodeInt32Array(m1.hashvalues).replace(/==/g');
log(base64EncodeInt32Array(m2.hashvalues).replace(/==/g')

如果您只想一次比较两个文档(文档a和文档B的相似程度如何?),那么将每个文档的最小哈希存储为串联字符串就可以了。您可以通过将每个文档的字符串拆分回其组成的minhash并计算共享的minhash数(相同)来比较这两个文档

但是,如果您想问“还有哪些文档与文档A类似”,这是一个糟糕的解决方案,因为您必须将文档A单独与以前看到的所有其他文档进行比较。更糟糕的是,如果要在语料库中找到所有文档之间的相似性,就必须将每个文档与其他文档进行比较。在一组1000份文件中,需要进行499500次比较。有一百万份文档,这就有近5000亿份比较。这是一个O(n2)问题

相反,适当的方法是保留一个哈希字典,将minhash映射到文档ID。每次遇到新文档时,都会生成其最小哈希值,然后在哈希字典中查找共享一个或多个哈希值的所有其他文档。文档与传入文档共享的哈希越多,其估计的相似性就越高。 最后,将新文档的所有minhash添加到hash字典中,以便将来进行搜索。