美文网首页嵌牛IT观察
近邻算法识别手写数字

近邻算法识别手写数字

作者: JS_Terry_M | 来源:发表于2019-10-28 14:14 被阅读0次

    姓名:赵宗明

    学号: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

    相关文章

      网友评论

        本文标题:近邻算法识别手写数字

        本文链接:https://www.haomeiwen.com/subject/pfhbvctx.html