k近邻法学习笔记
一、概念
k近邻法(kNN)是一种基本的分类与回归的方法,通过选取与待分类的实例最相近的k个实例,将k个实例对应的类别中通过多数表决的方法进行预测,将其作为该实例的预测类标签。
当k = 1时,kNN算法也称为最近邻算法。
二、k近邻模型
k近邻模型主要由三部分组成:距离度量、k值大小、分类决策规则。
(1)距离度量
距离度量是衡量实例之间近似程度的一个标准,不同的距离度量标准下,实例之间的距离远近也不尽相同。下面简单介绍一下几种常见的距离度量的方法:
a.欧氏距离(Euclidean Distance)
欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式。
a-1.二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:
a-2.三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
a-3.两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
也可以用表示成向量运算的形式:
b.曼哈顿距离(Manhattan Distance)
从名字就可以猜出这种距离的计算方法了。想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。实际驾驶距离就是这个“曼哈顿距离”。而这也是曼哈顿距离名称的来源, 曼哈顿距离也称为城市街区距离(City Block distance)。
(1)二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离
(2)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的曼哈顿距离
c.闵可夫斯基距离(Minkowski Distance)
闵氏距离不是一种距离,而是一组距离的定义。
两个n维变量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的闵可夫斯基距离定义为:
其中p是一个变参数。
当p=1时,就是曼哈顿距离
当p=2时,就是欧氏距离
当p→∞时,就是切比雪夫距离
根据变参数的不同,闵氏距离可以表示一类的距离
除此之外,还有标准化欧氏距离、马氏距离、夹角余弦、汉明距离……具体可以从这篇博客中了解:http://www.cnblogs.com/heaad/archive/2011/03/08/1977733.html
(2)k值大小
k值的选择对该算法的结果会产生较大的影响,在应用中,我们一般选取一个比较小的k值(如k = 20),可以通过交叉验证的方法来选取最优的k值
(3)分类决策规则
kNN算法的分类决策规则一般选取多数表决的规则,即由输入实例的k个最邻近的实例中的多数类决定该实例的类标签。
三、kd树
kNN算法一个很大的问题在于它的时空复杂度,需要对所有的实例继续距离的计算和比较,如果采用最简单的顺序线性扫描的方法,非常耗时,因此,kd树正是为了解决这个问题而产生的。
kd树是一种对k维空间中的实例点进行存储以便对其进行快速检索的二叉树结构。
下面给出构建一棵平衡的kd树的算法:
输入:k维空间的数据集T = {x1,x2,x3,...,xN},其中xi= (xi(1),xi(2),...,xi(k)),i = 1,2,...,N
输出:kd树
算法:
1、构造树的根节点,选择x(1)为坐标轴,将T中所有的实例的x(1)坐标的中位数作为切分点,生成根节点,存储该实例,将T中的实例的x(1)坐标小于切分点的实例放在左子树,T中的实例的x(1)坐标大于切分点的实例放在右子树
2、不断重复1中的算法,选择x(2,3,...)作为坐标轴,对左右两个子树上面对应的T的子集进行循环,直到没有实例停止
构建完一棵kd树之后,怎么对它进行搜索呢?怎么最快找到k个最近的实例呢?下面将给出对应的算法:
输入:kd树;目标点x
输出:x的最近邻
算法:
1、kd树中找到包含目标点x的叶子节点:从根节点出发,若x的当前维的坐标小于切分点的坐标,则移动到左子树;大于则移动到右子树,直到找到叶子节点。2、以此节点为“当前最近点”
3、递归向上回退,在每一个节点处进行以下操作:
3-1、如果该节点保存的实例点比当前最近的点距离目标点更近,则以该实例点为“当前最近点”
3-2、当前最近点一定存在于该节点的一个子节点对应的区域。检查该子节点的父节点的另一个子节点对应的区域是否有更近的点。具体的,检查另一个子节点对应的区域是否与以目标点为球心、以目标点与“当前最近点”间的距离为半径的球相交。若相交,可能在另一个子节点对应的区域内存在剧目标点更近的点,移动到另一个子节点。接着,递归进行最近邻搜索;否则,向上回退。
4、当回退到根节点时,搜索结束。最后的“当前最近点”即x的最近邻。