2,K近邻原理:
kNN原理很简单,通过计算待分类样本与已知类别样本之间的距离,找到距离待分类最近的K个已知类别的样本,然后根据少数“服从多数”的判决原则,统计K个样本中各类样本出现的次数,出现次数最多的样本即为待分类样本的类别。
图1 K近邻分类
上图中要确定测试样本绿色属于蓝色还是红色。显然,当K=3时,将以1:2的投票结果分类于红色;而K=5时,将以3:2的投票结果分类于蓝色。
我们不禁会反问,你这样的分类准确吗?为什么不同的K值会得到不同的分类结果?你有什么理由说待分类的样本与K个样本中出现次数最多样本是同一类?
对于这三个问题,我说下我的理解,
我们都听说过这句话“同一类样本之间差异较小,不同类之间差异较大”,这差异通过什么来体现呢?在KNN算法中,样本特征之间差异,主要通过特征之间的“距离”来体现,距离体现了他们之间的相似性,在多维空间中,不同类的样本散布于多维空间之中,同类样本总是聚集在一起,本质是讲就是他们的特征存在相似性,不同类样本之间是彼此分离的。
图2 KNN概念图
因此通过计算待分类样本与已分类样本之间的距离来进行分类是可靠的。对于分类决策主要是根据“少数服从多数” 本质上讲就是哪类样本与待分类样本最相似,就分给哪类。(
对于这种判决准则,不一定适用于所有情况,后面会有讨论
)
关于为什么K取不同的值,分类结果可能不一致,这主要体现KNN在类边界上,分类结果会随K的取值不同,分类结果不稳定,但对于非类边界分类准确率还是很高的。
K值选取:
关于K的取值是K-最近邻算法中的一大难题,没有特定的经验公式来告诉我们K应该取多大?K值如果选取的太小,模型太复杂,K值选取的太大的话,又会导致分类模糊。K的取值与实际背景有关,与你数据分析的目标……那么K值到底怎么选取呢?既然K值这么麻烦有没有一些常规选取K值的方法,答案是肯定的。
经验规则:k一般低于训练样本数的平方根。
常用方法有Cross Validation,贝叶斯准则, bootstrap……
大家如果想了解更多关于如何用Cross Validation选择K值可以参照一下两篇博客:
(1)KNN算法实现及其交叉验证:
http://www.jianshu.com/p/48d391dab189
(2)机器学习-CrossValidation交叉验证Python实现:http://blog.csdn.net/dream_angel_z/article/details/47110077
上面提到了类与类之间的相似性通过距离来体现,下面我们看下有哪些距离:
3,距离定义:
(
1
)欧式距离
欧氏距离是最常见的距离度量,衡量的是多维空间中各个点之间的绝对距离。
因为计算是基于各维度特征的绝对数值,所以欧氏度量需要保证各维度指标在相同的刻度级别,比如对身高(cm)和体重(kg)两个单位不同的指标使用欧式距离可能使结果失效。
(
2
)
马氏距离:马氏距离能够缓解由于属性的线性组合带来的距离失真,是数据的协方差矩阵。
(
3
)曼哈顿距离:
曼哈顿距离来源于城市区块距离,是将多个维度上的距离进行求和后的结果。
(
4
)切比雪夫距离
切比雪夫距离起源于国际象棋中国王的走法,我们知道国际象棋国王每次只能往周围的8格中走一步,那么如果要从棋盘中A格(x1, y1)走到B格(x2, y2)最少需要走几步?扩展到多维空间,其实切比雪夫距离就是当p趋向于无穷大时的明氏距离。
(
5
)闵氏距离:
闵氏距离是欧氏距离的推广,是对多个距离度量公式的概括性的表述。r取值为2式为曼哈顿距离 ;r取值为1时为欧式距离。
(
6
)平均距离
(
7
)
弦距离:
(
8
)测地距离
关于距离选择:
高维度对距离衡量的影响:众所周知当变量数越多,欧式距离的区分能力就越差。
变量值域对距离的影响:值域越大的变量常常会在距离计算中占据主导作用,因此应先对变量进行标准化。
比较常用的是选用欧式距离。可是这个距离真的具有普适性吗?《模式分类》中指出欧式距离对平移是敏感的,这点严重影响了判定的结果。在此必须选用一个对已知的变换(比如平移、旋转、尺度变换等)不敏感的距离度量。书中提出了采用切空间距离(tangent distance)来替代传统的欧氏距离。
(引自:
http://blog.csdn.net/liqiming100/article/details/77851226
【kNN(K-Nearest Neighbor)最邻近规则分类中的三大问题(K值选取、距离度量、分类决策规则)】)
最近邻法介绍:
切空间距离定义:
(引自:杨剑. 基于局部切距离的近邻法[A]. 中国自动化学会智能自动化专业委员会、中国科学院自动化研究所.2005年中国智能自动化会议论文集[C].中国自动化学会智能自动化专业委员会、中国科学院自动化研究所:,2005:6.)
4,算法实现步骤:
简单来说,KNN可以看成:有那么一堆你已经知道分类的数据,然后当一个新数据进入的时候,就开始跟训练数据里的每个点求距离,然后挑离这个训练数据最近的K个点看看这几个点属于什么类型,然后用少数服从多数的原则,给新数据归类。
具体步骤如下
step.1---计算未知样本和每个训练样本的距离dist ;
step.2---对dist从小到大排序;
step.3---取出距离从小到大的K个训练样本,作为K-最近邻样本;
step.4---统计K-最近邻样本中每个类标号出现的次数
step.5---选择出现频率最大的类标号作为未知样本的类标号,
5,算法复杂度分析:
KNN算法简单有效,但没有优化的暴力法那样效率容易达到瓶颈。如样本个数为N,特征维度为D的时候,该算法时间复杂度呈O(DN)增长。所以通常KNN的实现会把训练数据构建成K-D Tree(K-dimensional tree),构建过程很快,甚至不用计算D维欧氏距离,而搜索速度高达O(D*log(N))。不过当D维度过高,会产生所谓的”维度灾难“,最终效率会降低到与暴力法一样。因此通常D>20以后,最好使用更高效率的Ball-Tree,其时间复杂度为O(D*log(N))。人们经过长期的实践发现KNN算法虽然简单,但能处理大规模的数据分类,尤其适用于样本分类边界不规则的情况。最重要的是该算法是很多高级机器学习算法的基础。
(KNeighbors Classifier可以设置3种算法:‘brute’,‘kd_tree’,‘ball_tree’。如果不知道用哪个好,设置‘auto’让KNeighborsClassifier自己根据输入去决定。)
(引用:http://blog.csdn.net/lsldd/article/details/41357931)
6,类别如何判定最合理?
投票法没有考虑近邻的距离的远近,距离更近的近邻也许更应该决定最终的分类,所以加权投票法更恰当一些。
7,KNN实现:
KNN----Python实现:
1. #coding:utf-8
3. from numpy import *
4. import operator
6. ##给出训练数据以及对应的类别
7. def createDataSet():
8. group = array([[1.0,2.0],[1.2,0.1],[0.1,1.4],[0.3,3.5]])
9. labels = ['A','A','B','B']
10. return group,labels
12. ###通过KNN进行分类
13. def classify(input,dataSe t,label,k):
14. dataSize = dataSet.shape[0]
15. ####计算欧式距离
16. diff = tile(input,(dataSize,1)) - dataSet
17. sqdiff = diff ** 2
18. squareDist = sum(sqdiff,axis = 1)###行向量分别相加,从而得到新的一个行向量
19. dist = squareDist ** 0.5
21. ##对距离进行排序
22. sortedDistIndex = argsort(dist)##argsort()根据元素的值从大到小对元素进行排序,返回下标
24. classCount={}
25. for i in range(k):
26. voteLabel = label[sortedDistIndex[i]]
27. ###对选取的K个样本所属的类别个数进行统计
28. classCount[voteLabel] = classCount.get(voteLabel,0) + 1
29. ###选取出现的类别次数最多的类别
30. maxCount = 0
31. for key,value in classCount.items():
32. if value > maxCount:
33. maxCount = value
34. classes = key
36. return classes
引自:https://www.cnblogs.com/ybjourney/p/4702562.html
8,计算量太大怎么办?
浓缩技术(condensing)
编辑技术(editing)
9,假设样本中,各类分布不均匀,如何处理:
(参考:训练样本分布不均的KNN分类改进算法_丁应逵)
10,K-最近邻优缺点分析:
相比于贝叶斯、决策树、支持向量积、KNN,神经网络等分类算法,KNN是一种基于实例的学习算法,它不同于贝叶斯、决策树等算法,KNN不需要训练,当有新的实例出现时,直接在训练数据集中找k个最近的实例,把这个新的实例分配给这k个训练实例中实例数最多类。KNN也成为懒惰学习,它不需要训练过程,在类标边界比较整齐的情况下分类的准确率很高。
下面先给大家介绍下KNN的优点:
简单,易于理解,易于实现,无需估计参数,无需训练;
适合对稀有事件进行分类;
特别适合于多分类问题(multi-modal,对象具有多个类别标签), kNN比SVM的表现要好。
懒惰算法,对测试样本分类时的计算量大,内存开销大,评分慢;
当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数;
可解释性较差,无法给出决策树那样的规则。
11,KNN案例分析:
KNN算法实现及其交叉验证:http://www.jianshu.com/p/48d391dab189
机器学习KNN实战: https://zhuanlan.zhihu.com/p/23191325
参考文献:
http://blog.csdn.net/zhaoshuaijiang/article/details/40509227
http://blog.csdn.net/lsldd/article/details/41357931
http://blog.csdn.net/xlm289348/article/details/8876353
http://zhaoshuaijiang.com/2014/10/18/knn_kmeans/
https://www.cnblogs.com/fengfenggirl/archive/2013/05/27/knn.html
https://www.cnblogs.com/sumuncle/p/5611705.html
http://blog.csdn.net/haluoluo211/article/details/78177510
https://www.cnblogs.com/ybjourney/p/4702562.html
模型中各种距离度量的表示 :http://www.jianshu.com/p/607c64556a08
KNN算法实现及其交叉验证:http://www.jianshu.com/p/48d391dab189