我有一个存储向量的系统,允许用户找到与用户查询向量最相似的n个向量。也就是说,用户提交一个向量(我称之为查询向量),我的系统吐出“这里是n个最相似的向量”。我使用KD-Tree生成类似的向量,一切运行良好,但我想做更多。我想呈现n个最相似的向量的列表,即使用户没有提交完整的向量(具有缺失值的向量)。也就是说,如果用户提交具有三维的矢量,我仍然希望找到我存储的n个最近的矢量(存储的矢量是11维)。
我有几个明显的解决方案,但我不确定其中任何一个看起来非常好:
创建多个KD树,每个KD树使用用户将搜索的最受欢迎的维度子集构建。也就是说,如果用户提交了维度x,y,z的查询向量,我将该查询与我已经构建的KD树匹配,该KD树仅包含三维x,y,z的向量。
< / LI>当用户提交缺少值的查询向量时,忽略KD-Trees,并使用类似点积的东西逐个将查询向量与向量(存储在DB中的表中)进行比较。
这是一个常见问题,有什么建议吗?谢谢你的帮助。
答案 0 :(得分:2)
您的第一个解决方案对于查询来说可能是最快的(因为树构建不会考虑您不关心的方向中的拆分),但它肯定会占用大量内存。如果你不得不反复重建树木,它可能会变慢。
第二个选项看起来很慢,除非你只有几个点。如果是这种情况,你可能首先不需要kd树:)
我认为最好的解决方案是让您亲自处理您正在使用的代码。据推测,最近邻搜索计算树叶中的点与查询向量之间的距离;您应该能够修改它以处理点和查询向量大小不同的情况。例如。如果树中的点是以3D形式给出的,但查询向量只是长度为2,则点(p0,p1,p2)与查询向量(x0,x1)之间的“距离”将为
sqrt( (p0-x0)^2 + (p1-x1)^2 )
我没有深入研究您链接到的java代码,但如果您需要帮助,我可以尝试找到更改所需的确切位置。
-Chris
PS - 您可能不需要上面等式中的sqrt,因为距离平方通常是等效的。
修改强> 对不起,没有意识到它在源代码中会如此明显。您应该使用此版本的邻居函数:
nearest(double [] key, int n, Checker<T> checker)
实现自己的Checker类;看他们的EuclideanDistance.java看欧几里德版本。您可能还需要注释掉查询代码抛出的任何KeySizeException,因为您知道可以处理不同大小的键。
答案 1 :(得分:0)
您的第二个选项看起来像是您想要的合理解决方案。
如果存在任何值,您还可以使用最重要的(或平均值或您认为应该是的任何值)填充缺少的维度。
答案 2 :(得分:0)
您可以尝试使用现有的KD树 - 当拆分用于源矢量未提供的维度时,可以使用两个分支。这比执行强力搜索所花费的时间更少,并且可能比为维度子集维护一堆专用树更少麻烦。
你需要调整你的N最近算法(没有更多的信息,我不能告诉你...),对于距离,你将使用源矢量提供的那些元素的平方和
答案 3 :(得分:0)
以下是我最终做的事情:当用户没有指定值时(当他们的查询向量缺少维度时),我只是将我的匹配范围(在API中)调整为巨大的值,以便匹配任何值。