主要问题:
当实现KNN算法的时候,主要问题是如何快速的,在训练样本中找到,距离我们要判断类型的样本点(以下简称点),最近的k个点。
解决方法:
1:线性扫描:
什么是线性扫描?线性扫描就是当你输入一个点的时候,就要计算这个点和所有已知类比的点的距离,然后通过比较(一般都是直接排序),然后找到最近的k个点。
我的上一篇博客中使用的方法就是这种,详情请点击关于KNN算法的基础及其底层代码实现
这种方法的缺点很明显:过于耗时!
2:KD树:
什么是KD树:
下面是百科给的解释:
很抽象,下面是我的理解:
KD树用于多维空间关键数据的搜索,这多维空间是什么意思呢?跟我们学的有什么联系呢?
上一篇博客中我已经说过,我们在分类问题中,是要对样本进行特征提取的,我们最终会提取成特征向量的形式,例如:某电影(戏剧内容,格斗内容,爱情内容......)在代码中就是(X1,X2,X3......)这就是一个特征向量。
而对于KD树算法,则是将特征向量看成多维空间内的一个点,其各个特征就是其在空间内对应各轴的坐标,就例如一只狗(眼睛颜色黄,毛发黄),我么们既定黄=21,则这只狗的特征向量就是(21,21),那么该样本所对应的点就在二维空间内。
KD树也是二叉树,二叉树相信大家都有所了解,KD树表示的是对k维空间的划分。
为什么要这样做呢,以下是我的理解:
(该图片来源于网络,侵权必删!)
如上图所示:我们给定一堆已有的样本数据,和一个被询问的数据点(红色五角星),我们如何找到离五角星最近的20个点?
直接算每个点跟五角星的距离肯定不现实,也不是我们的常用思路,一般我们都是找到能把五角星附近的一些点都给圈主,然后找离其最近的20个点,如下图所示:(该图片来源于网络,侵权必删!)
这画的这个圈圈其实就是对该二维空间的划分。
这下应该会有个大概了解了吧。
那么我们该如何划分?
算法步骤:
KD树算法包括以下三个步骤:
第一:构造KD树(划分)
第二:搜索最近邻
第三:预测
由于比较抽象,我们接下来就举例说明。
KD树的构造过程就是划分过程,上面就是我们要划分的目标,都是二维数据点(两个特征的样本点),所对应的空间也是二维空间。
划分的时候有两个注意点:
第一点:划分的维度,要根据数据点在各维度上的分布情况进行划分,方差越大,分布越离散,我们应当从方差大的维度开始划分,这样有更好的效果和平衡性。
补充:方差公式:
第二点:中值点的确定,一般都是先把所有点在所有维度上都进行依次排序,然后保存下来,这样后面就会方便很多。
现在我们开始构造:
KD树的构造(划分):
我们的示例:
因为是二维数据点,所在二维空间,那么接下来划分会方便一些
为了好显示,我先把划分的结果放在了这里。
在x轴上进行的排序:
(2,3)(4,5)(5,7)(6,4)(7,2)(9,6)
在y轴上的排序:
(7,2)(2,3)(6,4)(4,5)(9,6)(5,7)
第一次划分:
从x轴开始划分,我们先将他们沿着x轴方向对应的数进行排序,我们得到中位数6,我们过(6,4)点做垂直x轴的直线(其实这么说不太严谨,可是这是二维空间是一个平面,所以我就这么说了),进行一次划分,我们将它作为二叉树的根节点标记为0
这一步划分将剩下的点分成了两部分,即(2,3)(4,5)(5,7)左边一部分,(9,6)(7,2)右边一部分.
第二次划分:
这两个部分同时开始划分,两部分都沿着y轴上的数进行排序,左部份的到中值5,右部分的到中值6,那么过(4,5)点做y轴的垂线,其为(6,4)的左子节点,过(9,6)点做y轴的垂线,其为右子节点。,这样的话就相当于将二维空间划分成了四部分。
第三次划分:
四个部分同时划分,剩下的点沿着x轴上的数进行排序,其余同理......
第五次划分:
同理
这个划分沿着的某某轴,都是循环的,一般而言,二维空间就是X->Y->X->Y->......
三维就是:X->Y->Z->X->......
多维X->Y->Z->......->X->Y->Z->......->X->Y->Z......
当然我们上面也说了,要看各个轴方向对应的数所显示的离散程度。
最后就会得到这样的二叉树及其图像:
这D ,D1,D2什么的不用管就是标号而已,0,1,2,3则是做的记号,下面的图是按照记号与之对应的:
这下的话,应该可以明白二叉树怎么划分的基本方法了。
后面将介绍,KD树的搜索找最近邻,还有代码实现以及KNN算法的快速代码使用。