姓名:赵宗明
学号:19021211230
转载自:https://blog.csdn.net/qq_42869979/article/details/102765558
【嵌牛导读】:机器学习实战之k-近邻算法识别手写数字(含拍照检验步骤详解)
【嵌牛鼻子】:机器学习 临近算法 识别手写数字
【嵌牛提问】:如何利用机器学习识别手写数字
【嵌牛正文】:
本例中使用K-近邻算法识别手写数字,参考书目:Peter Harrington 的<机器学习实战(中文版)>。本文主要是使用书中已经构建好的算法,来解决实际问题。
训练集采用文件 ‘trainingDigits’ 中的2000个样本,都为txt文件格式,每个数字大约含有200个样本,每个样本都为32行*32列。打开其中任意一个文件‘2_33.txt’,如下图所示:
可以明显的看见数字2。且有字体部分为1,空白部分为0。接下来,在纸上随便写一个数字,我写的是数字2,并用手机拍照:
用手机自行剪裁的小一点。
之后,用Photoshop(PS)处理,把图像剪裁成32 * 32像素的的图像。
步骤是:
1.在ps中打开该图像
2.点击上方的‘图像’——>‘图像大小’——>修改图像大小栏中的‘宽度(W)’与‘高度(H)’,再点击确定
就得到了32 * 32像素的的图像。
3.点击‘文件’——>‘储存为’,把当前图像储存好。如下图:
再把此时的图像(命名为‘1.png’)用MATLAB处理,得到test_myself.txt文件,注意应该把该图像导入matlab的当前文件中,否则会显示找不到该文件。
MATLAB代码如下:
如果,i2不转置,则得到的txt文件如下:
注意,此时test_myself.txt文本中,只有一行,即含有1*1024个字符,而不是32行 * 32列。需要修改书中的img2vector()与handwritingClassTest()函数,分别修改为img_myself()与handwritingPerson()函数。
所用到的Python代码及其解释如下:
from numpy import *
import operator
from os import listdir
def classify0(inX, dataSet, labels, k): #对于该函数的解释,见后面图中
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1) #every hang add together
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
def img2vector(filename): #该函数是针对文本中为32行*32列进行的处理函数,返回一个1*1024的数组
returnVect = zeros((1,1024))
fr = open(filename)
for i in range(32):
lineStr = fr.readline() #读取一行,即32个字符
for j in range(32):
returnVect[0,32*i+j] = int(lineStr[j])
return returnVect
##
def img_myself(filename): #该函数是针对文本中为1*1024进行的处理函数,返回一个1*1024的数组
returnVect=zeros((1,1024))
fr=open(filename)
lineStr=fr.readline() #读取一行,即1*1024个字符
for i in range(1024):
returnVect[0,i]=int(lineStr[i])
return returnVect
def handwritingPerson(filename): #filename为待测试的txt文件,本例中为'test_myself.txt'文件
hwLabels = []
trainingFileList = listdir('trainingDigits') #储存训练集'trainingDigits'文件夹中所有的文件名到列表trainingFileList中
m = len(trainingFileList)
trainingMat = zeros((m, 1024)) #每行储存一个图像
for i in range(m):
fileNameStr = trainingFileList[i] #第i个文件的文件名储存在fileNameStr中,如‘0_0.txt’
fileStr = fileNameStr.split('.')[0] #把文件名用‘.’分开成两部分,取第一部分,如把‘0_0.txt’分开成‘0_0’与‘txt’两部分,0代表取前一部分
classNumStr = int(fileStr.split('_')[0]) #同理,取‘0_0’中前一部分0,并转换为int类型
hwLabels.append(classNumStr) #训练集的标签矩阵
trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr) #打开trainingDigits文件夹下的文件,读取并转化为1*1024的矩阵后,添加到trainingMat的对应行中,组成训练集的矩阵
test_myself=img_myself(filename) #读取filename文件并转化为1*1024的矩阵,组成测试集
test_myself_label=classify0(test_myself,trainingMat,hwLabels,5) #进行训练并测试,把结果放到test_myself_label中
print("The test_myself_label is ",test_myself_label)
classify0()函数的解释如下图:
最后检验识别效果:
handwritingPerson('test_myself.txt')
大约运行5秒,得到运行结果:
识别正确!
————————————————
版权声明:本文为CSDN博主「qq_450593249」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42869979/article/details/102765558
网友评论