机器学习-k近邻算法原理与实现

k近邻算法(k-nearest neighbor,k-NN)是一种基本分类与回归方法。

1.算法原理

K最近邻(k-Nearest Neighbor,KNN)分类算法可以说是最简单的机器学习算法了。它采用测量不同特征值之间的距离方法进行分类。它的思想很简单:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。

        比如上面这个图,我们有两类数据,分别是蓝色方块和红色三角形,他们分布在一个上图的二维中间中。那么假如我们有一个绿色圆圈这个数据,需要判断这个数据是属于蓝色方块这一类,还是与红色三角形同类。怎么做呢?我们先把离这个绿色圆圈最近的几个点找到,因为我们觉得离绿色圆圈最近的才对它的类别有判断的帮助。那到底要用多少个来判断呢?这个个数就是k了。如果k=3,就表示我们选择离绿色圆圈最近的3个点来判断,由于红色三角形所占比例为2/3,所以我们认为绿色圆是和红色三角形同类。如果k=5,由于蓝色四方形比例为3/5,因此绿色圆被赋予蓝色四方形类。从这里可以看到,k的值还是很重要的。
       KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。由于KNN方法主要靠周围有限的邻近的样本,而不是靠判别类域的方法来确定所属类别的,因此对于类域的交叉或重叠较多的待分样本集来说,KNN方法较其他方法更为适合。
       该算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。因此可以采用权值的方法(和该样本距离小的邻居权值大)来改进。该方法的另一个不足之处是计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点。目前常用的解决方法是事先对已知样本点进行剪辑,事先去除对分类作用不大的样本。该算法比较适用于样本容量比较大的类域的自动分类,而那些样本容量较小的类域采用这种算法比较容易产生误分[参考机器学习十大算法]。
       总的来说就是我们已经存在了一个带标签的数据库,然后输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似(最近邻)的分类标签。一般来说,只选择样本数据库中前k个最相似的数据。最后,选择k个最相似数据中出现次数最多的分类。其算法描述如下:
1)计算已知类别数据集中的点与当前点之间的距离;
2)按照距离递增次序排序;
3)选取与当前点距离最小的k个点;
4)确定前k个点所在类别的出现频率;
5)返回前k个点出现频率最高的类别作为当前点的预测分类。

2.算法实践python版

代码来自于机器学习实战第二章

from numpy import *
import operator

def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group,labels

def classify0(inX, dataSet, labels, k):
    dataSetSize = dataSet.shape[0]
    diffMat = tile(inX, (dataSetSize, 1)) - dataSet
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5
    sortedDistIndicies = distances.argsort()
    classCount={}
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return dataSetSize,diffMat,sqDiffMat,sqDistances,distances,sortedDistIndicies,classCount,sortedClassCount[0][0]

测试用例

>>> group,labels=kNN.createDataSet()
>>> a,b,c,d,e,f,g,h=kNN.classify0([0,0],group,labels,3)

最后结果

>>> a
4
>>> b
array([[-1. , -1.1],
       [-1. , -1. ],
       [ 0. ,  0. ],
       [ 0. , -0.1]])
>>> c
array([[ 1.  ,  1.21],
       [ 1.  ,  1.  ],
       [ 0.  ,  0.  ],
       [ 0.  ,  0.01]])
>>> d
array([ 2.212.  ,  0.  ,  0.01])
>>> e
array([ 1.486606871.414213560.        ,  0.1       ])
>>> f
array([2, 3, 1, 0])
>>> g
{'A': 1, 'B': 2}
>>> h
'B'

通过以上输出步骤,可以进一步理解分类算法工作原理
最终结果:’B’,也就是输入数据[0,0]与B类距离最接近

3.个人理解

Python基本函数说明:
- shape[] 返回矩阵长度,shape[0]返回矩阵第一维长度,这里也就是4
- tile函数

在此分类器中是构造重复构造[0,0]数组

>>> a=[0,0]
>>> a
[0, 0]
>>> diffmat=tile(a,(4,1))
>>> diffmat
array([[0, 0],
       [0, 0],
       [0, 0],
       [0, 0]])
  • **x 运算为diffMat的x次方
  • sum(axis=1) 为每一行向量相加
  • argsort()函数返回数组值从小到大的索引值
  • items 返回可遍历的(键-值)元组数组,所以这里返回的是
>>> y={'A': 1, 'B': 2}
>>> k=y.items()
>>> k
dict_items([('A', 1), ('B', 2)])
  • sorted函数
v=sorted(k, key=operator.itemgetter(1), reverse=True)
>>> v
[('B', 2), ('A', 1)]

理解:输入测试数据为[0,0],训练样本中就有相同数据,所以在距离上最近且为0。计算测试数据与不同样本之间的欧几里得距离,在根据定义的k=3来选取前三个距离最小值,当k=1时,sortedDistIndicies=2,labels[2]=’B’, 然后加1 ,k=2时还是B加1,k=3时,变成A加1,然后按从大到小排序,返回sortedClassCount第一维第一个数及最后结果’B’

你可能感兴趣的:(机器学习)