【问题标题】:KD-Trees and missing values (vector comparison)KD-Trees 和缺失值(向量比较)
【发布时间】:2009-12-22 17:12:52
【问题描述】:

我有一个存储向量的系统,并允许用户找到与用户查询向量最相似的 n 个向量。也就是说,用户提交了一个向量(我称之为查询向量),我的系统会吐出“这是 n 个最相似的向量”。我使用 KD-Tree 生成类似的向量,一切正常,但我想做更多。即使用户没有提交完整的向量(具有缺失值的向量),我也想提供 n 个最相似向量的列表。也就是说,如果用户提交了一个3维的向量,我仍然想找到我存储的n个最近的向量(存储的向量是11维)。

我有几个明显的解决方案,但我不确定任何一个看起来都很好:

  1. 创建多个 KD 树,每个 KD 树都使用用户将搜索的最流行的维度子集构建。也就是说,如果用户提交了一个维度为 x、y、z 的查询向量,我将该查询与我已经构建的 KD-Tree 匹配,该 KD-Tree 仅包含三个维度的向量 x、y、z。

  2. 当用户提交带有缺失值的查询向量并使用点积之类的方法将查询向量与向量(存储在数据库中的表中)一一进行比较时,忽略 KD 树。

这一定是一个常见问题,有什么建议吗?感谢您的帮助。

【问题讨论】:

  • 你说的是数字向量,对吧?实数,自然数?请告诉我们更多关于您如何定义向量之间的“相似性”的信息。
  • 布朗博士,是的,实数,自然数。具体来说,我有一个使用 double 类型数组的 Java 实现。这些数字是人体的测量值。因此,股骨有一个以厘米为单位的测量值,这是向量中的一个值。胫骨有一个以厘米为单位的测量值,这是向量中的一个值。很快。现在,相似性是由我正在使用的 KD-Tree api (cs.wlu.edu/~levy/software/kd) 创建的,但如果我按照方法 2 中的描述手动估计相似性,我会使用点积(这合理吗?)。谢谢。
  • 这取决于您需要比较的值的数量。你的意思不是“点积”,对吗?您正在考虑诸如“最小二乘法”之类的东西,对吗?
  • 布朗博士,我不清楚,有理数。在 Java 中翻倍,如 70.24、89.3。
  • 也许我也不清楚。您的数据库中有多少个向量可供比较? 100、10000、1000000 还是更多?你的向量的典型长度是“十一”吗?

标签: database performance algorithm math vector


【解决方案1】:

您的第一个解决方案对于查询可能是最快的(因为树构建不考虑在您不关心的方向上进行拆分),但它肯定会占用大量内存。如果你必须反复重建树木,它可能会变慢。

除非你只有几个点,否则第二个选项看起来很慢。如果是这样的话,你可能一开始就不需要 kd-tree :)

我认为最好的解决方案是亲自动手编写正在使用的代码。大概最近邻搜索计算树叶中的点与查询向量之间的距离;您应该能够修改它以处理点和查询向量大小不同的情况。例如。如果树中的点以 3D 形式给出,但您的查询向量的长度仅为 2,那么点 (p0, p1, p2) 和查询向量 (x0, x1) 之间的“距离”将为

sqrt( (p0-x0)^2 + (p1-x1)^2 )

我没有深入研究您链接到的 java 代码,但如果您需要帮助,我可以尝试找出需要进行更改的确切位置。

-克里斯

PS - 您可能不需要上述等式中的 sqrt,因为距离的平方通常是等价的。

编辑 抱歉,没有意识到它在源代码中会如此明显。你应该使用这个版本的邻居函数:

nearest(double [] key, int n, Checker<T> checker)

并实现你自己的 Checker 类;查看他们的 EuclideanDistance.java 以查看欧几里得版本。您可能还需要注释掉查询代码抛出的任何 KeySizeException,因为您知道可以处理不同大小的键。

【讨论】:

【解决方案2】:

您的第二个选项看起来是您想要的合理解决方案。

如果有的话,您还可以用最重要的(或平均值或您认为应该是的任何值)填充缺失的维度。

【讨论】:

    【解决方案3】:

    您可以尝试使用现有的 KD 树——当拆分是针对源向量未提供的维度时,采用两个分支。这应该比进行蛮力搜索花费更少的时间,并且可能比尝试为维度子集维护一堆专门的树更少麻烦。

    您需要调整您的 N-closest 算法(没有更多信息,我无法就此提供建议...),对于距离,您将仅使用源向量提供的那些元素的平方和.

    【讨论】:

      【解决方案4】:

      这就是我最终做的事情:当用户没有指定值时(当他们的查询向量缺少维度时),我只是将我的匹配范围(在 API 中)调整为很大,以便匹配任何值。

      【讨论】:

      • 你的做法不正确。考虑 kd 树中的以下点: (2,2, 100000) (2,3,100000) (1,2,4) 其中 100000 是大值 如果我想找到最接近 (1,2) 的点,则为根据您的逻辑,点 (2,2,100000),但是,根据 celion 的解决方案,它将是 (1,2,4)。
      猜你喜欢
      • 2011-08-07
      • 2014-01-03
      • 2012-02-28
      • 1970-01-01
      • 2012-06-11
      • 2013-02-09
      • 2013-08-05
      • 2021-08-06
      • 1970-01-01
      相关资源
      最近更新 更多