1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > 《机器学习实战》读书笔记(二)K-近邻算法(下)(手写识别系统)

《机器学习实战》读书笔记(二)K-近邻算法(下)(手写识别系统)

时间:2023-12-17 00:27:08

相关推荐

《机器学习实战》读书笔记(二)K-近邻算法(下)(手写识别系统)

前言:本作者书写的博文中所包含的所有文件,读者均可从作者提供的链接中下载,创作不易,多谢理解!

2.3手写识别系统

本节我们将一步步地构建使用k-近邻分类器的手写识别系统,

老规矩,先附上文件下载链接:/download/qq_38172282/11232509

链接文件中的材料如下图所示:

准备数据:将图像转换为测试向量

digits.zip文件为压缩文件,里面包含testDigits+trainingDigits文件

testDigits文件为测试用的手写数字数据,包含大约900个测试数据,

trainingDigits文件为训练用的手写数字数据,包含大约2000个测试数据,每个数字约含有200个样本

上述文件中:文件名 a_b.txt 中,a代表的是文件中展示的数字,b代表的是数字的编号,内容是32*32的0和1组成的图案。

本节代码较为简单,首先创建一个1*1024的Numpy数组,然后打开给定的文件,循环读出文件的前32行,并将每行的头32个字符值存储在Numpy数组中,最后返回数组!

话不多说,可直接运行代码如下所示:

import numpy as np#将32*32的二进制图像矩阵转换为1*1024的向量def img2vector(filename):returnVect = np.zeros((1,1024))fr = open(filename)for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0,32*i+j] = int(lineStr[j])return returnVecttestVector = img2vector('testDigits/0_13.txt')print(testVector[0, 0:31])print(testVector[0, 32:63])

运行结果如下:

测试算法:使用K-近邻算法识别手写数字

1、对训练集,获取目录下的txt文件名字,组成列表。在for循环中,通过对文件名的字符操作可以得到Label(标签),然后打开文件,将32*32转成1*1024,最后得到训练集的特征矩阵和标签向量

2、对测试集,一样得到标签和特征向量,然后将特征向量、训练集特征矩阵和标签向量、k=3输入defclassify0,返回预测标签,与实际标签比对。

在下面的代码中,为了读者能理解程序清单2-6,我特意添加了较为详细的备注!

可直接运行代码如下所示:

import numpy as npimport operatorfrom os import listdir#用于获取文件夹下的文件名# #对目标元素进行分类# #程序清单2-1# def classify0(inX, dataSet, labels, k):#dataSet_size = dataSet.shape[0]## 在列方向上重复inX,1次,行方向上重复inX,dataSet_size次#diff_mat = np.tile(inX, (dataSet_size, 1)) - dataSet## diff_mat:输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算#sq_diff_mat = diff_mat ** 2## 按行进行累加,axis=1表示按行。#sq_distances = sq_diff_mat.sum(axis=1)## 开方运算,求出距离#distances = sq_distances ** 0.5## 返回distances中元素从小到大排序后的索引值#sorted_dist_indices = distances.argsort()## 定一个字典:统计类别次数#class_count = {}#for i in range(k):# # 取出前k个元素的类别# vote_index_label = labels[sorted_dist_indices[i]]# # 统计类别次数# class_count[vote_index_label] = class_count.get(vote_index_label, 0) + 1# # 把分类结果进行降序排序,然后返回得票数最多的分类结果# sorted_class_count = sorted(class_count.items(), key=operator.itemgetter(1), reverse=True)# return sorted_class_count[0][0]#与书中程序清单相同,不过是改进后的K-近邻算法def classify0(X, dataset, labels, k):size = dataset.shape[0]dis = np.sqrt(np.sum(np.square(dataset-X), axis=1))#差值后平方、求和、开方sort_index = np.argsort(dis)#按照距离排序,返回的是排序后的索引label_count = {}for i in range(k):label = labels[sort_index[i]]label_count[label] = label_count.get(label, 0)+1sort_label = sorted(label_count.items(), key=lambda d: d[1], reverse=True)#按照标签出现次数进行排序return sort_label[0][0]#将32*32的二进制图像矩阵转换为1*1024的向量def img2vector(filename):returnVect = np.zeros((1, 1024))fr = open(filename)for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0,32*i+j] = int(lineStr[j])return returnVectdef handwritingClassTest():# 初始化我们所需要的数据hwLabels = []# 这里需要我们提前导入os模块,listdir可以列出给定目录下的文件名trainingFileList = listdir('trainingDigits') # 加载训练集m = len(trainingFileList) # 获得训练样本数目trainingMat = np.zeros((m,1024)) # 构造m×1024的矩阵# 循环遍历训练集中的每个文件,生成每个数字的向量信息,保存在trainingMat中for i in range(m):fileNameStr = trainingFileList[i] # 获得文件名fileStr = fileNameStr.split('.')[0] # 分离.txtclassNumStr = int(fileStr.split('_')[0]) # 获得该文件所代表的数字hwLabels.append(classNumStr) # 将文件所代表的数字其存放在类别标签中trainingMat[i,:] = img2vector('trainingDigits\\%s' % fileNameStr)# 遍历测试数据文件夹,使用KNN进行测试。testFileList = listdir('testDigits') # 遍历测试集errorCount = 0.0mTest = len(testFileList) # 获得测试样本数目for i in range(mTest):fileNameStr = testFileList[i]fileStr = fileNameStr.split('.')[0] # 分离.txtclassNumStr = 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.0print("\nthe total number of errors is: %d" % errorCount)print("\nthe total error rate is: %f" % (errorCount/float(mTest)))print(handwritingClassTest())

运行结果如下图所示:

K-近邻算法识别手写数字数据集,错误率为1.06%,改变变量k的值、修改函数handwritingClassTest()随机选取训练样本、改变训练样本的数目,都会对k-近邻算法的错误率产生影响,感兴趣的话可以改变这些变量值,观察错误率的变化。

K-近邻算法小结

k-近邻算法是分类数据最简单最有效的算法。k-近邻算法是基于实例的学习,使用算法时我们必须有接近实际数据的训练样本数据。k-近邻算法必须保存全部数据集,如果训练数据集的很大,必须使用大量的存储空间。此外, 由于必须对数据集中的每个数据计算距离值,实际使用时可能非常耗时。k-近邻算法的另一个缺陷是它无法给出任何数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。