python实现knn算法

刚接触机器学习不久,在看《机器学习实战》,今天将书上的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  operator

def 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 operator
import 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函数获取的不是值,而是定义了一个函数,通过该函数作用到对象上才能获取值。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值