机器学习实战:K-近邻算法(一)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lom9357bye/article/details/73007711

工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最邻近)的分类标签。一般来说,我们只选择样本数据集中前k个最相似数据,这就是k-临近算法的出处,通常k是不大于20的整数。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。


算法流程:

(1)收集数据

(2)准备数据:距离计算所需要的数值,最好是结构化的数据格式。

(3)分析数据

(4)训练算法:此步骤不适用于k-临近算法

(5)测试算法:计算错误率

(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-临近算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续处理。


来看一个例子:


假如有一组数据已经做好了分类,(1,1.1)和(1,1)属于A类,(0,0)(0,0.1)属于B类

现在有一点(1,0),它应该属于哪一类?

思路:

(1)求出(1,0)到四个点之间的距离

(2)找出距离最近的k个点

(3)找出k个点中分类出现次数最多的那个


用到的python知识:


 
 
  1. # -*- coding:utf-8 -*-
  2. from numpy import *
  3. import operator
  4. #1.shape函数
  5. group=array([[ 1.0, 1.1],[ 1.0, 1.0],[ 0, 0],[ 0, 0.1]])
  6. print(group.shape[ 0]) #输出4,数组行数
  7. print(group.shape[ 1]) #输出2,数组列数
  8. print(group)
  9. #2.tile函数
  10. test=[ 1, 0]
  11. print(tile(test,( 4, 1)))
  12. #输出
  13. #[[1 0]
  14. # [1 0]
  15. # [1 0]
  16. # [1 0]]
  17. #3.sum函数
  18. arr=array([[ 1, 2, 3],[ 4, 5, 6]])
  19. print(arr.sum(axis= 1)) #将矩阵的每一行相加
  20. #输出[ 6 15]
  21. print(arr.sum(axis= 0)) #将矩阵的每一列相加
  22. #输出[5 7 9]
  23. #4.argsort函数:返回的是数组值从小到大的索引值
  24. array1=([ 1, 3, 2, 7])
  25. print(argsort(array1))
  26. #输出[0 2 1 3]
  27. #5.sorted
  28. #sorted(iterable, cmp=None, key=None, reverse=False)
  29. #iterable:迭代对象,要排序的对象
  30. #cmp:比较函数
  31. #key:指定取待排序元素的哪一项进行排序,operator.itemgetter(1)获取对象的第1个域的值,此处是按value值排序
  32. #reverse:是否反转,表示是否从高到低排序
  33. dict={ 'A': 10, 'B': 5, 'C': 20, 'D': 15}
  34. print(sorted(dict.items(),key=operator.itemgetter( 1)))
  35. #结果:[('B', 5), ('A', 10), ('D', 15), ('C', 20)]
  36. #reverse=true结果:[('C', 20), ('D', 15), ('A', 10), ('B', 5)]


python3代码:


 
 
  1. # -*- coding:utf-8 -*-
  2. from numpy import *
  3. import operator
  4. def createDataSet():
  5. group=array([[ 1.0, 1.1],[ 1.0, 1.0],[ 0, 0],[ 0, 0.1]]) #数据集
  6. labels=[ 'A', 'A', 'B', 'B'] #数据对应的分类
  7. return group,labels
  8. #intX:分类的输入向量
  9. #dataSet:训练样本
  10. #labels:标签向量
  11. #k:选择最近邻居的数目
  12. def classify0(intX,dataSet,labels,k):
  13. dataSetSize=dataSet.shape[ 0] #数组行数
  14. #距离计算
  15. diffMat=tile(intX,(dataSetSize, 1))-dataSet #将输入向量转为行数为dataSetSize的二维数组,并计算与训练样本的差
  16. sqDiffMat=diffMat** 2 #求数组的2次方
  17. sqDistances=sqDiffMat.sum(axis= 1) #将矩阵的每一行相加
  18. distances=sqDistances** 0.5 #求数组的0.5次幂,也就是求平方根
  19. #选择距离最小的k个点
  20. sortedDistIndicies=distances.argsort() #根据距离将数组的下标排序
  21. classCount={}
  22. #求出前距离最近的前K个点中出现最多的分类
  23. for i in range(k):
  24. voteIlabel=labels[sortedDistIndicies[i]] #遍历前k个点,获取每个点所属分类
  25. classCount[voteIlabel]=classCount.get(voteIlabel, 0)+ 1 #将类别作为key,出现的次数作为value,计算每个类别出现的次数
  26. #排序
  27. sortedClassCount=sorted(classCount.items(),key=operator.itemgetter( 1),reverse= True)
  28. return sortedClassCount[ 0][ 0]
  29. #测试
  30. group,labels=createDataSet()
  31. result=classify0([ 1, 0],group,labels, 3)
  32. print(result)



距离计算:

(1)求两个矩阵的差

输入的数据为[1,0]:

训练样本集为:

[[1.0,1.1],

 [1.0,1.0],

 [0, 0],

 [0,0.1]],是一个二维数组,也可以看作为一个行为4列为2的矩阵,为了两个矩阵可以相减,首先需要将输入向量[1,0]转换为一个行数为4的二维数组

经过tile(intX,(dataSetSize,1))后输入向量变为


 
 
  1. [[ 1 0],
  2. [ 1 0],
  3. [ 1 0],
  4. [ 1 0]]

然后减去训练样本集,求出两个矩阵的差,差值为


 
 
  1. [[ 0. -1.1]
  2. [ 0. -1. ]
  3. [ 1. 0. ]
  4. [ 1. -0.1]]


(2)使用欧氏距离公式,计算两个向量点之间的距离

首先求差值的2次方,结果为:


 
 
  1. [[ 0. 1.21]
  2. [ 0. 1. ]
  3. [ 1. 0. ]
  4. [ 1. 0.01]]

然后将矩阵的每一行相加得到:

[ 1.21  1.    1.    1.01]
 
 

然后开根

[ 1.1   1.    1.    1.00498756]
 
 


根据距离最近点排序


 
 
  1. 值 : 1 1 1.00498756 1.1
  2. 下标: 1 2 3 0
得到:

[1 2 3 0]


(3)选择距离最小的k个点,此处k=3,也就是前3个点

从上一步得到排序后的下标,取前三个值,然后从lables标签中取下标为1  2  3 的值,分别是A  B  B

求出出现频率最高的类别,B出现两次,A出现1次,因此推测[1,0]的分类结果是B


来自:机器学习实战


python知识参考:

http://blog.csdn.net/sunny2038/article/details/9002531

http://www.cnblogs.com/chamie/p/4847332.html

http://blog.csdn.net/iboxty/article/details/44975575

http://www.cnblogs.com/100thMountain/p/4719503.html

http://www.cnblogs.com/kellyseeme/p/5525052.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值