kd树优化的k近邻算法

前言

k紧邻最简单的实现方法是线性扫描,即遍历整个训练数据集,计算每一个训练实例与输入实例之间的距离。时间复杂度为o(N),当训练数据集中的实例点数N很大时,非常耗时,为了提高k近邻搜索的效率,可以使用特殊的数据结构存储训练数据,以减少计算距离的次数。常用的算法就是kd树方法。

1. kd—Tree

Kd-Tree,即K-dimensional tree,是一棵二叉树,树中存储的是一些K维数据,(这K不是K近邻的K)。在一个K维数据集合上构建一棵Kd-Tree,就相当于不断用垂直于坐标轴的超平面将k维空间划分,构成一系列的k维超矩形区域,即树中的每个结点就对应了一个K维的超矩形区域(Hyperrectangle)。

1.1 BST(二叉搜索树)

  1. 若它的左子树不为空,则左子树上所有结点的值均小于它的根结点的值;
  2. 若它的右子树不为空,则右子树上所有结点的值均大于它的根结点的值;
  3. 它的左、右子树也分别为二叉搜索树;

如果数据是一维数据。那么构造BST的过程如下:

  1. 将数据排序,将中间位置的数据作为根节点;
  2. 根节点数据之前的数据作为根节点的左子树,根节点数据之后的数据作为根节点的右子树;
  3. 递归的构造左右子树。
将一维空间的BST推广到K维空间之后,创建二叉树和查询二叉树的算法会有一些相应的变化。

2. kd树的构造

kd树优化的k近邻算法_第1张图片

2.1 切割维度dim的选取

在李航老师的《统计学习方法》一书中,是依次选择坐标轴对空间进行切割,也就是第一次分割的时候,选择第一个维度,第二次分割的时候选择第二个维度……
在这里插入图片描述
mod是取模的意思。直到分割完所有的实例点。
但是按照坐标轴轮着来会出现一定的问题。我看了一篇博客,上面举了一个例子:
kd树优化的k近邻算法_第2张图片
博客链接:Kd-Tree算法原理和开源实现代码

因此,为了避免出现这样的问题,这里采用了最大方差法,来作为切割维度的选取标准,即:在当前的数据中心哪一个维度的方差大,就把那个维度作为分割维度。

2.2 左右子树的划分依据

和一维BST构造相同,先把数据按照当前的切割维度进行排序,然后选取中间值作为根节点,如果当前维度小于根节点的值,就是左子树,如果当前维度大于根节点的值,就是右子树。这样每个子树都对应了一个超矩形区域,左子树是某一维度的值小于中间值,右子树时某一维度的值大于中间值。

3. kd树的构造算法

3.1 算法过程

kd树优化的k近邻算法_第3张图片

3.2 举例

这个例子是李航老师《统计学习方法》中的一个例子:

kd树优化的k近邻算法_第4张图片
kd树优化的k近邻算法_第5张图片
kd树优化的k近邻算法_第6张图片

4. 利用kd树进行最近邻搜索

这里以最近邻(k=1)为例,最近邻搜索是利用已经构造好的kd树搜索与输入实例距离最近的实例点,这种方法可以拓展到k近邻,k近邻和最近邻思想和算法过程是相同的,知识有一些细节需要修改一下。

4.1 最近邻搜索的算法

kd树优化的k近邻算法_第7张图片
kd树优化的k近邻算法_第8张图片

4.2 怎样判断父节点的另一子节点区域是否有离x更近的点?

从几何空间上来看,就是判断以x为中心center和以最近距离为半径的超球面与另一子节点对应的超矩形区域之间是否相交。
在实现中,我们可以用以下方式来求x与另一子节点对应的区域之间的距离。

在构造树的过程中,记录下每个子树所在的分割维度dim和分割值m(即根节点的dim维度的值),x与子树的距离则为|x(dim) - m|。当|x(dim) - m|大于当前最近距离时,说明另一节点的区域与超球面没有交集,如果小于当前最近距离,说明有交集,可能有更近的点,转到另一个子节点的区域。

4.3 举例

以上面构造的kd树为例:设输入实例为(6,3)
kd树优化的k近邻算法_第9张图片
搜索过程如下:
kd树优化的k近邻算法_第10张图片

你可能感兴趣的:(机器学习)