【问题标题】:Two algorithms to find nearest neighbor with Locality-sensitive hashing, which one?使用局部敏感散列查找最近邻居的两种算法,哪一种?
【发布时间】:2013-06-19 23:13:40
【问题描述】:

目前我正在研究如何使用 Locality-sensitive hashing 找到最近的邻居。然而,当我阅读论文和搜索网络时,我发现了两种算法:

1- 使用 L 个哈希表和 L 个随机 LSH 函数,从而增加两个相似文档获得相同签名的机会。例如,如果两个文档 80% 相似,那么它们有 80% 的机会从一个 LSH 函数中获得相同的签名。但是,如果我们使用多个 LSH 函数,则更有可能从其中一个 LSH 函数中获得文档的相同签名。这个方法在wikipedia中有说明,希望我的理解是正确的:

http://en.wikipedia.org/wiki/Locality-sensitive_hashing#LSH_algorithm_for_nearest_neighbor_search

2- 另一种算法使用了一篇论文(第 5 节)中的方法,名为:Moses S. Charikar 的舍入算法中的相似性估计技术。它基于使用一个 LSH 函数生成签名,然后对其应用 P 排列,然后对列表进行排序。其实我不是很了解这个方法,希望有人能澄清一下。

我的主要问题是:为什么有人会使用第二种方法而不是第一种方法?我发现它更简单、更快捷。

真的希望有人能帮忙!!!

编辑: 实际上,我不确定@Raff.Edward 是否混合了“第一”和“第二”。因为只有第二种方法使用半径,而第一种方法只使用由哈希族 F 组成的新哈希族 g。请查看 wikipedia 链接。他们只是使用许多 g 函数来生成不同的签名,然后对于每个 g 函数,它都有一个相应的哈希表。为了找到一个点的最近邻居,您只需让该点通过 g 函数并检查相应的哈希表是否存在冲突。因此,我如何将其理解为更多的功能......更多的碰撞机会。

我没有发现任何关于第一种方法的半径的提及。

对于第二种方法,它们只为每个特征向量生成一个签名,然后对它们应用 P 个排列。现在我们有 P 个排列列表,每个列表包含 n 个签名。现在他们从 P 中对每个列表进行排序。在给定查询点 q 之后,他们为其生成签名,然后对其应用 P 排列,然后对每个排列和排序的 P 列表使用二进制搜索来找到最相似的签名查询 q。我在阅读了很多关于它的论文后得出了这个结论,但我仍然不明白为什么有人会使用这种方法,因为它在找到汉明距离时似乎并不快!!!!

对我来说,我只需执行以下操作即可找到查询点 q 的最近邻居。给定签名列表 N,我将为查询点 q 生成签名,然后扫描列表 N 并计算 N 中的每个元素与 q 的签名之间的汉明距离。因此,我最终会得到 q 的最近邻居。它需要 O(N) !!!

【问题讨论】:

    标签: algorithm machine-learning locality-sensitive-hash


    【解决方案1】:

    您对第一个的理解有点偏离。发生碰撞的概率与相似度不成正比,而是与是否小于预定义半径成正比。目标是半径内的任何物体发生碰撞的几率很高,而半径 * (1+eps) 之外的物体发生碰撞的几率很低(并且中间的区域有点模糊)。

    第一种算法实际上很难很好地实现,但可以得到很好的结果。特别是,第一个算法适用于 L1 和 L2(技术上还有更多)指标。

    第二种算法实现起来非常简单,尽管根据您的问题规模,简单的实现可能会占用太多内存而无用。在这种情况下,碰撞概率与输入的相似性成正比。但是,它仅适用于余弦相似度(或基于相似度变换的距离度量)。

    因此,您将使用哪一个主要取决于您为最近邻(或任何其他应用程序)使用的距离度量。

    第二个实际上比第一个更容易理解和实现,论文只是很罗嗦。

    简短版本:取一个随机向量 V 并给每个索引一个独立的随机单位正常值。根据您希望的签名长度创建尽可能多的向量。当您进行矩阵向量乘积时,签名是每个索引的符号。现在任何两个签名之间的汉明距离与各个数据点之间的余弦相似度有关。

    因为您可以将签名编码为 int 数组并使用带有位计数指令的 XOR 来非常快速地获得汉明距离,所以您可以非常快速地获得近似的余弦相似度分数。

    LSH 算法没有很多标准化,而且两篇论文(和其他论文)使用不同的定义,所以有时会让人有些困惑。我最近才在JSAT 中实现了这两种算法,并且仍在努力完全理解它们。

    编辑:回复您的编辑。维基百科的文章对 LSH 来说不是很好。如果您阅读original paper,您所说的第一种方法仅适用于固定半径。然后基于该半径创建散列函数,并将其连接起来以增加在碰撞中接近点的概率。然后,他们通过确定他们想要的 k 的最大值来构建一个用于在此基础上进行 k-NN 的系统,然后找到他们可以找到第 k 个最近邻居的最大合理距离。这样,半径搜索很可能会返回一组 k-NN。为了加快速度,他们还创建了一些额外的小半径,因为密度通常不均匀,并且您使用的半径越小,结果越快。

    您链接的维基百科部分取自“稳定分布”部分的论文描述,该部分提供了用于搜索半径 r=1 的哈希函数。

    对于第二篇论文,您描述的“排序”不是散列的一部分,而是更快地搜索汉明空间的单一方案的一部分。正如我所提到的,我最近实现了这个,你可以看到a quick benchmark I 确实使用蛮力搜索仍然比 NN 的幼稚方法快得多。同样,如果您需要 L2 或 L1 距离上的余弦相似度,您也可以选择此方法。您会发现许多其他论文提出了用于搜索由签名创建的汉明空间的不同方案。

    如果您需要帮助,即使您仍在使用蛮力,也可以更快地说服自己适合 - 只要这样看:假设平均稀疏文档与另一个文档有 40 个常用词(在我的研究中这是一个非常保守的数字经验)。您有 n 个要比较的文档。然后蛮力余弦相似性将涉及大约 40*n 浮点乘法(以及一些额外的工作)。如果你有一个 1024 位的签名,那就只有 32 个整数。这意味着我们可以在 32*n 整数运算中进行蛮力 LSH 搜索,这比浮点运算要快得多。

    这里还有其他因素在起作用。对于稀疏数据集,我们必须同时保留双精度和整数索引来表示非零索引,因此稀疏点积正在执行大量额外的整数运算来查看它们有哪些共同的索引。 LSH 还允许我们节省内存,因为我们不需要为每个向量存储所有这些整数和双精度数,相反我们可以只保留它的散列 - 这只有几个字节。 减少内存使用可以帮助我们更好地利用 CPU 缓存。

    您的 O(n) 是我在博文中使用的天真的方式。而且速度很快。但是,如果您事先对位进行排序,则可以在 O(log(n)) 中进行二进制搜索。即使你有 L 个这些列表,L

    【讨论】:

    • 我已回复您的编辑。我没有感到困惑,维基文章没有很好地组织来解释正在发生的事情。
    • @Raff.Edward 你知道方法 2 的任何 open src 实现吗?能否请您也看看我发布的this 问题?
    • 我不知道#2 的完整实现是开源的。
    猜你喜欢
    • 2020-06-22
    • 2016-03-16
    • 1970-01-01
    • 2020-11-05
    • 1970-01-01
    • 2014-03-10
    • 2017-02-19
    • 1970-01-01
    • 2020-08-07
    相关资源
    最近更新 更多