k近邻算法与kd树的创建和搜索 -ag凯发k8国际
hit2015spring晨凫追风
欢迎关注我的博客:http://blog.csdn.net/hit2015spring
k近邻算法
是一种常用的监督学习的方法:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于k个邻居的信息来进行预测。通常:
分类任务中用投票,选择k个样本中出现最多的类别标记作为预测结果 回归任务中:平均法 还可以基于距离的远近进行加权平均或者加权投票,距离越近权重越大没有显示的训练过程,训练时间开销为0,是一种懒惰学习
分类的结果与k的选择和距离计算方式的选择有关系
上图可以看出二维空间中,距离的计算方式不同,包含的区域也是不相同的。故会影响结果
k值得选择也会对结果产生影响,k值小的话,相当于用较小的邻域中的训练实例进行预测,学习的近似误差会减小,只有与输入实例较近的训练实例才会对预测结果起作用,但是估计误差会增大,意味着会产生过拟合。
kd树的构建
实现k近邻方法时,面临一个计算速度的挑战问题,当特征空间的维数非常大以及训练数据非常大的时候,我们优化这个搜索的方法就显得尤为重要了
一般方法:最简单的是实现一个线性扫描,就是计算输入的实例与每一个训练实例之间的距离,训练集很大的时候,计算会耗时很长,于是就出现了kd树的这种方法。
构造kd树的数学描述比较难懂:
输入的是k维空间数据集t={x1,x2,⋯,xn},注意这里的k维指的是特征的维度是k维,即xi=(x(1)i,x(2)i,⋯,x(k)i),i=1,2,⋯,n
(1)开始:构造根结点,根结点对应于包含t的k维空间的超矩形区域.选择x(1)为坐标轴,以t中所有的实例的x(1)坐标的中位数为切分点,将根结点对应的超矩形区域划分为两个子区域。切分由通过切分点并与坐标轴x(1)垂直的超平面实现。
由根结点生成深度为1的左右两个子结点:左结点对应坐标x(1)小于切分点的子区域,右结点对应于坐标x(1)大于切分点的子区域,落在切分超平面的点保存在根结点
(2)重复:对深度为j的结点,选择x(l)为切分的坐标轴,以该结点的区域内部所有的实例的x(l)坐标的中位数作为切分点,将该结点对应的矩形区域切分为两个子区域。切分由通过切分点并与坐标轴x(l)垂直的超平面实现。
该结点生成左右两个结点,左结点对应坐标x(l)小于切分点的子区域,右子结点对应坐标x(l)大于切分点的子区域。落在切分超平面上的实例点保存在该结点。
(3)直到两个子区域没有实例存在时停止。
直接通过一个例子来理解:
简单的理解就是:每次选择一个维度的特征,把该实例点划分为两个部分,一个大于中位数,一个小于中位数,中位数就保留在这个结点,其他的放到下一层中,继续上面的过程。
当然了这里面的关键是怎么选取要切分那个维度呢?
最简单的方法就是轮着来,即如果这次选择了在第i维上进行数据划分,那下一次就在第j(j≠i)维上进行划分,例如:j = (i mod k) 1。想象一下我们切豆腐时,先是竖着切一刀,切成两半后,再横着来一刀,就得到了很小的方块豆腐。
可是“轮着来”的方法是否可以很好地解决问题呢?再次想象一下,我们现在要切 的是一根木条,按照“轮着来”的方法先是竖着切一刀,木条一分为二,干净利落,接下来就是再横着切一刀,这个时候就有点考验刀法了,如果木条的直径(横截 面)较大,还可以下手,如果直径较小,就没法往下切了。因此,如果k维数据的分布像上面的豆腐一样,“轮着来”的切分方法是可以奏效,但是如果k维度上数 据的分布像木条一样,“轮着来”就不好用了。因此,还需要想想其他的切法。
如果一个k维数据集合的分布像木条一样,那就是说明这k维数据在木条较长方向 代表的维度上,这些数据的分布散得比较开,数学上来说,就是这些数据在该维度上的方差(invariance)比较大,换句话说,正因为这些数据在该维度 上分散的比较开,我们就更容易在这个维度上将它们划分开,因此,这就引出了我们选择维度的另一种方法:最大方差法(max invarince),即每次我们选择维度进行划分时,都选择具有最大方差维度。
最后再给一个例子看看:
运用kd树查找
构建好了kd树之后就是利用kd树来进行最近邻查找了:
(1)将查询数据q从根结点开始,按照q与各个结点比较的结果向下访问kd树,直到查找到叶子结点。
就是把q的k个特征,在每一个结点上面的维度k与对应的分割的值m(那个中位数)这样向下走,就到了一个叶子结点,把q与结点上面的数据进行计算距离,记做当前的最近邻点p_point和最小距离p_dist。
(2)进行回溯操作,这个操作是为了找到离q点更加近的最近邻点。即判断没有被访问的分支里面的点是否还具有更近的点。
如果q与其父结点下的未被访问过的分支之间的距离小于dcur,则认为该分支中存在离p更近的数据,进入该结点,进行(1)步骤一样的查找过程,如果找到更近的数据点,则更新为当前的“最近邻点”pcur,并更新dcur
怎样判断未被访问的树的分支里面是否有离q更近的点?
从几何空间上来看,就是判断以q为中心center和以dcur为半径radius的超球面(hypersphere)与树分支branch代表的超矩形(hyperrectangle)之间是否相交。
在实现中,在构造树的过程中,记录下每个子树所在的分割维度k和分割值m,(k, m),q与子树的距离则为|q(k) - m|。即这个距离和当前存的最小距离相比较,如果有比这个距离小,那就进去搜索,如果没有那就往上面回溯。
就是理解为超球体和超平面是否相交
以上就是kd-tree的构造过程和基于kd-tree的最近邻查找过程。
下面用一个简单的例子来演示基于kd-tree的最近邻查找的过程。
数据点集合:(2,3), (4,7), (5,4), (9,6), (8,1), (7,2) 。
已建好的kd-tree:
假设我们的k-d tree就是上面通过样本集{(2,3), (5,4), (9,6), (4,7), (8,1), (7,2)}创建的。
我们来查找点(2.1,3.1),在(7,2)点测试到达(5,4),在(5,4)点测试到达(2,3),然后search_path中的结点为<(7,2), (5,4), (2,3)>,从search_path中取出(2,3)作为当前最佳结点nearest, dist为0.141;
然后回溯至(5,4),以(2.1,3.1)为圆心,以dist=0.141为半径画一个圆,并不和超平面y=4相交,如下图,所以不必跳到结点(5,4)的右子空间去搜索,因为右子空间中不可能有更近样本点了。
于是在回溯至(7,2),同理,以(2.1,3.1)为圆心,以dist=0.141为半径画一个圆并不和超平面x=7相交,所以也不用跳到结点(7,2)的右子空间去搜索。
至此,search_path为空,结束整个搜索,返回nearest(2,3)作为(2.1,3.1)的最近邻点,最近距离为0.141。
参考文章
参考文章
福利答谢大家!
感谢您阅读本篇文章,对此特别发放一个无门槛的现金红包,打开支付宝扫码领取!
总结
以上是ag凯发k8国际为你收集整理的k近邻算法与kd树的创建和搜索的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇:
- 下一篇: