工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最邻近)的分类标签。一般来说,我们只选择样本数据集中前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知识:
# -*- coding:utf-8 -*-
from numpy import *
import operator
#1.shape函数
group=array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
print(group.shape[0])#输出4,数组行数
print(group.shape[1])#输出2,数组列数
print(group)
#2.tile函数
test=[1,0]
print(tile(test,(4,1)))
#输出
#[[1 0]
# [1 0]
# [1 0]
# [1 0]]
#3.sum函数
arr=array([[1,2,3],[4,5,6]])
print(arr.sum(axis=1))#将矩阵的每一行相加
#输出[ 6 15]
print(arr.sum(axis=0))#将矩阵的每一列相加
#输出[5 7 9]
#4.argsort函数:返回的是数组值从小到大的索引值
array1=([1,3,2,7])
print(argsort(array1))
#输出[0 2 1 3]
#5.sorted
#sorted(iterable, cmp=None, key=None, reverse=False)
#iterable:迭代对象,要排序的对象
#cmp:比较函数
#key:指定取待排序元素的哪一项进行排序,operator.itemgetter(1)获取对象的第1个域的值,此处是按value值排序
#reverse:是否反转,表示是否从高到低排序
dict={'A':10,'B':5,'C':20,'D':15}
print(sorted(dict.items(),key=operator.itemgetter(1)))
#结果:[('B', 5), ('A', 10), ('D', 15), ('C', 20)]
#reverse=true结果:[('C', 20), ('D', 15), ('A', 10), ('B', 5)]
python3代码:
# -*- coding:utf-8 -*-
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
#intX:分类的输入向量
#dataSet:训练样本
#labels:标签向量
#k:选择最近邻居的数目
def classify0(intX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]#数组行数
#距离计算
diffMat=tile(intX,(dataSetSize,1))-dataSet#将输入向量转为行数为dataSetSize的二维数组,并计算与训练样本的差
sqDiffMat=diffMat**2#求数组的2次方
sqDistances=sqDiffMat.sum(axis=1)#将矩阵的每一行相加
distances=sqDistances**0.5#求数组的0.5次幂,也就是求平方根
#选择距离最小的k个点
sortedDistIndicies=distances.argsort()#根据距离将数组的下标排序
classCount={}
#求出前距离最近的前K个点中出现最多的分类
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]#遍历前k个点,获取每个点所属分类
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1#将类别作为key,出现的次数作为value,计算每个类别出现的次数
#排序
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
#测试
group,labels=createDataSet()
result=classify0([1,0],group,labels,3)
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 0],
[1 0],
[1 0],
[1 0]]
然后减去训练样本集,求出两个矩阵的差,差值为
[[ 0. -1.1]
[ 0. -1. ]
[ 1. 0. ]
[ 1. -0.1]]
(2)使用欧氏距离公式,计算两个向量点之间的距离
首先求差值的2次方,结果为:
[[ 0. 1.21]
[ 0. 1. ]
[ 1. 0. ]
[ 1. 0.01]]
然后将矩阵的每一行相加得到:
[ 1.21 1. 1. 1.01]
然后开根
[ 1.1 1. 1. 1.00498756]
根据距离最近点排序
值 : 1 1 1.00498756 1.1
下标: 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