第二章kNN完整代码注释
2018-01-19 16:41
99 查看
# -*- coding: cp936 -*- from numpy import * import operator from os import listdir import time #创建数据集 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 #inX:用于分类的输入向量 #dataSet:训练样本集 #labels:标签向量 #k:用于选择最近邻居的数目 def classify0(inX,dataSet,labels,k): dataSetSize=dataSet.shape[0]#shape函数的功能是查看矩阵或数组的维数,也就是说知道有几个训练数据,所以shape[0]表示得到数组的行数,它在这里是4 diffMat=tile(inX,(dataSetSize,1))-dataSet#tile()函数是numpy模块中的函数,它将原来的一个数组,扩充成了4个一样的数组。diffMat得到了目标与训练数值之间的差值 sqDiffMat=diffMat**2#diffMat中的每一个元素(上一行代码计算出来的目标数据集与每个训练数据集的各个特征值(这里只有两个)之间的差值)进行平方 sqDistance=sqDiffMat.sum(axis=1)#把上一行代码中的平方项按’列‘(?sqDiffMat数组的第一列加第二列)进行相加 distance=sqDistance**0.5#开根号,计算出距离啦! sortedDistIndicies=distance.argsort()#升序排列,得到一个升序排列的矩阵,argsort函数返回的是数组值从小到大的索引值 #下面进行选择距离最小的k个点 classCount={}#这是一个字典,用于计数,即用于存储不同标签(labels)出现的次数 for i in range(k): voteIlabel=labels[sortedDistIndicies[i]] #从前面已经排好序的矩阵中选择距离最小的k个点并获得这k个点所对应的标签,也就是前k个点,k是你在使用时具体输入的,书上k是3,所以就提炼出了前3个训练数据集的标签 #sortedDistIndicies[i]是索引值,正好与label的值的索引是对应的 classCount[voteIlabel]=classCount.get(voteIlabel,0)+1#classCount[voteIlabel]是个变量名,别多想,然后voteIlabel是前k个,也就是距离最小的k个训练数据集所对应的标签(labels),现在利用dict.get(key, default=None)函数来统计这k个的标签出现的次数,key就是dict中的键voteIlabel,如果不存在则返回一个0并存入dict(这里的dict就是classCount),如果存在则读取(get)当前值(标签),并在classCount中加1 #最后得到的classCount{}应该是类似这种样子的:classCount{'A':3,'B':0} #print voteIlabel #排序 sortedClassCount=sorted(classCount.iteritems(),#这里使用了sorted()函数sorted(iterable, cmp=None, key=None, reverse=False),iteritems()将classCount这个dict分解为元组列表(一个list包含两个tuple):[('B', 2), ('A', 1)] key=operator.itemgetter(1),reverse=True)#operator.itemgetter(1)表示按照第二个元素的次序对元组进行排序,因为编程语言的index(索引)从0开始 #print sortedClassCount return sortedClassCount[0][0]#返回出现次数最多的的标签,这也就是最终的分类(label)结果 def file2matrix(filename): fr=open(filename) arrayOLines=fr.readlines()#一次读取整个文本数据,并且readlines() 自动将文件内容分析成一个行的列表,该列表可以由 Python 的 for ... in ... 结构进行处理。比readline()快 ,下面的img2vector就是使用的readline(),因为要逐行逐个读取,可以对比一下 #print arrayOLines#打印出一大堆,电脑要卡死的节奏 numberOfLines=len(arrayOLines) returnMat=zeros((numberOfLines,3))#文件有几行就是几行,设置为3列(可调) #到这里 classLabelVector=[] index=0 for line in arrayOLines: line=line.strip()#去掉回车符,(使上下的数据紧凑在一起) ,括号里面是不太对的理解,是去掉那个超级大的一行的列表中的回车符“\n” ,然后一行一行的处理,最后才得到所看到的上下的数据紧凑在一起的数据 #print line# 这玩意儿根本刹不住车!果断注释掉! listFromLine=line.split('\t')#分成了4列数据,得到了4个列表 #print listFromLine#这玩意儿也刹不住车,密密麻麻的,注释掉! returnMat[index,:]=listFromLine[0:3] #前3个列表元素是爱伦要的特征,取出来去填充returnMat classLabelVector.append(int(listFromLine[-1]))#是1 or 2 or 3,填入得到分类标签向量 print classLabelVector index+=1#继续迭代 return returnMat,classLabelVector def autoNorm(dataSet): minVals=dataSet.min(0) #print minVals maxVals=dataSet.max(0) #print maxVals ranges=maxVals-minVals #print ranges normDataSet=zeros(shape(dataSet))#先创建一个(0)返回矩阵,维度与DatSet一样 #print normDataSet m=dataSet.shape[0]#获取dataSet的行数 normDataSet=dataSet-tile(minVals,(m,1)) normDataSet=normDataSet/tile(ranges,(m,1)) return normDataSet,ranges,minVals def datingClassTest(): hoRatio=0.10 datingDataMat,datingLabels=file2matrix('datingTestSet.txt')#读取所有的数据 normMat,ranges,minVals=autoNorm(datingDataMat)#归一化 m=normMat.shape[0]#获取一共有多少行数据 numTestVecs=int(m*hoRatio)#取全部数据的10%用作测试,这里一共有numTestVecs个测试数据 errorCount=0.0 for i in range(numTestVecs): classifierResult=classify0(normMat[i,:],normMat[numTestVecs:m,:],\ datingLabels[numTestVecs:m],3) #调用classify0函数,第一项是10%的测试数据,第二项是90%的训练数据,第三项是90%的训练数据所对应的标签,第四项是k的取值 print "the classifier came back with : %d,the real answer is : %d" %(classifierResult,datingLabels[i]) if (classifierResult!=datingLabels[i]):errorCount+=1.0#测试结果不等于已知结果,错误个数加1 print "the total error rate is: %f" %(errorCount/float(numTestVecs))#计算错误率 def classifyPerson(): resultList=['not at all','in small doses','in large doses']#构建返回的标签向量,这3个标签分别与第1,2,3类相对应,与最后一行代码呼应,海伦之前已经有了1000次的数据,所以我认为那个datingTestSet文件是本程序的结果汇总得到的答案,本身参与程序的是datingTestSet2文件,书中的27页代码清单2-4文件名写错了 percentTats=float(raw_input("percentage of time spent playing video game?")) ffMiles=float(raw_input("frequent flier miles earned per year?")) iceCream=float(raw_input("liters of ice cream consumed per year?")) datingDataMat,datingLabels=file2matrix('datingTestSet2.txt') normMat,ranges,minVals=autoNorm(datingDataMat) inArr=array([ffMiles,percentTats,iceCream])#创建目标特征值,这是classify0的第一个参数 classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)#新输入的目标变量也需要进行归一化 print classifierResult print "you will probably like this person:", resultList[classifierResult-1]#索引从0开始,索引减去1才能索引到对应的resultList #这里综合调用了前面所构造的各个函数 def img2vector(filename): returnVect=zeros((1,1024))#创建1行1024列的二维数组 fr=open(filename)#打开二进制图像文件 for i in range(32): #i lineStr=fr.readline()#readline()每次读取一行,每迭代一次就读取一行,比readlines()慢得多,readline()返回的是一个字符串对象,保存当前行的内容 #print int(lineStr[0]) for j in range(32): returnVect[0,32*i+j]=int(lineStr[j]) return returnVect def handwritingClassTest(): time_start=time.time()#计时开始 hwLabels=[] trainingFileList=listdir('trainingDigits')#将trainingDigits目录中的文件内容存储在训练列表"trainingFileList"中 m=len(trainingFileList)#得到目录中有多少文件,并将其存储在变量m中 trainingMat=zeros((m,1024))#创建一个m行1024列的训练矩阵,该矩阵的每行数据存储一个图像 for i in range(m): fileNameStr=trainingFileList[i]#依次获取每个文件的名字 fileStr=fileNameStr.split('.')[0]#将文件名分割成两部分并只取第一部分。第二部分是后缀格式,我们不需要它 classNumStr=int(fileStr.split('_')[0])#获取类名(1-9) hwLabels.append(classNumStr)#将类名依次添加到hwLabels里面 trainingMat[i,:]=img2vector('trainingDigits/%s'%fileNameStr)#打开目录中的每一个文件并添加到trainingMat这个矩阵中去 #print trainingMat #下面对testDIGITS执行类似的操作 testFileList=listdir('testDigits') #将testDigits目录中的文件内容存储在测试列表"testFileList"中 errorCount=0.0 mTest=len(testFileList)#得到目录中有多少文件,并将其存储在变量mTest中 for i in range(mTest): fileNameStr=testFileList[i]#依次获取每个文件的名字 fileStr=fileNameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0]) vectorUnderTest=img2vector('testDigits/%s'%fileNameStr)#这里和上面不同之处在于没有将读取的文件载入到矩阵中,而是要利用分类器进行测试,继续向下看 classifierResult=classify0(vectorUnderTest,trainingMat,hwLabels,3)#调用分类器进行测试 print "the classifier came back with: %d,the real answer is : %d"%(classifierResult,classNumStr) if (classifierResult!=classNumStr):errorCount+=1 print "\nthe total number of errors is:%d"%errorCount print "\nthe total error rate is :%f"%(errorCount/float(mTest)) time_end=time.time() #计时结束 print time_start-time_end, print "s"
相关文章推荐
- 机器学习实战 第二章KNN(1)python代码及注释
- 机器学习实战第二章kNN代码清单2-1详细注释
- PowerDesigner 12.5 开启注释列 将Comment(注释)及Name(名称)内容互相COPY的VBS代码 根据名称生成注释(完整示例)
- maven-javadoc插件避免thrift生成代码注释不完整
- PowerDesigner 12.5 开启注释列 将Comment(注释)及Name(名称)内容互相COPY的VBS代码 根据名称生成注释(完整示例)
- 电影记录管理系统 修改与注释,完整代码
- 自己写 localtime 函数(含完整注释,代码)
- Android远程登录含有loading登录效果~~完整代码和超级详细注释
- [翻译] 编写高性能 .NET 代码--第二章 GC -- 减少大对象堆的碎片,在某些情况下强制执行完整GC,按需压缩大对象堆,在GC前收到消息通知,使用弱引用缓存对象
- Java魔板游戏完整代码及注释
- 学习笔记——《机器学习实战》KNN算法实现 约会网站测试,手写数字识别,代码,注释,错误修改
- 最基本的C++ 窗口程序代码及完整注释
- KNN-Dating完整代码
- VB6+网络编程语言(Dhtml等)开发高级网页编辑器完整代码+注释
- C++单刷《机器学习实战》——kNN算法完整代码
- C231n-KNN-assignment1-完全代码及注释
- 机器学习实战:KNN 代码注释(python)
- openCV实现多人脸检测,多眼部检测,完整代码和详细注释
- KNN算法Python实现(代码来自机器学习实战)及注释
- 自己写 localtime 函数(含完整注释,代码)转载