Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使Sim哈希(位置敏感哈希)算法更准确?_Java_Algorithm_Hash_Locality Sensitive Hash_Simhash - Fatal编程技术网

Java 使Sim哈希(位置敏感哈希)算法更准确?

Java 使Sim哈希(位置敏感哈希)算法更准确?,java,algorithm,hash,locality-sensitive-hash,simhash,Java,Algorithm,Hash,Locality Sensitive Hash,Simhash,我有两个名字和一个地址的“记录”(基本上是CSV字符串)。我需要找到彼此相似的记录:基本上,姓名和地址部分看起来都很“相似”,就好像它们是由人类解释的一样 我使用了这篇优秀博文中的想法:写一个简单的SimHash。如果两个或多个字符串的SimHash结果相同,我将该子集的所有记录传递给一个细粒度匹配程序,该程序为O(n^2),它将集合中的每个记录与其他记录进行比较 对于SimHash部分,我有一些参数,可以在其中定义数据报大小(基本上是字符串上大小为n的滑动窗口)和迭代次数,以确定SimHash

我有两个名字和一个地址的“记录”(基本上是CSV字符串)。我需要找到彼此相似的记录:基本上,姓名和地址部分看起来都很“相似”,就好像它们是由人类解释的一样

我使用了这篇优秀博文中的想法:写一个简单的SimHash。如果两个或多个字符串的SimHash结果相同,我将该子集的所有记录传递给一个细粒度匹配程序,该程序为O(n^2),它将集合中的每个记录与其他记录进行比较

对于SimHash部分,我有一些参数,可以在其中定义数据报大小(基本上是字符串上大小为n的滑动窗口)和迭代次数,以确定SimHash计算需要使用多少(随机)哈希。到目前为止,数据报大小为4,并使用4个哈希来计算SimHash。我尝试过各种其他组合,但这一个产生了迄今为止最好的结果

我遇到的问题是,这个方法在我拥有的数据集中找到了大约80%的重复项。我知道这一点,因为我已经根据上面提到的非常慢的O(n^2)完全匹配验证了整个数据集。对于小于10^4的数据集,O(n^2)匹配器是可以的,但很快就变得不可行,因为我需要运行大小为10^8的数据集

关于如何提高SimHash的准确性以便更多的“类似”记录使用相同的SimHash编号进行标记,有什么想法、建议或想法吗

编辑: 在SimHashing之前,我将大写并删除所有![0-9A-Z]个字符。 应匹配的内容示例(拼写错误是故意的):


  • 约翰·史密斯,镇上任何一条街123号邮编
  • 约翰尼·史密斯,123号,有担架吗
  • SOMETOWNE ZIP ROBERT PARKER,442 ANY STREET SOMETOWN ZIP


这里1和2是相似的,3不是。输出应为:1+2

在您尝试装腔作势并更改sim哈希之前,您是否尝试将特定领域的知识应用于该问题

你有你的算法遗漏对的列表吗?他们有什么共同点吗

您是否尝试过删除大写字母、将昵称转换为全名、删除中间名、扩展N、E、S、W和北、南、东、西、将st扩展到street等操作?

(我会将下面的内容放在评论中,但尚未找到代表。)

你到底想做什么?找到所有重复的吗?您如何定义重复项?案件敏感性问题?类似的措辞

我有点搞不清楚你们是怎么做的——找到相似的记录并创建一个集合,但随后O(n^2)检查我假设的完全相等。如果您正在检查是否完全相等,那么似乎无法找到类似记录(除非您将其用作O(n^2)的过滤器以节省时间)

一些随意的想法: 通过一种消毒器运行每条记录,该消毒器尝试将每条记录转换为最通用的形式(如果您关心/这很重要)

如果您感兴趣的是完全相等,并且内存不是一个限制,但是您希望提高速度,那么您可以为每个记录创建一个Java对象。为每个记录定义.equals()(您可以随时自定义它以不实现完全相等)。然后您需要定义一个hashCode()然后您可以将每条记录粘贴到哈希集中

生成的哈希集将没有重复项(由.equals()/.hashCode()实现定义)

或者,如果要查找重复项,则在添加到哈希集之前,先检查它是否包含记录,如果包含,则找到重复项

此实现将非常快,但可能会使用大量内存,因为您将在内存中存储整个数据集。替代方法是为每个记录创建一个哈希,然后将其存储在哈希集中,并检查每个记录的哈希是否相等

对每个记录进行散列的缺点是开发一个具有良好分布的良好散列生成的挑战,当然,对于散列,您必须担心冲突的误报。但是如果您的散列算法是可靠的,那么发生冲突的机会应该非常少,您不应该真正担心它


关于散列,你可以做一些简单的事情,比如所有字段串联的MD5。你可以做一个校验和。或者你可以为每个字段取散列代码的和。我不是一个超级数学天才,所以我不能告诉你哪一个会有最好的分布行为,从而导致冲突的可能性最小。如果您决定采用此方法,可能值得研究。

Simhash不是适合此目的的算法,因为它仅适用于差异非常小且大部分特征相同的近似重复检测。请参阅我的教程

一个更好的方法是,看起来你的散列功能最好生成为字符的带状(长度可能为4),而不是单词的带状

给出这样短的文本字段,并且给定单词顺序可能不太可能改变,您应该考虑包括终止带状疱疹:从文本字段的开始和结束的带状疱疹,包含少于正常字符数的字符,加上终止标记。n短时间运行的文本,例如“Whitmore”和“Whitemore”,不终止木瓦将产生

[WHIT、HITM、ITMO、TMOR、更多] 和 [WHIT、HITE、ITEM、TEMO、EMOR、MORE] Jaccard相似性较低,为2/9

而包括端接木瓦在内,这些木瓦将产生

[W,#WHI,WHI,WHIT,HITM,ITMO,TMOR,MORE,ORE,RE,E] 和 [W,#WHI,WHI,WHIT,HITE,ITEM,TEMO,EMOR,MORE,ORE,RE,E] 机智