手写识别系统(k-近邻算法)

k-近邻算法(kNN)是机器学习中一个相对比较简单的算法。该算法在训练集中数据和标签已知的情况下,输入测试数据,将测试数据的特征与训练集中对应的特征进行相互比较(比如通过欧氏距离),找到训练集中与之最为相似的前K个数据,则该测试数据对应的类别就是K个数据中出现次数最多的那个分类,其算法的描述为:
1)计算测试数据与各个训练数据之间的距离;
2)按照距离的递增关系进行排序;
3)选取距离最小的K个点;
4)确定前K个点所在类别的出现频率;
5)返回前K个点中出现频率最高的类别作为测试数据的预测分类。

以下代码是通过kNN算法实现的手写识别系统。其中每个输入数据为32*32的二值图像,数据存储在txt文件中(32行*32列)。文件命名为诸如”0_0.txt”的形式。其中,”_”左边的0为其实际标签(实际类),右边的0为数据的编号。

import numpy as np
from os import listdir

def readDatatoList(Filename):
    f=open(Filename)
    List=np.zeros((1,32*32))
    for i in range(0,32):
        eachLine=f.readline()
        for j in range(0,32):
            List[0,32*i+j]=int(eachLine[j])
    return List

def kNNclassify(dataSet,label,sample,k):
    sizeof_dataSet=len(label)
    distanceSet=np.zeros((1,sizeof_dataSet))
    for i in range(0,sizeof_dataSet):
        distance=0
        for j in range(0,32*32):
            distance+=((dataSet[i][j]-sample[0][j])**2)
        distance=distance**0.5
        distanceSet[0,i]=distance
    sortDistindex=distanceSet[0].argsort()
    # print(sortDistindex)
    maxVoted=0
    classVoted={}
    for i in range(0,k):
        if(label[sortDistindex[i]] in classVoted):
            classVoted[label[sortDistindex[i]]]+=1
        else:
            classVoted[label[sortDistindex[i]]]=1
        if(classVoted[label[sortDistindex[i]]]>maxVoted):
            maxVoted=classVoted[label[sortDistindex[i]]]
            nearClass=label[sortDistindex[i]]
    return nearClass

def handwritingTest():
    trainingFileList=listdir('trainingDigits')
    trainingSampleNum=len(trainingFileList)
    trainingSet=np.zeros((trainingSampleNum,32*32))
    label=[]
    for i in range(0,trainingSampleNum):
        Filename=trainingFileList[i]
        trainingSet[i:]=readDatatoList('trainingDigits/%s' %Filename)
        label.append(int(Filename.split('_')[0]))

    testFileList=listdir('testDigits')
    errorNum=0
    testSampleNum=len(testFileList)
    for i in range(0,testSampleNum):
        Filename=testFileList[i]
        realClass=int(Filename.split('_')[0])
        sample=readDatatoList('testDigits/%s' %Filename)
        testedClass=kNNclassify(trainingSet,label,sample,3)
        if(realClass!=testedClass):
            errorNum+=1
        print("Case %d:The real class is:%d, the answer is:%d" %(i,realClass,testedClass))
    print("The total number of errors is:%d" %errorNum)
    print("The total error rate is: %f" %(errorNum/float(testSampleNum)))

handwritingTest()

测试结果:
32*32,k=3

为了提高效率,笔者对32*32的图片进行下采样,改成16*16,修改以下代码:

def readDatatoList(Filename):
    f=open(Filename)
    List=np.zeros((1,16*16))
    for i in range(0,16):
        qLine=f.readline()
        oLine=f.readline()
        for j in range(0,16):
            List[0,16*i+j]=int(qLine[2*j])+int(qLine[2*j+1])+int(oLine[2*j])+int(oLine[2*j+1])
    return List

得到同样的结果:
16*16,k=3

当然,k值设置不同、计算距离方式的不同、投票方式的不同、甚至训练样本的权重,等等因素,都可能影响正确率和时间效率。kNN的主要缺点是算法思想相对比较简单,时间效率不高(属于平时不训练,临阵磨枪)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值