徒手写代码之《机器学习实战》----KNN算法(3)(手写识别系统项目)

    xiaoxiao2025-03-04  39

    手写识别系统

    说明:

    将数据集文件 ‘digits.zip’ 解压至当前文件夹

    定义将图像转换为向量函数

    # 导入程序所需要的模块 import numpy as np import operator from os import listdir # 将32*32的二进制图像矩阵转换为1*1024向量 def img2vector(filename): # 存储图片像素的向量维度是1x1024 # 创建1*1024零向量 returnVect = np.zeros((1, 1024)) # 打开文件 fr = open(filename) # 按行读取 for i in range(32): # .readline() 和 .readlines() 之间的差异是后者一次读取整个文件 # .readline() 每次只读取一行 lineStr = fr.readline() #每一行的前32个元素依次添加到returnVect中 for j in range(32): returnVect[0, 32*i+j] = int(lineStr[j]) # 返回转换后的1*1024向量 return returnVect #测试img2vector函数,然后与文本编辑器打开的文件进行比较。 returnVect=img2vector("./digits/trainingDigits/0_0.txt") returnVect[0,0:31] array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])

    定义 k 近邻算法

    def classify0(inX, dataSet, labels, k): # inX是测试集,dataSet是训练集,lebels是训练样本标签,k是取的最近邻个数 dataSetSize = dataSet.shape[0] # 训练样本个数 diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet # np.tile: 重复n次 sqDiffMat = diffMat**2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances**0.5 # distance是inX与dataSet的欧氏距离 sortedDistIndicies = distances.argsort() # 返回排序从小到达的索引位置 classCount = {} # 字典存储k近邻不同label出现的次数 for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 对应label加1,classCount中若无此key,则默认为0 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) # operator.itemgetter 获取对象的哪个维度的数据 return sortedClassCount[0][0] # 返回k近邻中所属类别最多的哪一类

    定义手写数字识别系统函数

    def handwritingClassTest(): # 训练样本的类别标签 hwLabels = [] #导入训练集,函数listdir可以列出给定目录的文件名。 trainingFileList = listdir('./digits/trainingDigits') #返回文件夹下文件的个数 m = len(trainingFileList) #初始化训练矩阵 trainingMat = np.zeros((m, 1024)) #从文件名中解析出训练集的类别 for i in range(m): #fileNameStr得到的是每个文件名称,例如"0_0.txt" fileNameStr = trainingFileList[i] #去掉“.txt”,剩下“0_0” fileStr = fileNameStr.split('.')[0] # 按下划线‘_' 划分“0_0”,取第一个元素为类别标签 classNumStr = int(fileStr.split('_')[0]) #将获得的类别添加到 hwLabels中 hwLabels.append(classNumStr) #将每一个文件的1x1024数据存储到trainingMat矩阵中 trainingMat[i, :] = img2vector('./digits/trainingDigits/%s' % fileNameStr) # 测试样本 #导入测试集,函数listdir可以列出给定目录的文件名。 testFileList = listdir('./digits/testDigits') #iterate through the test set #错误检测计数,初始为0 errorCount = 0.0 #测试数据的数量 mTest = len(testFileList) for i in range(mTest): # fileNameStr 得到的是每个文件名称,例如"0_0.txt" fileNameStr = testFileList[i] #去掉“.txt”,剩下“0_0” fileStr = fileNameStr.split('.')[0] # 按下划线‘_' 划分“0_0”,取第一个元素为类别标签 classNumStr = int(fileStr.split('_')[0]) #获得测试集的1x1024向量 vectorUnderTest = img2vector('./digits/testDigits/%s' % fileNameStr) # 调用knn函数 classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 1) print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)) if (classifierResult != classNumStr): errorCount += 1.0 print("\nthe total number of errors is: %d" % errorCount) print("\nthe total error rate is: %f" % (errorCount/float(mTest))) handwritingClassTest()

    参考文档:

    最新回复(0)