导入一些常用的库
from numpy import * import operator from os import listdir
# 开始定义分类函数 # inx为需要分类的参数,dataSet为训练集,labels为dataSet的标签向量,也就是对应的分类结果。k为最近的几个邻近数目,k应为奇数。 def classify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] # shape是返回的为dataSet的维度,也就是有几行几列(如果是二维)。 # 取第一个维度就是有多少行,一般来说行为数据有多少条,列为数据特征值。 diffMat = tile(inX, (dataSetSize,1)) - dataSet # tile函数是创建一个重复元素矩阵的函数,第一个参数inx为需要分类的参数,(dataSetSize,1)为重复的方式。 # 这里的行重复的次数与数据集的条数相同,列重复一次。因为输入参数的特征数(列数),和每条数据的列数一样,只要重复一次就可以了 # diffMat就是一个输入参数和每个数据的特征值之差矩阵 sqDiffMat = diffMat**2 # 将特征值之差的矩阵的每个元素都平方 sqDistances = sqDiffMat.sum(axis=1) # 将每行的元素按列加和,axis=1是指定加和方式为按列加和 distances = sqDistances**0.5 # 将加和后开方就得出了inx到每个数据的距离,这里的算法用的是欧式距离,还有一种曼哈顿距离也可以考虑 sortedDistIndicies = distances.argsort() # 按从小到大排列再提取其对应的index(索引),然后输出索引值,就是原来数据中排第几行。 classCount={} # 创建分类统计字典 for i in range(k): # 取前K个数据 voteIlabel = labels[sortedDistIndicies[i]] # 先取第i个数据的index值,然后再根据index值取到标签 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 # 根据取到的标签去字典中找对应的index,如果没有这个index便创建这个index,默认初始值为0 # 找到这个index对应的值,然后加1,因为统计到了一次这个index sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # 原书classCount.iteritems()在python3.5版本中改成了classCount.items(),来获取字典中的键-值 # 按照第二个域来排序也就是值来排序 # reverse = True 就是反转,从大到小排序 return sortedClassCount[0][0] #输出标签
【1】由于tile这个函数创建矩阵比较陌生
建议可以自己用打印一下tile(1,4); tile(1,(4,2)); tile((1,2),(4,2)) 来感受一下
注意tile是numpy下的函数。需要先导入numpy
【2】argsort 函数是将dataSet中的数据先按从小到大排列,然后再给出排列好的数据在原来dataSet中是第几行的一个数组。
如果对这个函数比较陌生也可以自己创建几个例子来print一下。
def file2matrix(filename): fr = open(filename) # 打开这个输入文件 arrayOLines = fr.readlines() # 读取文件信息 numberOfLines = len(arrayOLines) # 读取文件行数N returnMat = zeros((numberOfLines,3)) # 创建一个N行3列元素全部是0的矩阵 classLabelVector = [] # 创建一个存放分类向量的空矩阵 index = 0 # 初始化index for line in arrayOLines: # 对于文件中的每一行 line = line.strip() # 移除字符串头尾指定的字符(默认为空格) listFromLine = line.split('\t') # 根据tab来分割每行的数据 returnMat[index,:] = listFromLine[0:3] # 将读取出来的前三个值赋给那个零矩阵的第index行 classLabelVector.append(int(listFromLine[-1])) # 将最后一个值赋给分类矩阵中 index += 1 # index加1 return returnMat,classLabelVector
首先要熟悉这个要读取的数据结构,这篇文章是已经熟悉了数据结构,才能这样创建矩阵。
def datingClassTest(): hoRatio = 0.10 #hold out 10% datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] # 返回行数 numTestVecs = int(m*hoRatio) #确定测试集 errorCount = 0.0 for i in range(numTestVecs): classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)#numTestVecs前为测试集,之后的数据都为训练集 print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])) if (classifierResult != datingLabels[i]): errorCount += 1.0 print ("the total error rate is: %f" % (errorCount/float(numTestVecs))) print (errorCount)
记住python3 print要加括号了