Simhashing(希望)简单(2012)

2021-04-10 20:14:17

朝着弄清楚不同的各种数据彼此有何相似(并且哪个是大量候选人中最近的匹配),偶数是我最喜欢的算法之一。它'在它的方法中有点简单,辉煌,但对于大多数人(我所包括的人)来说仍然不够明显。读者可能熟悉散列算法,例如MD5或SHA,其旨在非常快速地创建数据的唯一签名(哈希)。构建了这些功能,以便数据的相同文件或斑点共享相同的哈希,因此您可以快速查看两个斑点是否相同,或者如果在传输之后仍然存在相同的签名,请查看它是否已损坏或不具有相同的签名。然后是不同的斑点,即使大多数相同,也得到了完全不同的签名。

虽然Simhashes仍然旨在具有唯一的文档签名,但他们还试图确保看起来同样相同的哈希文档。这样,如果文档密切相关,则可以查看类似的哈希值,而无需将它们与位进行比较。它'统计工具,以帮助我们更快地找到近复制。

那个'有点模糊,但是,'好吧。我'请试图以一种良好理解的方式解释事物。

让'首先看看ASCII。 ASCII中的字符' A',AS',是第97号,或者在二进制表示中,01100001.基本英文字母的所有字母都可以表示:

这对大多数程序员来说都不是新的。我还可以代表具有这些二进制值的序列的整个单词:

一些读者可以直接阅读二进制和ascii,知道这些词是什么。我们可以很容易地看到所有字母的前3位(左侧)都是一样的,我们可以丢弃它们,获取:

如果我要在两对彼此相似的两对中将这些单词组分组,那么你将把#1和#3放在一起,#2和#4在一起。你会这样做。四个字,按顺序,是"香蕉&#34 ;," bozo&#34 ;," cabana&#34 ;," ozone"

通过查看二进制模式,我们的大脑能够自然地弄清楚一些事情。每个比特的位置,单词的长度,重复位的比特序列,以及如何'光'或#39;黑暗'一列看起来是我们可能作为每个单词的某种签名的一些东西。

什么'很有趣的是,这些签名中的每一个都是独一无二的,但我们'重新弄清楚他们是如何基于这一点的。将此与以下四个MD5散列进行比较:

'没有办法一目了然地知道哪个更近的。再次,在那里没有任何令人惊讶的是,给定MD5并不意味着哈希相似。

虽然我们的视觉布局很高兴地弄清楚如何将短文字匹配,它完全不切实际地用一般的方式使用这种视觉签名 - 编程软件以识别人类将永远占用的方式,而且它比仅比较一个字母逐渐比较慢。

但是,我们拥有的是,使用BLOB的二进制表示的想法可能足以创建一个尊重相似性的体面签名 - 一个simhash。

什么可能很好就是能够压缩信息一点,所以它'它有点明显它包含的内容。我们可以构建所有二进制值的直方图:在列中设置为1的每个位的1,跳过其余部分。这可能给我们一个有趣的布局,有点像如下(我制作酒吧水平):

那个'不是很好。问题是我们'只看一半的数据。我们'重新丢弃所有0位。让'尝试通过假装每个空位(白方形)值-1,其他人(黑色方块)值得+1。我们可以代表Sums:

让' S比视觉更重要,将每个总和表示为一点直方图,再次:

它' s现在更容易看到最接近哪个,如果你眯着眼睛。它甚至可能更容易,而不是在观看中拥有完整的模式时,我们'重新完成我们之前的数据的一小部分。我们'获得一个体面的签名。

让' s进一步推动它。我' ll取决于这些最终直方图,每个值高于或等于0,i' ll填充一点。对于0下的每个值,i' ll离开它。我的四个签名现在是:

热门炎热,工作正常。在这种情况下,我们立即看到要配对在一起。 1和3显然适合在一起,鉴于它们'重复相同,2和4一起走,因为它们得到了相同的签名。

我们如何在其中不相同时发现签名之间的距离?如果我们有一段数据导致散列10011,那将是最接近的?事实证明,使用汉明距离是一种做到的方式。汉明距离是一种简而言之,一种方式来看看两个数字,字母或任何数据序列,并看看它们是多么不同。通过一群相同的长度组,它通过一个接一个地看待它们而完成。每次他们'重复不同,我们加1到汉明距离。如果他们'重新相同,我们会像它一样离开它。因此,我们两个先前签名与我们的新模式之间的汉明距离是:

与签名1和3相比,我们的新图案的汉明距离为1,与签名2和4相比,我们可以说新的签名可能与1比2更类似于1。

现在它'因为我们目前的偶像,事情非常相似,而不是那种对人眼的方式 - 弦" sssss"会给我们签名更接近"香蕉"比"例如,Bozo",距离1.有很好的解释。

我们刚刚实现了一个非常非常基本的SimHash算法版本。为什么我们所做的工作需要一些数学。这就是Simhash论文倾向于弯曲统计肌肉的地方。为了使它短而过于简单,当我们拍摄整个二进制斑点的碎片时(这里我们从一个Zeroes流中拿出6位的片段),我们'重新服用整件的某种快照,并根据它发生的频率来提供体重。

让&#39再次看看我们的话,但这一次,通过他们最重要的比特排序来排序:

这使得有点易于了解每个字母的频率(或者更确切地说,每个特征,因为论文称为他们)对最终值的影响。如果我们有许多相同的字母(特征),无论他们的订单,那么当我们&#39时,机会就会看起来相当相似;折叠'整个东西变成了一个微小的5位哈希。

如果功能的顺序并不重要,我们如何使其了解"哈哈哈哈!"从&#34有一种不同的意义; aaaaaahhhhhhh!&#34 ;?

当与不同的二进制表示相当类似的方式时,我们会做什么?这有点糟糕," cc"被视为类似于" Bababababa&#34 ;,因为他们应该在我们目前的计划下提供非常相似的签名。

我们如何处理非ASCII文本的数据,其中功能可能会有不同的大小?

事实上,这三个问题有点符合讨论散发比5或8位长的方式,并给予规则的长度。

提高我们特征中的比特分布的第一种简单方法是通过某种函数来传递唯一的函数,但即使它们也使它们变化很大。这是铃铛吗?

散列算法如MD5,SHA,甚至是您的常见散列' S Hashing函数将这样做。事实上,通过MD5散列算法传递一个字母将给我提供128位数据,这些数据不太可能与其他值获得的数据相似。什么'很好的是它也将让我采取更大的功能(例如,需要表示需要多个字节的代码点序列),并给它与ASCII字符相同的权重。

通过通过普通散列函数传递每个特征(无论其尺寸是什么),我们允许给它们所有相同的重量。然后,我们可以以前的方式计算我们的Simhash,但是使用新的中间哈希函数的二进制值。

这很有意思,因为如果我这样做,而不是使用字母,我也可以为我的simhash使用单词。也许这个词" cat"将给我010110010111,那个"罗马式和#34;将给我01000101001101。然后可以通过选择我们认为是一个特征,以及什么' t。

我们可以解决" aaaaaahhhhh!"与"哈哈哈哈!"通过制作音节的问题:"啊"和" aa"和#34; hh"和#34;!"可以被视为不同的特征。然后我们将保证不同的结果,而不是我们通过信函拿走一切信。

它的第二方面是能够对每个特征提供重量。假设我们想象一下,我们在磁盘上有3个文件:

我们想根据他们的内容偶发它们,而不是它们在磁盘上的二进制表示。如果我们在整个文件中使用Simhashing,我们会发现两个PDF文件被视为非常相似。那个' s是因为pdf是比.txt文件更重的格式,具有元数据,标题和一些常见结构,这些结构将在许多情况下超重内容。

对于人类阅读这一点,可能更优选的是在树木中清楚地谈论白色猫,而句子2完全是关于别的东西的句子。以下是这些句子中的单词的所有(虚构)哈希:

然后,这三个句子可以具有以下签名(我预先排序,使它们更容易处理):

基于这一点,句子1和2非常接近。我们怎样才能带来我们想要的意义?解决方案是创建称重的功能。要做到这一点,我可以常常用句子,在句子中的少数意义'一个'和#39;和#39;'并给他们一个体重1,并采取更不寻常的单词,如'男人' happy'或' cat'并给予他们的重量为3。

计数值时,而不是执行+1或-1,我做+重量或 - 重量,有效地给我以下签名:

正如我们希望的那样,弦1和3现在最接近两个汉明距离。

不,不是真的。就偶数而言,它'它!现在的复杂性在于弄清楚建立'词汇和#39; (加权功能的字典)与我们尝试匹配的东西相关:如果您'重新对XML文档的结构感兴趣,但不是它们的文本,序列化树层次结构和节点类型作为特征可能是一种方法这对你来说比&#39所希望知道了解HTML站点的文本内容是否更改了,这更加有意义,即使结构本身也改变了。

建立良好的词汇表是在让偶像有用的时候挑战的巨大部分挑战的地方。另一个棘手的区域是如何能够快速将Simhash匹配在一起。将一大吨的Simhash与众不同地找到最佳匹配仍然是一个复杂的问题,就像没有偶像一样的方式:但是,您收益的收益是多少来存储所有物品来比较,以及每个比较多长时间将。对于大档案,它已经' S已经完全改进,但是它赢得了'如果您有一个o(n²)算法来比较一切,请补偿n的大值。如果你'遗嘱感兴趣,有几篇论文可以自由地提供。

我希望我设法使偶发可以理解和有趣作为算法。 有各种有趣的应用程序,偶发可以闪耀,试图弄清楚如何数据结构是如何,发现您刮擦的网站的布局或内容是否改变,检测垃圾邮件[PDF]或附近的实时合并 -Duplicate日志事件。