1. KNN算法
K近邻算法,即K-Nearest Neighbor algorithm,简称KNN算法,是一个理论上比较成熟的方法,也
是最简单的机器学习算法之一,1968年由 Cover 和 Hart 提出。
该方法的思路是:如果一个样本在特征空间中的 k 个最相似(即特征空间中最邻近)的样本中的大
多数属于某一个类别,则该样本也属于这个类别。KNN 算法中,所选择的邻居都是已经正确分类
的对象;该方法在分类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类
别。KNN算法并不具有显式的学习过程。k=1时,为最近邻搜索。
特点:基于实例之间距离和投票表决的分类,精度高、对异常值不太敏感,计算复杂度高、空间复
杂度高,特别适合多分类,简单易实现,大多数情况下比朴素贝叶斯好,给定训练集、距离度量、
k值及分类决策函数时,其结果唯一确定。
1.1 算法流程
输入:训练数据集为实例的特征向量,实例向量x
输出:实例x所属的类别y
根据给定的距离度量,在训练集T中找出与x最近的k个点,涵盖着k个点的x的邻域记作Nk(x)
在Nk(x)中根据分类决策规则(如多数表决)决定x所属的类别y。上式中,I为指示函数,即当yi=cj
时,I为1,否则为0
K近邻算法中,当训练集、距离度量、k值及分类决策规则确定后,对于任何一个输入实例,它所
属的的类唯一地确定。特征空间中,对于每个训练实例点,距离该点比其他点更近的所有点组成了
一个区域,叫单元(cell)。每个训练实例点拥有一个单元,所有训练实例点的单元构成对特征空间
的一个划分。
1.2 距离度量
特征空间是n维实数向量Rn,xi,xj∈Rn,
xi,xj的一般距离定义为闵式距离LP:
当p=2时,为欧几里得距离;当p=1时,为曼哈顿距离;当p=+∞时,为切比雪夫距离
注意:使用的距离不同,k近邻的结果也会不同的,即由不同距离度量所确定的最邻近点是不同的
1.3 K值的选择
k值得选择非常重要,对算法结果产生重要影响,如果选择的比较小的话,相当于用较小邻域中的
训练实例进行预测,学习的近似误差会减少,只有与输入实例较近的训练实例才会对预测结果起作
用,缺点是学习的估计误差会增大,易受噪声影响,极端情况是k=1。如果k值选取的比较大,相
当于用较大邻域中的训练实例进行预测,学习的估计误差会减少,但是近似误差会增大,而且与输
入实例较远的训练实例也会对预测起作用,是预测结果错误,k值的增大意味着整体模型变得简
单。因为划分的区域少了,更容易进行预测结果。极端情况是k=N。在应用中k一般取一个比较小
的值,通常采用交叉验证法来选取最优的k值。
1.4 分类决策规则
k近邻法的分类决策规则往往是多数表决,即由输入实例的k个近邻训练实例多数所属的类来决定,
如果损失函数为0-1损失,则分类函数表示为:
误分类的概率:
实例x,最近邻居集合Nk(x),如果涵盖类别为cj,误分类率为:
目标:最小化误分类率,等价于经验风险最小化
2. KD-Tree
k-d树是K-dimension tree的缩写,是对数据点在k维空间中划分的一种数据结构,主要应用于多维
空间关键数据的搜索(如:范围搜索和最近邻搜索)。本质上说,k-d树就是一种平衡二叉树,范
围查询就是给定查询点和查询距离的阈值,从数据集中找出所有与查询点距离小于阈值的数,K近
邻查询是给定查询点及正整数K,从数据集中找到距离查询点最近的K个数据。k-d树是一种空间划
分树,即把整个空间划分为特定的几个部分,然后在特定空间的部分内进行相关搜索操作。
特征匹配算法大致可以分为两类:
一类是线性扫描法,即将数据集中的点与查询点逐一进行距离比较,也就是穷举,缺点很明显,就
是没有利用数据集本身蕴含的任何结构信息,搜索效率较低;第二类是建立数据索引,然后再进行
快速匹配。因为实际数据一般都会呈现出簇状的聚类形态,通过设计有效的索引结构可以大大加快
检索的速度。索引树属于第二类,其基本思想就是对搜索空间进行层次划分。根据划分的空间是否
有混叠可以分为Clipping和Overlapping两种。前者划分空间没有重叠,其代表就是k-d树;后者划
分空间相互有交叠,其代表为R树。因此k近邻算法常用 k-d树实现。
split表示垂直于分割超平面的方向轴(坐标轴)序号,k-d树现在常用的有几种不同计算split的策
略:计算当前数据集上所有维度的方差,取方差最大的维度的标号作为split,对深度为j的节点,选
择l=j(mod k)+1作为split。
2.1 构造KD树
输入:k维空间数据集,其中
输出:kd树
构造根节点,根节点对应于包含T的k维空间的超矩形区域:
split策略,计算split所对应的维度(坐标轴)x(1),以所有实例的x(1)坐标内的中位数作为切
分点,将根节点对应的超矩形区域垂直切分成两个子区域,由根节点生成深度为1的左右两个节
点,左子节点对应坐标x(1)小于切分点的子区域,右子节点对应坐标x(1)大于切分点的子区
域,将落在切分超平面上的实例点保存于根节点。
构造其它节点,递归:
对深度为j的节点,split策略,计算split所对应的维度(坐标轴)x(1),以所有实例的x(1)坐标
内的中位数作为切分点,将该节点对应的超矩形区域垂直切分成两个子区域,由该节点生成深度为
j+1的左右两个节点,左子节点对应坐标x(1)小于切分点的子区域,右子节点对应坐标x(1)大
于切分点的子区域,将落在切分超平面上的实例点保存于该节点,直到两个子区域没有实例时停
止,从而形成k-d树的区域划分。
2.2 k-d树的最近邻搜索
输入:已构造的kd树;目标点x
输出:x的最近邻
在kd树中找出包含目标点x的叶节点(DFS):从根节点开始,递归地向下访问kd树。若目标点x当
前维的坐标小于切分点的坐标,则移动到左子节点,否则移动到右子节点,直到子节点为叶节点为
止,在stack中顺序存储已经访问的节点。以此叶节点为“当前最近点”,然后通过stack回溯:如果
该节点保存的实例点比“当前最近点”距离目标更近,则以该实例点为“当前最近点,检查该节点的父
节点的另一个子节点对应的区域是否与以目标点为球心,以目标点与“当前最近点”间的距离为半径
的超球体相交,如果相交,则在另一个子节点对应的区域存在距离目标点更近的点,到父节点的另
外一侧,用同样的DFS搜索法,开始检查最近邻节点,如果如果不相交,则继续往上回溯,而父节
点的另一侧子节点都被淘汰,不再考虑的范围中。当搜索回到root节点时,搜索完成,得到最近邻
节点。
回溯过程实际上是一个二叉树的中序遍历,如果实例点是随机分布的,k-d树搜索平均计算复杂度
是O(logN),N为实例总数,当维数较大时,直接利用k-d树快速检索的性能急剧下降。假设数据
集的维数为k,一般来说要求数据的规模N满足条件:N远大于2的k次方,才能达到高效的搜索。k
近邻的k和k-d树的k是不一样的。
2.3 基于距离加权的K近邻算法
对k近邻算法的一个显而易见的改进是对k个近邻的贡献加权,根据它们相对查询点x的距离,将较
大的权值赋给较近的近邻:
用代替
其中
k近邻算法及其所有变体都只考虑k个近邻以分类查询点;如果分类一个新的查询实例时考虑所有
的训练样例,我们称此为全局(global)法。如果仅考虑最靠近的训练样例,我们称此为局部
(local)法。按距离加权的k-近邻算法是一种非常有效的归纳推理方法。它对训练数据中的噪声有
很好的鲁棒性,而且当给定足够大的训练集合时它也非常有效。注意通过取k个近邻的加权平均,
可以消除孤立的噪声样例的影响。
2.4 K近邻算法存在的问题
问题一:近邻间的距离会被大量的不相关属性所支配。
应用k近邻算法的一个实践问题是,实例间的距离是根据实例的所有属性(也就是包含实例的欧氏
空间的所有坐标轴)计算的
解决方法:当计算两个实例间的距离时对每个属性加权。
这相当于按比例缩放欧氏空间中的坐标轴,缩短对应于不太相关属性的坐标轴,拉长对应于更相关
的属性的坐标轴。每个坐标轴应伸展的数量可以通过交叉验证的方法自动决定。
问题二:k近邻算法必须保存全部数据集,如果训练数据集的很大,必须使用大量的存储空间。此
外,由于必须对数据集中的每个数据计算距离值,实际使用时可能非常耗时
问题三:在训练数据集中要求的观测值的数目,随着维数k的增长以指数方式增长。这是因为和最
近邻的期望距离随着维数k的增多而急剧上升,除非训练数据集的大小随着k以指数方式增长。
解决方法:当计算两个实例间的距离时对每个属性加权。
通过降维技术来减少维数,如主成分分析,因子分析,变量选择(因子选择)从而减少计算距离的
时间;
解决方法:当计算两个实例间的距离时对每个属性加权。
用复杂的数据结构,如搜索树去加速最近邻的确定。这个方法经常通过设定“几乎是最近邻”的目标
去提高搜索速度.