机器学习实战(1)-KNN(K-近邻算法)

来源:互联网 发布:nginx 添加第三方模块 编辑:程序博客网 时间:2024/05/18 01:54

KNN(K-近邻算法):算法本身是一个有监督学习的算法,故训练数据是有标签的,算法的原理是计算测试数据距离训练数据的距离(一般是欧式距离),将计算出的距离进行从小到大的排序,取前K个距离对应的训练数据,计算这K个数据中不同标签所占比例,比例最高的标签即为测试数据所属于的类。

Python实现:

from numpy import *import operatordef createDataSet():    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])    labels = ['A','A','B','B']    return group, labelsdef classify(x,dataSet,labels,k):    dataSetSize = dataSet.shape[0]    diffMat = tile(x,(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.iteritems(),key=operator.itemgetter(1),reverse=True)    #print classCount    return sortedClassCount[0][0]groups,labels=createDataSet()classes=classify([0.2,0.2],groups,labels,3)

关于上述代码中涉及的方法的解释:
1.shape返回数组的行列数,shape[0]即为数组的行数
2.tile(x,(dataSetSize,1)):
tile方法是将数组x,复制dataSetSize行,具体情况如下所示:

>>> import numpy>>> numpy.tile([0,0],5)#在列方向上重复[0,0]5次,默认行1次array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])>>> numpy.tile([0,0],(1,1))#在列方向上重复[0,0]1次,行1次array([[0, 0]])>>> numpy.tile([0,0],(2,1))#在列方向上重复[0,0]1次,行2次array([[0, 0],       [0, 0]])>>> numpy.tile([0,0],(3,1))array([[0, 0],       [0, 0],       [0, 0]])>>> numpy.tile([0,0],(1,3))#在列方向上重复[0,0]3次,行1次array([[0, 0, 0, 0, 0, 0]])>>> numpy.tile([0,0],(2,3))#在列方向上重复[0,0]3次,行2次array([[0, 0, 0, 0, 0, 0],       [0, 0, 0, 0, 0, 0]])

3.diffMat**2:将diffMat数组中的每个元素进行平方
4.sqDiffMat.sum(axis=1):将数组sqDiffMat按行相加
5. distances.argsort():进行排序,不过返回的不是排序后的数组,而是排序后数组中元素序号:
如:

>>> a=[1,3,6,2]>>> argsort(a)array([0, 3, 1, 2], dtype=int64)

6.sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True):
(1),第一个参数指定要排序的list或者iterable
(2),key为函数,指定取待排序元素的哪一项进行排序,在这里用的是operator.itemgetter(1)。

  • operator.itemgetter函数

            operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为一些序号(即需要获取的数据在对象中的序号),下面看例子。

    a = [1,2,3]
    b=operator.itemgetter(1) //定义函数b,获取对象的第1个域的值
    b(a) 2
    b=operator.itemgetter(1,0) //定义函数b,获取对象的第1个域和第0个的值
    b(a) (2, 1)

      要注意,operator.itemgetter函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。

    在这里用operator.itemgetter(1)就表示,根据第二个域进行排序。(因为要排序的数据在classCount中,这是一个字典,形式为:{‘A’: 1, ‘B’: 2},所以要根据第二个域进行排序,来获得测试数据是属于哪个类的)
    (3),reverse参数就不用多说了,是一个bool变量,表示升序还是降序排列,默认为false(升序排列),定义为True时将按降序排列。

1 0