k近邻算法:采用测量不同特征值之间的距离方法进行分类。
优点:精度高,对异常不敏感,无输入假定;
缺点:复杂度高;
适用范围:数值型,标称型。
正常人听得懂的算法原理:取出样本数据集中前k个和新数据“最像”的集合,并用这集合中出现最多次数的分类来作为新数据的分类。“最像”指的是:数据的特征属性最相似(最近邻)。
然后本菜鸡开始梳理实战书上过程:
1、准备:使用Python导入数据
创建kNN.py文件,输入
from numpy import * # 导入科学计算包NumPy import operator # 导入运算符模块 #createDataSet()函数创建数据集合标签 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
导入以上程序模块,输入
>>> import kNN
>>> group,labels=kNN.createDataSet()
>>> group
array([[1. , 1.1],
[1. , 1. ],
[0. , 0. ],
[0. , 0.1]])
>>> labels
['A', 'A', 'B', 'B']
2、从文本中解析数据
正常人可理解的算法过程:
(1)计算原有所有结点和新结点的距离;
(2)距离递增排序;
(3)选前k个点(即距离最小的k个点);
(4)计算这k个点不同类别的频率;
(5)以最高频率的类别作为当前点的预测分类。
然后接着在kNN.py里写函数classify0()
# 参数注解 # inX 用于分类的输入向量 # dataSet 输入的训练样本集 # labels 标签向量 # k 前k个 def classify0(inX, dataSet, labels, k): # shape属性依次返回向量的各维度个数,如二维矩阵则范围[行,列],shape[0]则取出其行数dataSetSize dataSetSize = dataSet.shape[0] # tile函数功能:如向量A,tile(A,(i,j))则将A在行上乘i次,列上乘j次,此处将用于分类的输入向量扩充到和输入的训练样本集一样大的矩阵,相减即得到各个元素之差矩阵diffMat diffMat = tile(inX, (dataSetSize, 1)) - dataSet sqDiffMat = diffMat ** 2 # diffMat每个元素(属性差值)平方 sqDistances = sqDiffMat.sum(axis=1)#sum函数:没有axis参数表示全部相加,axis=0表示按列相加,axis=1表示按照行的方向相加 distances = sqDistances ** 0.5#平方和开方 sortedDistIndicies = distances.argsort()#argsort()函数返回默认返回原数组在按递增顺序排序后的下标位置 classCount = {}#创建字典 for i in range(k):#找出相差最小的前k个 voteIlabel = labels[sortedDistIndicies[i]]#通过argsort()函数定位到的原数组中下标 classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1#get()函数取出字典中对应键的值,默认为0,然后自增 #对classCount根据各个元素中下标为1(实际第二个子元素)排序,并通过reverse设置为真使其反序,这样第一个元素就有要找的分类属性 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) #劳资终于找到你啦!!!! return sortedClassCount[0][0]
接着我们来兴奋的测试一下:
>>> import kNN
>>> kNN.classify0([0,0],group,labels,3)
'B'
结果正确,很开森!
感谢大家看到最后,发现错误欢迎指正。