机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别

会有一股神秘感。 提交于 2020-01-27 16:10:26

机器学习实战学习笔记(二)-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

参考书籍

<>

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!