机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别
概要
目的
构造使用k-近邻分类器的手写识别系统。为了简单起见,这里构造只能识别数字0到9分类器
数据格式
文件名包含了标签
内部是图片转化成的txt格式
步骤
图像转化为测试向量
必须将图像格式化处理为一个向量。 我们将把一个32 x32的二进制图像矩阵转换为1 x 1024的向量,这样前两节使用的分类器就可以处理数字图像信息了.
# 打开文件 def imgvector(filename): returnVect=np.zeros((1,1024)) fr=open(filename,'r',encoding='utf-8') for i in range(32): lineStr=fr.readline() for j in range(32): returnVect[0,32*i+j]=int(lineStr[j]) return returnVect
测试算法
1.获取目录的内容
2.读取目录的文件名因为它包含了分类的标签
3.读取每张图片(txt文档)的向量
4.读取测试集,进行训练,输出结果
5.统计最终结果
# 手写测试 def handwritingClassTest(): hwLabels=[] trainingFileList=listdir('KNN/testDigits') m=len(trainingFileList) trainingMat=np.zeros((m,1024)) for i in range(m): filenameStr=trainingFileList[i] fileStr=filenameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0]) hwLabels.append(classNumStr) trainingMat[i,:]=imgvector('KNN/testDigits/%s'%filenameStr) testFileList=listdir('KNN/testDigits')#注意这是错误的,要使用测试集进行测试,因为我没找到测试集,自己又懒得从训练集去抠,逃 errorCount=0.0 mTest=len(testFileList) for i in range(mTest): filenameStr=testFileList[i] fileStr=filenameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0]) vectorUnderTest=imgvector('KNN/testDigits/%s'%filenameStr) classifierResult=knnClassify(vectorUnderTest,trainingMat,hwLabels,3) print("分类器的返回结果是%d,真正的结果是%s"%(classifierResult,classNumStr)) if classifierResult!=classNumStr: errorCount+=1.0 print("总预测错误的次数为: %d "%errorCount) print("总的错误率为 %f "%(errorCount/float(mTest)))
结果
我的做法是错误的,不可以使用训练接作为测试集!!!,但是还是记录下吧!
附录代码
import numpy as np from os import listdir import operator as op #K近邻算法 #inX是输入的数据 #dataSet是训练的数据 #labels是标签,类别 #k是周围邻居的数量 #返回预测的类别 def knnClassify(inX,dataSet,labels,k): #计算欧式距离 dataSetSize=dataSet.shape[0]#shape是(4,2),要获取点的数量显然是shape[0] diffMat=np.tile(inX,(dataSetSize,1))-dataSet ''' np.tile(inX,(dataSetSize,1))=[[0,0],[0,0],[0,0],[0,0]] dataSet=[[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]] np.tile-dataSet=[[-1.0,-1.1],[-1.0,-1.0],[0,0],[0,-0.1]] 即([x1-x0,y1-y0],[x2-x0,y2-x0],[x3-x0,y3-y0],[x4-x0,y4-y0]) ''' sqdiffMat=diffMat**2 #([(x1-x0)**2,(y1-y0)**2],[(x2-x0)**2,(y2-x0)**2],[(x3-x0)**2,(y3-y0)**2],[(x4-x0)**2,(y4-y0)**2]) sqDistances=sqdiffMat.sum(axis=1) #([(x1-x0)**2+y1-y0)**2],[(x2-x0)**2+(y2-x0)**2],[(x3-x0)**2+(y3-y0)**2],[(x4-x0)**2+(y4-y0)**2]) # print(sqDistances) distances=sqDistances**0.5 #([(x1-x0)**2+(y1-y0)**2]**(0.5),[(x2-x0)**2+(y2-x0)**2]**(0.5),[(x3-x0)**2+(y3-y0)**2]**(0.5),[(x4-x0)**2+(y4-y0)**2])**(0.5) sortedDistIndicies=distances.argsort()#按照数值大小对下标排序,[2 3 1 0] classCount={} #选择距离最小的k个点 for i in range(k): votIlabel=labels[sortedDistIndicies[i]]#获取最近的K个邻居的距离,对应的目标值 # print(votIlabel) classCount[votIlabel]=classCount.get(votIlabel,0)+1#get(key,default)当key不存在时候默认值是default sortedClassCount = sorted(classCount.items(), key=op.itemgetter(1), reverse=True) # [('B', 2), ('A', 1)] return sortedClassCount[0][0]#返回与其最近的k个邻居中,出现最多的次数 # 打开文件 def imgvector(filename): returnVect=np.zeros((1,1024)) fr=open(filename,'r',encoding='utf-8') for i in range(32): lineStr=fr.readline() for j in range(32): returnVect[0,32*i+j]=int(lineStr[j]) return returnVect # 手写测试 def handwritingClassTest(): hwLabels=[] trainingFileList=listdir('KNN/testDigits') m=len(trainingFileList) trainingMat=np.zeros((m,1024)) for i in range(m): filenameStr=trainingFileList[i] fileStr=filenameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0]) hwLabels.append(classNumStr) trainingMat[i,:]=imgvector('KNN/testDigits/%s'%filenameStr) testFileList=listdir('KNN/testDigits')#注意这是错误的,要使用测试集进行测试,因为我没找到测试集,自己又懒得从训练集去抠,逃 errorCount=0.0 mTest=len(testFileList) for i in range(mTest): filenameStr=testFileList[i] fileStr=filenameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0]) vectorUnderTest=imgvector('KNN/testDigits/%s'%filenameStr) classifierResult=knnClassify(vectorUnderTest,trainingMat,hwLabels,3) print("分类器的返回结果是%d,真正的结果是%s"%(classifierResult,classNumStr)) if classifierResult!=classNumStr: errorCount+=1.0 print("总预测错误的次数为: %d "%errorCount) print("总的错误率为 %f "%(errorCount/float(mTest))) if __name__ == "__main__": handwritingClassTest()
目录结构
数据集地址
https://github.com/pbharrin/machinelearninginaction
参考书籍
<>
来源:https://www.cnblogs.com/mengxiaoleng/p/12236075.html