Python中的增量最近邻算法

时间:2010-11-25 06:10:53

标签: python machine-learning nearest-neighbor

是否有人知道在Python中实现的最近邻居算法可以逐步更新?我找到的所有内容,例如this one,似乎都是批处理过程。是否可以实现增量NN算法?

3 个答案:

答案 0 :(得分:6)

这是迟到的,但对后人来说:

实际上有一种技术可以将批量处理的算法(如KD-Tree)转换为增量算法:它称为静态到动态转换

要生成KD树的增量变体,您需要存储一组树而不是一棵树。当您的最近邻结构中有 N 个元素时,您的结构将为 N 的二进制表示中的每个“1”位都有一个树。此外,如果树 T_i 对应于 N i 位,则树 T_i 包含2 ^ < em> i 元素。

所以,如果你的结构中有11个元素,那么 N = 11或1011就是二进制,因此你有三棵树 - T_3 T_1 T_0 - 分别包含8个元素,2个元素和1个元素。

现在,让我们在我们的结构中插入一个元素 e 。插入后,我们将有12个元素,或二进制1100。比较新的和之前的二进制字符串,我们看到 T_3 没有改变,我们有一个新树 T_2 有4个元素,树 T_1 T_0 被删除。我们通过批量插入 e 以及 T_2 下面的树中的所有元素构建新树 T_2 ,这些< em> T_1 和 T_0

通过这种方式,我们从静态基础结构创建增量点查询结构。但是,以“额外 log(N)因子的形式”静态增加“这样的静态结构的渐近减速:

  • 在结构中插入 N 个元素: O(N log(N)log(n))
  • 最近邻查询 N 元素的结构: O(log(n)log(n))

答案 1 :(得分:3)

我认为,正如您在评论中提到的那样,增量构建KD树或KNN树的问题是树最终会变得不平衡,您无法进行简单的树旋转来修复平衡问题并保持一致性。至少,重新平衡任务并不简单,人们绝对不希望在每次插入时都这样做。通常,人们会选择使用批处理方法构建树,插入一堆新点并允许树变得不平衡到一个点,然后重新平衡

一个非常类似的事情是为M点批量构建数据结构,将其用于M'点,然后使用M + M'点重新构建数据结构。由于重新平衡不是我们熟悉的常规快速算法树,因此重建不一定比较慢,并且在某些情况下可以更快(取决于输入增量算法的点的顺序)。

话虽这么说,如果你采用重建方法,你编写的代码量,调试难度以及其他人对代码理解的容易程度可以大大降低。如果这样做,您可以使用批处理方法并保留尚未插入树中的外部点列表。可以使用蛮力方法来确保这些方法不比树中的方法更接近。

下面是Python实现/讨论的一些链接,但我没有发现明确声称是增量的任何链接。祝你好运。

http://www.scipy.org/Cookbook/KDTree

http://cgi.di.uoa.gr/~compgeom/pycgalvisual/kdppython.shtml

http://sites.google.com/site/mikescoderama/Home/kd-tree-knn

http://en.wikipedia.org/wiki/Kd-tree

注意:我的评论适用于高维空间。如果你在2D或3D工作,我所说的可能不合适。 (如果您在非常高维度的空间中工作,请使用蛮力或近似最近邻居。)

答案 2 :(得分:2)

有。 Scipy Cookbook WebSite包含一个kNN algorithm的完整实现,可以逐步更新。

也许有几行背景对任何有兴趣但不熟悉术语的人都有帮助。

kNN引擎由两种数据表示中的任何一种驱动 - 数据集中存储在多维数组中的所有点之间的成对距离(距离矩阵)或 kd-tree ,它只将数据点本身存储在多维二叉树中。

这些只是基于kd树的KNN算法所需的两个操作:您从数据集创建树(类似于在其他ML算法中以批处理模式执行的 training 步骤),以及您搜索树以查找“最近邻居”(类似于测试步骤)。

KNN算法上下文中的在线或增量训练(假设它基于kd树)意味着将节点插入到已经构建的kd树中。

回到SciPy Cookbook中的kd-Tree实现:负责节点插入的特定代码行出现在注释行“在kd-tree中插入节点”之后(实际上,该注释之后的所有代码都是定向的)节点插入)。

最后,在SciPy库( scipy.spatial 模块)的空间模块中有一个名为KDTree( scipy.spatial.KDTree )的kd-tree实现,但是我不相信它支持节点插入,至少这样的功能不在Docs中(我没有看过源代码)。