K近邻算法一般是我们学习机器学习的入门算法,本篇文章详细介绍了K近邻算法,并对其原理进行了说明。同时,为了优化K近邻算法查找最近K个邻域样本的性能,本文也对KD进行详细介绍和原理说明。相信通过文本的学习,您对K近邻算法和KD树一定有更深的理解,本文的全部内容如下所示!
假设现在有这么一种情况,如下图所示,平面上有两类点,其中有三个A类点,两个B类点,我们如何确定新的点(?点)属于A类点还是B类点呢?
一个非常自然的想法就是,如果它(?点)更靠近A类点,那么就属于A类点,反之,如果它更靠近B类点,那么就属于B类点。所以,我们可以选择距离它最近的三个点作为参考点,如下图所示:
可以看到,在离它最近的三个点中,其中一个属于A类点,两个属于B类点,如果此时我们采用少数服从多数的原则,就可以判断它属于B类点,这种分类算法就是K近邻( K-Nearest Neighbor,KNN )算法,在本例中,因为选取了三个点作为参考点,所以K=3,这也是K近邻算法名称的由来。K近邻算法通常由三个要素:
现在我们考虑更一般的情况,假设现在有数据集 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) } T=\{(x_{1},y_{1}),(x_{2},y_{2}),\dots ,(x_{n},y_{n})\} T={(x1,y1),(x2,y2),…,(xn,yn)},其中每一个元素是一个样本,数据集 T T T中共 N N N个样本,其中:
假设现在数据集 T T T中共有 5 5 5( n = 5 n=5 n=5)个样本点,我们的目的就是将待分类样本 ( x , y ) (x,y) (x,y)进行正确的样本分类
根据上面介绍过的K近邻算法,我们可以首先找到待分类样本 ( x , y ) (x,y) (x,y)的邻域:
找到其邻域后,我们就可以对待分类样本 ( x , y ) (x,y) (x,y)进行分类,这个过程共分为两步:
这里首先要解决的问题就是如何计算 x x x的邻域 N k ( x ) N_{k}(x) Nk(x),一个非常自然的想法就是计算 x x x和每个样本之间的距离,如下图所示:
然后将计算后得到的距离保存在一个数组里面:
因为我们要找距离最近的K个样本作为邻域样本,所以对数组进行升序排序,排序后的前K个数据,就代表了距离 x x x最近的K个样本,那么这K个样本就是 x x x的邻域样本:
上面提到的这种方法虽然很简单,但是需要计算 x x x和每个样本之间的距离,所以整个线性查找计算过程的时间复杂度为 O ( N ) O(N) O(N),所以计算量较大,那么是否存在更加快速的求邻域的方法呢?答案是有的,也就是我们耳熟能详的KD树(K-Dimensional Tree)。
以下图中的七个初始样本为例,这七个样本作为初始样本使用,如果有需要进行分类的样本,那么就要计算待分类样本与这七个初始样本之间的距离。
刚才我们也提到了,如果全部都遍历求距离的话,计算量较大,所以我们使用KD树来计算最小距离,在使用KD树之前,我们首先要对初始样本进行KD树的初始化,整个过程如下所示:
需要注意的是,分割后的两个子空间中分别只有一个样本,那么我们分别将这两个样本储存为叶节点,如下图所示:
此时,我们已经将七个初始样本进行了KD树的初始化,假如现在有一个待分类样本 x x x,其坐标为 [ 438 , 681 ] [438,681] [438,681]。如下图所示:
此时我们该如何利用已经初始化好的KD树寻找和 x x x最近的样本呢?整个过程如下所示:
现在我们已经确定了距离待分类样本 x x x最近的初始样本所处的范围(上图中圆圈内的部分),所以我们只需要计算在这个范围内的所有初始样本与待分类样本 x x x的距离,然后通过不停的更新最小距离样本就可以得到距离待分类样本 x x x最近的初始样本了,这个过程我们可以通过回溯算法遍历KD树得到,在回溯的过程中需要记住一个查找原则:如果此节点所代表的空间范围和查找范围相交,则计算与待分类样本 x x x的距离,否则不计算,整个回溯遍历KD树的过程如下所示:
① 首先回溯到节点二的父节点,也就是节点一,因为节点一所代表的空间范围和查找范围相交,所以我们计算节点一到待分类样本 x x x之间的距离,并更新最小距离样本(因为节点一与待分类样本 x x x之间的距离更小)。然后继续回溯到节点三,按照同样的方法计算并更新最小距离,如下图所示:
② 以此类推,我们可以回溯到根节点,计算每一个和查找范围相交的节点(橙色的节点)与待分类样本 x x x之间的距离,最后发现和待分类样本 x x x最近的节点就是节点三,这个过程如下图所示:
可以看到,通过KD树查找距离最近的样本时,并不需要对每个样本都计算距离,在上例中节点五并没有参与计算,因为节点五所代表的空间范围和查找范围不相交,所以就可以节省很多不必要的计算。在当 n n n足够大,且样本随机分布的情况下,KD树检索距离最近样本的平均时间复杂度为 O ( l o g N ) O(logN) O(logN),很明显比最开始提到的线性查找计算性能更高。
如果我们使用KD树作为计算距离最近的初始样本的检索方法,此时假设初始样本为 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , … , ( x n , y n ) } T=\{(x_{1},y_{1}),(x_{2},y_{2}),\dots ,(x_{n},y_{n})\} T={(x1,y1),(x2,y2),…,(xn,yn)},待分类样本为 ( x , y ) (x,y) (x,y),那么原来的K近邻算法可以被改进为如下步骤:
以上就是本文的全部内容了,后续还会为大家带来更优质的关于机器学习的算法博客,下篇博文见!