【问题标题】:Can someone tell me about the kNN search algo that Matlab uses?有人能告诉我关于 Matlab 使用的 kNN 搜索算法吗?
【发布时间】:2014-06-04 05:23:32
【问题描述】:

我为最近邻搜索编写了一个基本的 O(n^2) 算法。像往常一样,Matlab 2013a 的 knnsearch(..) 方法工作得更快。

谁能告诉我他们在实现中使用了什么样的优化?

我可以阅读您可能指向我的任何文档或论文。

PS:我知道网站上的文档提到了关于 kd 树的论文作为参考。但据我了解,当列数小于 10 时,kd 树是默认选项。我的是 21。如果我错了,请纠正我。

【问题讨论】:

  • 如果您想查看差异在哪里,请尝试在您的代码和 matlab 代码上使用profile,看看哪些部分有显着差异。

标签: matlab machine-learning knn


【解决方案1】:

MathWorks 在实现最近邻搜索方面所做的最大优化是所有困难的东西都在 MEX 文件中实现,如编译后的 C,而不是 MATLAB。

使用诸如 kNN 之类的算法(在我有限的理解中)是相当递归且难以矢量化的,这可能会带来这样的改进,以至于 O() 分析仅在相当高的 n 时才相关。

更详细地说,knnsearch 命令在后台使用createns 创建NeighborSearcher 对象。默认情况下,当X 的列数少于 10 列时,这将是一个 KDTreeSearcher 对象,而当 X 的列数超过 10 列时,它将是一个 ExhaustiveSearcher 对象(KDTreeSearcherExhaustiveSearcher 都是NeighborSearcher 的子类)。

NeighbourSearcher 的所有对象都有一个方法knnsearch(你很少会直接调用它,而是使用方便的命令knnsearch 而不是这个方法)。 KDTreeSearcherknnsearch 方法直接调用 MEX 文件以完成所有艰苦的工作。它位于 matlabroot\toolbox\stats\stats\@KDTreeSearcher\private\knnsearchmex.mexw64 中。

据我所知,这个 MEX 文件执行的算法与 Friedman、Bentely 和 Finkel 在文档页面中引用的论文中描述的算法几乎相同,没有结构变化。正如论文的标题所暗示的,这个算法是 O(log(n)) 而不是 O(n^2)。遗憾的是,无法检查 MEX 文件的内容以确认这一点。

【讨论】:

  • 实际上,kNN 很容易在几行代码中实现完全向量化(参见here for an example)。基本上,我们计算查询实例和所有训练点之间的距离矩阵(穷举搜索),按距离排序,取最近的K 点,然后应用多数投票来确定类标签。艰苦的工作由pdist2 完成,可能是vectorized into a single bsxfun call(虽然不建议用于大型数据集,因为您很容易耗尽内存)
  • @Amro 您在这里谈论的只是kNN 的详尽搜索算法,对吗? - 是的,这显然是可矢量化的。但是,我声称 KDTree 算法是相当递归且难以矢量化的,这是错误的吗?正如我所说,我对此的理解是有限的。 (实际上我刚刚意识到我的第二段是指一般意义上的 kNN,而不仅仅是 KDTrees,这就是我的意思)。
  • 对,我指的是朴素的 kNN 算法(穷举搜索)。构建和搜索 KD 树是一种迭代算法,不容易向量化(如果有的话)。我想您在第二段中谈论的是哪一个有点不清楚...对于任何感兴趣的人,这里是a page,其中包含有关 kd-trees 的简短教程和一些不错的动画。顺便说一句,IPT 工具箱在$toolboxdir\images\images\private\kdtree.m 中也有一个私有的 kd 树实现,并带有相应的 MEX 函数nnsearch 来执行搜索
【解决方案2】:

code 构建了一个KD-tree 空间分区结构来加速nearest neighbor search,把它想象成构建RDBMS 中常用的indexes 来加速查找操作。

除了最近邻搜索之外,此结构还加快了range-searches 的速度,它可以查找距离查询点r 范围内的所有点。

正如@SamRoberts 所指出的,代码的核心是在 C/C++ 中作为 MEX 函数实现的。

请注意,knnsearch 仅在特定条件下选择构建KD-tree,否则会退回到穷举搜索(通过天真地搜索所有点来寻找最近的点)。

请记住,在非常高维的数据(和少数实例)的情况下,算法会退化并且并不比穷举搜索好。一般来说,当您使用维度d>30 时,搜索 KD-trees 的成本将增加到搜索几乎所有点,并且由于构建树所涉及的开销,甚至可能变得比蛮力搜索更糟糕。

处理高维的算法还有其他变体,例如ball trees,它将数据划分为一系列嵌套的超球体(而不是像 KD 树一样沿笛卡尔轴划分数据)。不幸的是,这些都没有在官方统计工具箱中实现。如果您有兴趣,这里是a paper,它提供了对可用 kNN 算法的调查。

(上面是搜索 kd-tree 分区的 2d 空间的图示,借用自文档)

【讨论】:

    猜你喜欢
    • 2015-09-20
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-31
    • 2013-12-16
    相关资源
    最近更新 更多