目录
引入kd树
k
k
k近邻实现的方法是线性扫描。需要计算输入与每个训练实例的距离。如果训练集非常大,那么计算非常耗时。为了提高
k
k
k近邻搜索的效率,可以使用特殊的结构来存储训练数据,以减少计算距离的次数,
k
d
kd
kd树就是其中的一种方法。
k
d
kd
kd树是一种对
k
k
k维空间种的实例点进行存储以便对其进行快速检索的树形数据结构。
k
d
kd
kd树是二叉,是对
k
k
k维空间的一个划分。
kd树和KNN选择的方法:
假设一个数据有N个样本,维度维k。
1.当
N
>
>
2
k
N >>2^{k}
N>>2k,选择
k
d
kd
kd树
2.当k维空间接近训练实例数(N)时,选择KNN,因为
k
d
kd
kd的效率会迅速下降,几乎接近线性扫描
构造kd树
kd树的构造方法:
- 构造根节点,使根节点对应于k维空间中包含所有实例点的超矩形区域。
- 通过递归的方法,不断的对 k k k维空间进行切分,生成子节点。
- 切割的方法:在超矩形区域上选择一个坐标轴和这个坐标轴上的中点,通过过中点垂直于坐标轴将当前的超矩形区域切分维两个子区域。一直重复这个过程,直至没有可切分的点。
中值选择
- 对原始数据点在所有维度进行一次排序,存储下来,在以后的过程中只需查找不需计算。
- 从原始数据中随机选择固定数目的点,然后对这些点进行排序,每次从这些样本点中选择中值,来切分超平面,该方法具有很好的性能和平衡性。
例子
二维平面点(x,y)的集合X={
(
2
,
3
)
,
(
5
,
4
)
,
(
9
,
6
)
,
(
4
,
7
)
,
(
8
,
1
)
,
(
7
,
2
)
(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)
(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}。以此为例,构建一个
k
d
−
t
r
e
e
kd-tree
kd−tree。
-
构建根节点时,此时的切分维度为x,以上集合点在x维从小到大排序为(2,3),(4,7),(5,4),(7,2),(8,1),(9,6);其中值为(7,2)。
注: 2,4,5,7,8,9在数学中的中值为(5 + 7)/2=6,但因该算法的中值需在点集合之内, 所以中值计算用的是len(X)//2=3, sorted[3]=(7,2)。 -
所以(2,3),(4,7),(5,4)挂在(7,2)节点的左子树,(8,1),(9,6)挂在(7,2)节点的右子树。
-
构建(7,2)节点的左子树时,集合点为{(2,3),(4,7),(5,4)},此时的切分维度为y,中值为(5,4)作为分割平面,(2,3)挂在其左子树,(4,7)挂在其右子树。
-
构建(7,2)节点的右子树时,集合点{(8,1),(9,6)},此时的切分维度也为y,中值为(9,6)作为分割平面,(8,1)挂在其左子树。至此 k d kd kd-tree构建完成,如下图所示。
kd树搜索
k 近 邻 k近邻 k近邻
- 找到包含目标点的叶节点,以目标点和叶节点的距离为半径画圆。
- 退回父节点,如果父节点的另一个节点的超矩形区域与圆相交,在这个区域内找出这些点。
- 退回到更上一级的父节点,继续以上操作。
- 如果父节点的零一节点的超矩形区域与超球体不相交,则该区域不存在更近点
例子
设点x=(5.2,5.4)
- 找到包含x的叶节点。x点的x维值为5.2,小于中点值7,所以落到(7,2)的左子节点,x的y维值为5.4,大于y维的中点4,所以落在了(5,4)的右子节点。因此包含x的叶节点为(4,7)。最近邻点一定在以x为圆心,以x点到(4,7)距离为半径的圆内。
- 返回父节点(5,4),看是否在圆内,如果在则为最近点
- 查看(5,4)的左节点看是否相交,不相交则没有最近点,否则计算距离。
- 继续退回父节点(7,2)看是否相交
- 查看(7,2)的右节点是否在圆内
- 查看(8,1)是否与圆相交
- 在以上里面寻找最近点