基于KDTree的KNN实现

1. KNN算法

K Nearest Neighbors 可用于分类问题,就是新样本和训练集的所有样本作对比,找出与之最接近的K个样本,统计最近的k个训练样本中所属类别计数最多的那个类,就是新样本的类。
该算法简单直观,但是每次查询都需要和所有样本进行比较,代价很大。一种优化方法是基于KD树的实现。

2. KD树

KD树是一个二叉树,表示对K维空间的一个划分,它的功能就是在高维空间下进行一个快速的最近邻查询。利用KD树可省去对大部分数据点的搜索,从而减少搜索的计算量。

2.1 KD树构建

构建KD树相当于不断地用垂直于坐标轴的超平面将K维空间进行划分,构成一系列的K维超矩形区域,KD树的每一个节点对应于一个K维超矩形区域。
通常依次选择坐标轴对空间进行切分,选择训练样本在选定坐标轴上的中位数为切分点,这样得到的KD树是平衡的。但是,平衡的KD树搜索时的效率未必是最优的。也有选择 熵最大的特征值进行切分,个人感觉这里更有理由,因为熵越大,说明样本在这一维度上信息越大,切分后效果会越好。

2.2 KD树搜索


记待查询点的样本点为Q,样本点为xi,样本维度为d,即xi = {a1, a2, ..., ad}
  1. 首先从根节点开始递归往下找到包含Q的叶子节点,每一层都是找对应的xi;
  2. 将这个叶子节点认为是当前的“近似最近点”;
  3. 递归向上回退,如果以Q圆心,以“近似最近点”为半径的球与根节点的另一半子区域边界相交,则说明另一半子区域中存在与Q更近的点,则进入另一个子区域中查找该点并且更新”近似最近点“;
  4. 重复3的步骤,直到另一子区域与球体不相交或者退回根节点;
  5. 最后更新的”近似最近点“与q真正的最近点.
如果想找到K个最近点,可以使用维护一个长度为K的最大堆。(不是数组的 Top K问题,是BST的 Top K问题)

如果样本点是随机分布的,KD树搜索的平均计算复杂度为O(logN),其中N为训练样本个数。KD树更适用于训练样本树远大于空间维数的KNN搜索。当样本个数接近空间维数时,它的效率会急剧下降,几乎接近线性扫描。

3. 相关知识补充

3.1 二叉排序树

1. Binary Sort Tree(BST),又称为二叉查找树,它或者是一颗空树,或者是具有如下性质的二叉树:

(1)若左子树不为空,值小于根节点;
(2)若右子树不为空,值大于根节点;
(3)左右子树也是二叉排序树

        2. 二叉排序树的中序序列是一个有序序列,所以对一个任意的关键码字序列构造一颗二叉排序树,其实质是对此关键码字序列进行排序,使其变为有序序列。

        3. 类似于折半查找,二叉排序树上的查找,和关键码字的比较次数不超过树的深度。最坏情况下,退化成单枝顺序查找O(N);最好情况下,相当于折半查找O(logN)

3.2 平衡二叉树

  1. Balanced Binary Tree,又被称为AVL树。它或者是一颗空树,或者是具有如下性质的树:
(1)左右子树是平衡二叉树;(2)左右子树高度差不超过1
如果在建立排序二叉树的同时,保证其为平衡二叉树,可避免查找的时间复杂度由O(logN)退化成O(N)

  

       2. 在平衡二叉树上比较的次数不超过树的高度,而平衡二叉树相当于折半查找的判定树,因此它的时间复杂度为O(logN)

       3. 平衡二叉树的树结构比较好,但其插入删除的运算较为复杂,因此适用于一旦建立就很少进行插入和删除的运算,主要用于查找的场合。


你可能感兴趣的:(machine,learning,学习笔记)