欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-07-14 20:01:43
...

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

概要

目的

构造使用k-近邻分类器的手写识别系统。为了简单起见,这里构造只能识别数字0到9分类器

数据格式

文件名包含了标签
机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别

内部是图片转化成的txt格式

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

步骤

图像转化为测试向量

必须将图像格式化处理为一个向量。 我们将把一个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)))

结果

我的做法是错误的,不可以使用训练接作为测试集!!!,但是还是记录下吧!
机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别
机器学习实战学习笔记(二)-KNN算法(2)-使用KNN算法进行手写数字的识别

附录代码

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()

目录结构

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

数据集地址

https://github.com/pbharrin/machinelearninginaction

参考书籍

<>