高维数据中最近的邻居?

时间:2011-04-22 00:10:35

标签: algorithm language-agnostic search machine-learning nearest-neighbor

几天前我问过question如何找到给定矢量的最近邻居。我的矢量现在是21维度,在我继续前进之前,因为我不是来自机器学习领域,也不是数学领域,我开始问自己一些基本问题:

  • 欧几里德距离是否是首先找到最近邻居的一个很好的指标?如果没有,我的选择是什么?
  • 此外,如何确定确定k邻居的正确门槛?是否有一些分析可以用来计算出这个值?
  • 以前,我被建议使用kd-Trees,但维基百科页面清楚地表明,对于高维度,kd-Tree几乎相当于蛮力搜索。在这种情况下,有效查找百万点数据集中最近邻居的最佳方法是什么?

有人可以澄清一些(或所有)上述问题吗?

15 个答案:

答案 0 :(得分:165)

我目前正在研究这类问题 - 分类,最近邻搜索 - 用于音乐信息检索。

您可能对近似最近邻 ANN )算法感兴趣。这个想法是你允许算法足够返回邻居(也许不是最近的邻居);这样做可以降低复杂性。你提到了 kd-tree ;这是一个例子。但正如你所说, kd-tree 在高维度上效果不佳。事实上,所有当前的索引技术(基于空间划分)降级为线性搜索,以获得足够高的维度[1] [2] [3]。

最近提出的 ANN 算法中,最受欢迎的可能是 Locality-Sensitive Hashing LSH ),它映射了一组点高维空间到一组箱子,即哈希表[1] [3]。但与传统哈希不同,位置敏感的哈希将附近的点放在同一个bin中。

LSH 有一些巨大的优势。首先,它很简单。您只需计算数据库中所有点的哈希值,然后从中创建哈希表。要查询,只需计算查询点的哈希值,然后从哈希表中检索同一个bin中的所有点。

其次,有一个严格的理论支持其表现。可以看出,查询时间是数据库大小的次线性,即比线性搜索更快。更快的速度取决于我们能够容忍多少近似值。

最后, LSH 0 < p <= 2的任何Lp规范兼容。因此,要回答您的第一个问题,您可以将 LSH 与欧几里德距离指标一起使用,或者您可以将其与曼哈顿(L1)距离指标一起使用。汉明距离和余弦相似度也有变种。

2008年,Malcolm Slaney和Michael Casey为IEEE信号处理杂志撰写了一篇不错的综述[4]。

LSH 似乎无处不在。你可能想尝试一下。


[1] Datar,Indyk,Immorlica,Mirrokni,“基于p稳定分布的局部敏感哈希方案”,2004年。

[2] Weber,Schek,Blott,“高维空间中相似性搜索方法的定量分析和性能研究”,1998年。

[3] Gionis,Indyk,Motwani,“通过散列在高维度上搜索相似性”,1999年。

[4] Slaney,Casey,“寻找最近邻居的地方敏感哈希”,2008年。

答案 1 :(得分:74)

答案 2 :(得分:16)

您所面对的是curse of dimensionality。运行像PCA或 ICA 这样的算法有时很有用,可以确保您确实需要所有21个维度,并且可能找到一个线性变换,这个变换可以让您使用少于21个且具有大致相同的结果质量

<强>更新 我在Rangayyan的一本叫做生物医学信号处理的书中遇到过它们(我希望我能正确记住它)。 ICA不是一项简单的技术,但它是由芬兰的研究人员开发的,我认为它的Matlab代码可以公开下载。 PCA是一种使用更广泛的技术,我相信你应该能够找到它的R或其他软件实现。通过迭代求解线性方程来执行PCA。我很久以前就已经这么做了,以便记住。 =)

我们的想法是,在您的情况下,将信号分解为独立的特征向量(实际上是离散的本征函数)和它们的特征值。每个特征值显示每个特征函数为每个测量提供的贡献量。如果特征值很小,你可以非常接近地表示信号而不使用它相应的特征函数,这就是你如何摆脱一个维度。

答案 3 :(得分:9)

热门答案很好但很老,所以我想加上 2016年答案

如上所述,在高维空间中,维度的诅咒潜伏在拐角处,使得传统方法(如流行的k-d树)与蛮力方法一样慢。因此,我们转而关注近似最近邻搜索(ANNS),这有利于一些准确性,从而加快了这一过程。你得到了精确NN的良好近似值,具有良好的可行性。

可能值得的热门话题:

  1. LSH 的现代方法,例如Razenshteyn
  2. RKD森林:随机k-d树(RKD)的森林,如FLANN中所述, 或者是我最近参与的方法kd-GeRaF
  3. LOPQ 代表本地优化产品量化,如here所述。它与新的Babenko + Lemptitsky的approach非常相似。
  4. 您还可以查看我的相关答案:

    1. Two sets of high dimensional points: Find the nearest neighbour in the other set
    2. Comparison of the runtime of Nearest Neighbor queries on different data structures
    3. PCL kd-tree implementation extremely slow

答案 4 :(得分:8)

逐一回答您的问题:

  • 不,欧氏距离在高维空间中是一个坏指标。基本上在高维度上,最近和最远的邻居之间几乎没有差别。
  • 很多论文/研究都存在于高维数据中,但大部分内容需要大量的数学软化。
  • KD树对于高维数据是不利的......一定要避免它

这是一篇很好的论文,可以帮助您开始正确的方向。 “When in Nearest Neighbour meaningful?”由Beyer et all。

我使用尺寸为20K及以上的文本数据。如果你想要一些与文本相关的建议,我可能会帮助你。

答案 5 :(得分:5)

余弦相似性是比较高维向量的常用方法。请注意,因为它是相似性而不是距离,所以您希望最大化它而不是最小化它。您还可以使用特定于域的方式来比较数据,例如,如果您的数据是DNA序列,您可以使用考虑到突变概率的序列相似性等。

使用的最近邻居的数量取决于数据的类型,有多少噪音等。没有一般规则,您只需通过尝试所有值来找到最适合您的特定数据和问题的方法在一定范围内。人们可以直观地理解,数据越多,所需的邻居就越少。在假设您拥有所有可能数据的情况下,您只需要查找要分类的单个最近邻居。

已知k最近邻方法在计算上是昂贵的。这是人们转向支持向量机等其他算法的主要原因之一。

答案 6 :(得分:4)

kd-trees确实在高维数据上运行得非常好。因为修剪步骤不再有用,因为最近的边缘 - 一维偏差 - 几乎总是小于已知最近邻居的全维偏差。

但此外,kd-tree在我所知道的情况下只适用于Lp规范,并且存在距离集中效应,使基于距离的算法随着维数的增加而降低。

有关详细信息,您可能需要阅读维度的诅咒及其各种变体(它有多个方面!)

我不相信盲目地近似欧几里德最近邻居有很多用处,例如使用LSH或随机投影。可能有必要首先使用更精细的调谐距离函数!

答案 7 :(得分:3)

很大程度上取决于你想知道最近邻居的原因。如果您真正想要的是找到数据集的模式,您可以查看均值移位算法http://en.wikipedia.org/wiki/Mean-shift

答案 8 :(得分:3)

我认为布尔特征tf-idf上的余弦对大多数问题都有效。这是因为它经过时间验证的启发式技术在Lucene等许多搜索引擎中使用。根据我的经验,欧几里德距离对任何类似文本的数据都显示不良结果。选择不同的权重和k-示例可以通过训练数据和强力参数选择来完成。

答案 9 :(得分:3)

如果你早点退出,KD树可以正常运行21个维度, 在看完所有积分的5%之后。 FLANN这样做(以及其他加速) 匹配128-Dim SIFT向量。 (不幸的是,FLANN只做了欧几里德度量, 而快速而坚实 scipy.spatial.cKDTree 只做Lp指标; 这些您的数据可能适用也可能不适用。) 当然,这里存在速度准确性权衡。

(如果你能描述你的Ndata,Nquery,数据分布, 这可能会帮助人们尝试类似的数据。)

在4月26日添加了cKDTree的运行时间以及我的旧mac ppc的截止值,给出了一个非常粗略的可行性概念:

kdstats.py p=2 dim=21 N=1000000 nask=1000 nnear=2 cutoff=1000 eps=0 leafsize=10 clustype=uniformp
14 sec to build KDtree of 1000000 points
kdtree: 1000 queries looked at av 0.1 % of the 1000000 points, 0.31 % of 188315 boxes; better 0.0042 0.014 0.1 %
3.5 sec to query 1000 points
distances to 2 nearest: av 0.131  max 0.253

kdstats.py p=2 dim=21 N=1000000 nask=1000 nnear=2 cutoff=5000 eps=0 leafsize=10 clustype=uniformp
14 sec to build KDtree of 1000000 points
kdtree: 1000 queries looked at av 0.48 % of the 1000000 points, 1.1 % of 188315 boxes; better 0.0071 0.026 0.5 %
15 sec to query 1000 points
distances to 2 nearest: av 0.131  max 0.245

答案 10 :(得分:3)

iDistance可能是高维数据中精确检索的最佳选择。您可以将其视为近似Voronoi tessalation。

答案 11 :(得分:3)

我遇到了同样的问题,可以说如下。

  1. 欧几里德距离是一个很好的距离度量,但它的计算成本比Manhattan distance贵,有时会产生稍差的结果,因此,我选择后者。

  2. k的值可以凭经验找到。您可以尝试不同的值并检查生成的ROC curves或其他一些精确/召回度量,以便找到可接受的值。

  3. 欧几里德和曼哈顿距离都尊重Triangle inequality,因此您可以在公制树中使用它们。实际上,当数据超过10维时,KD树的性能会严重下降(我自己也遇到过这个问题)。我发现VP-trees是更好的选择。

答案 12 :(得分:2)

您可以尝试z顺序曲线。三维很容易。

答案 13 :(得分:0)

欧几里德距离是否是首先找到最近邻居的良好指标?如果没有,我的选择是什么?

我建议软子空间聚类,这是一种非常常见的方法,其中计算要素权重以找到最相关的维度。例如,在使用欧氏距离时,您可以使用这些权重。有关常见问题,请参阅维度诅咒,本文也可以通过某种方式启发您:

一种用于混合数值和空间的子空间聚类的k-means型聚类算法 分类数据集

答案 14 :(得分:0)

前一段时间我有一个类似的问题。为了快速进行“近似最近邻居”搜索,您可以使用Spotify中的烦人库:https://github.com/spotify/annoy

这是Python API的一些示例代码,该API已在C ++中进行了优化。

from annoy import AnnoyIndex
import random

f = 40
t = AnnoyIndex(f, 'angular')  # Length of item vector that will be indexed
for i in range(1000):
    v = [random.gauss(0, 1) for z in range(f)]
    t.add_item(i, v)

t.build(10) # 10 trees
t.save('test.ann')

# ...

u = AnnoyIndex(f, 'angular')
u.load('test.ann') # super fast, will just mmap the file
print(u.get_nns_by_item(0, 1000)) # will find the 1000 nearest neighbors

它们提供不同的距离测量。您要应用哪种距离测量很大程度上取决于您的个人问题。还应首先考虑对重要性进行预缩放(即加权)某些维度。这些维数或特征重要性权重可能由诸如熵损失之类的东西来计算,或者如果您有监督学习问题的基尼杂质增益或平均损失,则可以通过计算这些维数值来检查机器学习模型的性能差多少。 / p>

通常,矢量的方向比其绝对值更重要。例如,在文本文档的语义分析中,我们希望文档向量在语义相似而不是长度相似时保持闭合。因此,我们可以将这些向量归一化为单位长度,或者使用角距离(即余弦相似度)作为距离测量。

希望这会有所帮助。