本文是一篇介绍K近邻数据挖掘算法的文章,而所谓数据挖掘,就是讨论如何在数据中寻找模式的一门学科。算法
其实人类的科学技术发展的历史,就一直伴随着数据挖掘,人们一直在试图中数据中寻找模式,数据库
所谓数据挖掘,本质上就是经过分析存在于数据库里的数据来解决问题,数据挖掘被定义为找出数据中的模式的过程,这个过程必须是自动的或半自动的。数据结构
接下来的问题就是,如何表示数据模式?app
有价值的数据模式可以让咱们对新数据作出非凡的预测,表示一个数据模式有两种极端的方法:机器学习
两种方法可能均可以作出好的预测,它们的区别在于被挖掘出的模式可否以结构的形式清晰地表现,这个结构是否经得起分析,理由是否充分,可否用来造成将来的决策。ide
若是模式可以以显而易见的方法得到决策结构,就称为结构模式(structural pattern),换句话说,结构模式可以帮助解释有关数据的一些现象,具有可解释性。函数
更进一步地,机器学习从数据中挖掘结构模式的过程,称为知识表达,机器学习所能发现的模式有许多不一样的表达方式,每一种方式就是一种推断数据输出结构的技术,包括:工具
了解了前因后果的知识脉络以外,咱们将视野缩小到”基于实例的机器学习“这个领域内。学习
在基于实例的学习中,训练样本被一字不差地保存,而且使用一个距离函数来断定训练集中的哪一个实例与一个未知的测试实例最靠近。一旦找到最靠近的训练实例,那么最靠近实例所属的类就被预测为测试实例的类。测试
基于实例的算法,有时也称为基于记忆的学习,它不是明确概括几率分布或者分界面,而是将新的问题例子与训练过程当中见过的例子进行对比,这些见过的例子就在存储器中。
Relevant Link:
《数据挖掘 实用机器学习工具与技术》Ian H.Witten Eibe Frank,Mark A.Hall
咱们先来看下面这张图,
假设咱们如今的目标是寻找图中离绿色点最近的实例。这个问题的答案彷佛是显而易见的,很显然是右下方向的红色三角。
可是咱们只要对题目稍加改造,例如将空间维数从2维扩展到100维,图上的点密度增长10倍,这个时候,答案还依然明显吗?显然不是了!
最直观的想法是,咱们须要建一张表(table),将图中全部的数据点的坐标都保存起来,例如:
点 | x1 | ...... | xn |
A | 1 | ...... | 2 |
.. | |||
N | 5 | ...... | 3 |
这样,每输入一个新的点时,咱们就遍历一遍整张表,根据必定的距离函数(例如欧氏距离)找出距离最近的1个或k个实例。
这个场景在现实中是很是常见的需求,例如:
尽管上面描述的查表法很是简单且有效,可是缺点是速度很是慢。这个过程与训练实例的数量成线性关系,换句话说,就是一个单独的预测所花费的时间与训练实例的数量成比例关系。处理整个数据集所花费的时间与训练集实例数量O(train)和测试集实例数量O(test)的乘积成正比。
如何解决这个关键矛盾呢?学者们从数据结构优化上入手,提出了一系列的高效数据结构与搜索算法,它们合称为K近邻算法,K近邻算法要解决的最核心问题就是如何有效寻找到最近邻的实例集,支撑这种搜索的结构就是一种知识表达。咱们接下来来讨论它。
K近邻法(k-nearest neighbor KNN)是一种数据驱动(基于实例的算法(Instance-based Algorithms))的分类与回归方法。它属于一种判别模型。
在多分类问题中的k近邻法,k近邻法的输入为实例的特征向量,对应于特征空间的点,输出为实例的类别。
k近邻法假设给定一个训练数据集,其中的实例类别已定,分类时,对新的实例,根据其k个最近邻的训练实例的类别,经过多数表决等方式进行预测。所以,k近邻法不具备显示的学习过程(或者说是一种延迟学习),k近邻法实际上利用训练数据集对特征向量空间进行划分,并做为其分类的“模型”。
KNN算法不只能够用于分类,还能够用于回归。经过找出一个样本的k个最近邻居,将这些邻居的属性的平均值赋给该样本,就能够获得该样本的属性。
更有用的方法是将不一样距离的邻居对该样本产生的影响给予不一样的权值(weight),如权值与距离成正比。
输入训练数据集,其中
为实例的特征向量,
为实例的类别。
根据给定的距离度量,在训练集中找出与 x 最邻近的 K(须要人工设定调参) 个点,在由这 K 个点组成的邻域中根据分类决策规则决定 x 的类别 y
K近邻法的特殊状况是k=1的情形,称为最近邻算法,即对于输入的实例点(特征向量)x,最近邻法将训练数据集中与x最邻近的类做为x的类。
Y = P(y | x):这里几率函数P指某种最小化距离断定公式
能够看到,K近邻法没有显示的学习过程,做为判别模型的一种,k近邻法的判别函数的具体形式也不是很明显。
K近邻法使用的模型实际上对应于特征空间的划分,某种意义上来讲,k近邻的模型就是样本特征空间自己。
在k近邻法中,当下列基本要素:
肯定后,对于任何一个新的输入实例,它所属的类惟一地肯定。这至关于根据上述基本要素将特征空间划分为一些子空间,肯定子空间里的每一个点所属的类。
特征空间中,对每一个训练实例点x1,距离该点比其余点更近的全部点组成一个区域,叫做单元(cell)。每一个训练实例点拥有一个单元,全部训练实例点的单元构成对特征空间的一个划分:
K近邻很好地体现了判别式模型的思想,k近邻不生成几率分布函数,它只是经过三个基本要素尽量地“捕捉”训练样本中的几率密度特征。之因此输入样本会被分到不一样的类别,其本质就在于在训练样本中存在不均匀的几率密度分布,即某一个区域某一个类别密度占比比其余的类多。
下面咱们来具体谈谈K近邻模型的几个基本要素。
K值的选择会对K近邻法的结果产生重大影响。
近似偏差和估计偏差的核心区别在因而假设临近点的噪音扰动比较多仍是远点的噪音扰动比较多。
在实际应用中,K值通常选取一个比较小的数值,即咱们基本上认为近邻点的相关性是比较大的,而原点的相关性比较小
在实际项目中,K值的选择和样本中的几率密度分布有关,并无一个定式的理论告诉我么该选什么样的K值,好在的是这个K值的搜索空间并非很大,一般咱们能够采起一个for循环交叉验证来搜索全部可能的K值,经过重复进行屡次实验,每次随机选取不一样的train set和validate set,查看KNN模型对train set和validate set的拟合和泛化能力来选择一个最好的K值。
理论上分析:
理论上说,当 k 和实例的数量 n 都变成无穷大,使得 k/n -> 0 时,那么在数据集上产生的偏差几率将达到理论上的最小值。
特征空间中两个实例点的距离是两个实例点类似程度的一种数字化度量。
K近邻模型的特征空间通常是n维实数向量空间,计算两个向量之间的距离有不少种方法,注意这不是KNN独有的算法,向量间距离模型是数学中的基础概念:
设特征空间是n维实数向量空间
:
,
的Lp距离定义为:
下图给出了二维空间中p取不一样值时,与原点的Lp距离为1(Lp = 1)的点的集合图形
这张图很好地说明了取不一样的距离策略对于KNN对于紧邻点的搜索范围是不一样的,进而影响随后的判别分类结果
举一个例子说明由不一样的距离度量所肯定的最近邻点是不一样的。已知二维空间的3个点,咱们来对比一下在p取不一样的值时,Lp距离下X1的最近邻点
P值 | 和X2距离 | 和X3距离 |
1 | 4 | 6 |
2 | 4 | 4.24 |
3 | 4 | 3.78 |
4 | 4 | 3.57 |
能够看到,p = 1/2时,X2是X1的最近邻点;P >= 3,X3是X1的最近邻点。
近邻法中的分类决策规则每每是多数表决,即由输入实例的k个临近的训练实例中的多数的label决定输入实例的类。当K=1时算法退化为最近邻搜索。
多数表决规则(majority voting rule)本质也是最优化技术,它符合极大似然估计原则。
咱们假设分类的损失函数为0-1损失函数为:
那么误分类的几率是:
对给定的实例,其最近邻的 k 个训练实例点构成集合
,若是涵盖
的区域的类别是Cj,那么误分类率是:
要使误分类率最小,即经验风险最小,就要使下式最大:
即模型对训练样本的预测准确度(拟合程度)最大。因此多数表决规则等价于经验风险最小化。
KNN的学习策略很简单,就是在训练集中寻找最近邻的K个实例点,并进行voting,选择最多类别的那个,即经验风险最小化。这一样体现了极大似然估计的核心思想。
KNN的策略很是直观易理解,算法要解决是具体的工程化问题,即如何在高维空间中选出 k 个近邻点,当维度很高且样本量很大的时候,若是不采起一些高效的算法而直接暴力搜索的话是很是耗时的。
解决该问题的思路就是利用特殊构造的存储数据结构以及特殊的搜索方法来完成,这也是本文的重点讨论部分。
最早被提出的一种数据结构是树结构,经过应用分治思想,树结构将原始的O(N)复杂度下降为O(logN)复杂度,咱们接下来来讨论它。
KD树是一种对K维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。kd树是一个二叉树,一棵KD树就是一个超平面,表示对K维空间的一个划分(partition)。构造KD树至关于不断地用垂直于坐标轴的超平面将K维空间切分,构成一系列的K维超矩形区域。KD树的每一个结点对应于一K维超矩形区域。
这里K是数据集属性的数量。
下图展现了一个k=2的小例子:
树不必定会发展到相同的深度,训练集中的每个实例与树中的一个结点相对应,最多一半的结点是叶子节点。
输入:k维空间数据集(样本数量是N),每一个样本的维度是k,
用一个例子来讲明kd树构造过程 ,给定一个二维空间的数据集:
与其余大部分机器学习方法相比,基于实例学习的一个优点是新的实例能够在任什么时候候加入到训练集里。
新的数据来临时,须要用新的数据点判断其属于哪一个叶子节点,而且找出叶子节点的超矩形。若是超矩形为空,就将新数据点放置在那里,不然分裂超矩形,分裂在最长的边上进行,以保持方形。
这种简单的探索式方法并不能保证在加入一系列点后,树依然会维持平衡,也不能保证为搜索最近邻塑造良好的超矩形。有时候从头开始重建数不失为一个良策。例如,当树的深度达到最合适的深度值的两倍时。
完成了KD树建树后,接下来讨论如何利用KD树进行高效K近邻搜索:
输入:根据train set构造的kd树;目标点x
输出:x的最近邻
用下图来讲明kd树的搜索过程,根节点为A,子节点是B,C,D,E,F,G;目标实例点S,求S的最近邻
咱们已经看到,KD树是可用于有效寻找最近邻的良好数据结构,可是,并不完美。当面对不均匀数据的数据集时,便面临一些基本冲突和挑战:
这里所谓的平衡结构,就是指树的两边分叉要尽可能分布平均,这样能够最大程度地发挥O(logN)的优化效果,可是若是数据点的分布很是不均衡,采用中值的方法也许会在同一个方向上产多屡次后续分裂,从而产生瘦长型的超矩形。一个更好的解决方法是采用平均值做为分裂点而不是中位值。这样产生的KD树会更趋向于方形。
可是均值分裂点技术依然没法彻底规避KD原生的问题,为此,学界提出了超球分界面代替超矩形分界面的改进方法。
KD tree的思想很是精妙,可是也存在一些问题, 形并非用到这里最好的方式。偏斜的数据集会形成咱们想要保持树的平衡与保持区域的正方形特性的冲突。另外,矩形甚至是正方形并非用在这里最完美的形状,因为它的角。为了解决这些问题,引入了ball tree,即便用超球面而不是超矩形划分区域
Ball Tree就是一个K维超球面来覆盖训练样本点。
上图(a)显示了一个2维平面包含16个观测实例的图,图(b)是其对应的ball tree,其中结点中的数字表示包含的观测点数。
树中的每一个结点对应一个圆,结点的数字表示该区域保含的观测点数,但不必定就是图中该区域囊括的点数,由于有重叠的状况,而且一个观测点只能属于一个区域。实际的ball tree的结点保存圆心和半径。叶子结点保存它包含的观测点。
Ball tree的建树过程和KD tree大致上一致,区别在于ball tree每次的切分点都是当前超球体的圆心。
使用Ball tree时:
Relevant Link:
http://blog.csdn.net/pipisorry/article/details/53156836