python实现knn算法

来源:互联网 发布:java数据传输加密技术 编辑:程序博客网 时间:2024/05/03 18:28

刚接触机器学习不久,在看《机器学习实战》,今天将书上的knn算法敲了一遍,上写的很精炼,刚接触python不久的,还没接触过numpy,所以写一个读书笔记。


knn属于十大数据挖掘算法中算是比较简单的了。不过作用不小,他是一个监督学习分类器类别的算法,所以需要数据的练习。

  • 优点:精度高,对异常数值不敏感,无数据输入假定。
  • 缺点:计算复杂度高,空间复杂度高
  • 适用数据范围:数值型和标称型

什么是knn算法:

简单的说,K-近邻算法就是采用测量不同特征值之间的距离方法来进行分类。它的工作原理是:存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系,输入没有标签的新数据之后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出样本集中特征最相似数据的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是K-近邻算法名称的由来。


使用Python导入数据
首先创建名为KNN.py的python模块,里面的代码是:

#!/usr/bin/python# -*- coding: utf-8 -*-#__author__ = 'Mr Cai'from numpy import  *import  operatordef creatrDataSet():    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])    labels = ['A','A','B','B']    return  group,labels

运行程序
创建一个名为run.py的python模块,我们将要用到KNN.py模块中的函数,所以在run.py中用import KNN导入模块。

  • 实现K-近邻算法的一般流程:

    (1)计算已知类别数据集中的点与当前点之间的距离
    (2)按照距离递增次序排序
    (3)选取与当前点距离最小的k个点
    (4)确定前k个点所在类别的出现频率
    (5)返回前k个点中出现频率最高的类别作为当前点的预测分类


**代码实现run.py**
#!/usr/bin/python# -*- coding: utf-8 -*-#__author__ = 'Mr Cai'from numpy import *import operatorimport KNN#获取标准group, labels = KNN.creatrDataSet()def classify(inX, dataSet, labels, k):    #得到数组的行数。即知道有几个训练数据    dataSetSize = dataSet.shape[0]    #tile:numpy中的函数。tile将原来的一个数组,扩充成了4个一样的数组。diffMat得到了目标与训练数值之间的差值。矩阵之差    diffMat = tile(inX, (dataSetSize,1)) - dataSet    #tile(x,(y,z))   将x复制z遍,复制y行    #矩阵的各个元素分别平方    sqDiffMat = diffMat**2    #对应列相乘,即得到了每一个距离的平方    sqDistances = sqDiffMat.sum(axis=1)   #axis = 0,列相加   axis = 1,行相加    #开方,得到距离。    distances = sqDistances**0.5    #升序排列    sortedDistances = distances.argsort()  #从小到大返回排序的索引    #选择距离最小的k个点。    classCount = {}    for i in range(k):        numOflabel = labels[sortedDistances[i]]        classCount[numOflabel] = classCount.get(numOflabel,0) + 1 #统计    #排序    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1),reverse=True)    return sortedClassCount[0][0]if __name__ == '__main__':    print classify([0,0],group,labels,3)

代码中的知识点总结:

  • 字典的get()函数
    字典的get()函数接收两个参数。第一个参数是所要查询的key,第二个则是如果字典中不存在key返回的值。
    例:
    d = {‘key’:’value’}
    print d.get(‘key’, ‘not found’)
    也就是完成了下面的功能:
if d.has_key('key'):      print d['key']   else:     print 'not found'   
  • 字典的item(),与itemgetter()的区别
    python字典的items方法作用:是可以将字典中的所有项,以列表方式返回。如果对字典项的概念不理解,可以查看Python映射类型字典基础知识一文。因为字典是无序的,所以用items方法返回字典的所有项,也是没有顺序的。

    python字典的iteritems方法作用:与items方法相比作用大致相同,只是它的返回值不是列表,而是一个迭代器。
例:>>>x = {'title':'python web site','url':'www.iplaypython.com'}>>>x.items()>>>[('url', 'www.iplaypython.com'), ('title', 'python web site')]
例:>>> f = x.iteritems()>>> f<dictionary-itemiterator object at 0xb74d5e3c>>>> type(f)<type 'dictionary-itemiterator'>    #字典项的迭代器>>> list(f)[('url', 'www.iplaypython.com'), ('title', 'python web site')]

  • python中的sorted()函数详解
    sorted函数:
    Python内置的排序函数sorted可以对list或者iterator进行排序,官网文档见:http://docs.python.org/2/library/functions.html?highlight=sorted#sorted,该函数原型为:
    sorted(iterable[, cmp[, key[, reverse]]])
    参数解释:
    (1)iterable指定要排序的list或者iterable,不用多说;
    (2)cmp为函数,指定排序时进行比较的函数,可以指定一个函数或者lambda函数,如:
    students为类对象的list,没个成员有三个域,用sorted进行比较时可以自己定cmp函数,例如这里要通过比较第三个数据成员来排序,代码可以这样写:
    students = [(‘john’, ‘A’, 15), (‘jane’, ‘B’, 12), (‘dave’, ‘B’, 10)]
    sorted(students, key=lambda student : student[2])
    (3)key为函数,指定取待排序元素的哪一项进行排序,函数用上面的例子来说明,代码如下:
    sorted(students, key=lambda student : student[2])
    key指定的lambda函数功能是去元素student的第三个域(即:student[2]),因此sorted排序时,会以students所有元素的第三个域来进行排序。
    有了上面的operator.itemgetter函数,也可以用该函数来实现,例如要通过student的第三个域排序,可以这么写:
    sorted(students, key=operator.itemgetter(2))
    sorted函数也可以进行多级排序,例如要根据第二个域和第三个域进行排序,可以这么写:
    sorted(students, key=operator.itemgetter(1,2))
    即先根据第二个域排序,再根据第三个域排序。
    (4)reverse参数就不用多说了,是一个bool变量,表示升序还是降序排列,默认为false(升序排列),定义为True时将按降序排列。

  • operator.itemgetter(1)的解释
    因为sorted()函数中的key值需要接收一个函数,这边的意思是按照字典中的第二个参数排序。
    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函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。

0 0
原创粉丝点击