我有一个应用程序,我应该实现Bloom Filters和Minhashing来查找类似的项目。
我已经实现了Bloom Filter,但我需要确保我理解Minhashing部分:
我是否需要在文档中拼写所有字符串?问题是我无法真正找到帮助我的东西,我发现只有两个文件,而且从来没有一个String到一组字符串。
答案 0 :(得分:0)
因此:用户输入一个字符串,应用程序在单个文档中找到最相似的字符串。通过"相似性",你的意思是像Levenstein距离(其中" cat"被认为类似于" rat"" cart"),还是其他措施?你(粗略地说)正在寻找类似的段落,类似的句子,类似的短语或类似的单词?这些是重要的考虑因素。
另外,您说您正在将一个字符串与一组字符串进行比较。这些字符串是什么?句子?段落?如果您确定不想找到跨越多个段落(或多个句子,或者您有什么)的任何相似之处,那么将该文档视为多个单独的字符串是有意义的;否则,你应该把它想象成一个长串。
MinHash算法用于将许多文档相互比较,当不可能同时将所有文档存储在存储器中时,并且将每个文档单独地相互比较将是n平方问题。 MinHash通过仅为一些带状疱疹存储哈希来克服这些问题,因此牺牲了一些准确性。你不需要MinHash,因为你可以简单地将每个木瓦存储在内存中,例如,使用4个字符克来制作带状疱疹。但是,如果您不希望切换字词排序,您可能会发现Smith-Waterman algorithm更合适(另请参阅here)。
如果您希望用户输入长串的单词,您可能会在单词的基础上获得更好的结果;例如,3字克,忽略了白色间距,大小写和标点符号的差异。
生成4个字符克很简单:"猫坐在垫子上#34;会产生"","他c"," e ca"," cat"等等。这些中的每一个都将与它出现的段落号一起存储在内存中。当用户输入搜索字符串时,它将以相同的方式混合,并且包含最多共享的段落带状疱疹可以被检索。为了比较效率,您可以使用FNV1a或类似的廉价哈希将它们存储为哈希值,而不是将带状疱疹存储为字符串。
带状疱疹也可以用文字而不是字符构建(例如"猫坐在","猫坐在","坐在")。对于较大的文本片段,这往往更好:例如,30个字或更多。如果采用这种方法,我通常会忽略空格,大小写和标点符号的所有差异。
如果你想找到可以跨越段落的匹配,它会变得相当复杂,因为你必须存储每个木瓦的角色位置并考虑可能匹配的许多不同配置,根据广泛的处罚来惩罚它们分散他们的带状疱疹。这可能会导致相当复杂的代码,我会认真考虑坚持使用基于Levenstein的解决方案,例如Smith-Waterman,即使它不能很好地处理字序的反转。
我不认为布隆过滤器可能对你有很大帮助,但我不确定你是如何使用它的。如果您的文档结构高度,则Bloom过滤器可能非常有用:一组有限的可能字符串,您正在搜索其中一个字符串的存在。但是对于自然语言,我怀疑它会非常有用。