基于K-近邻算法的手写数字识别研究

  • Post author:
  • Post category:其他




摘要:

基于K-近邻算法研究手写数字(0-9)的识别问题,本文通过对手写数字的图像进行处理,提取特征向量,使用Python实现了K-近邻算法,并在此基础上开发了一个GUI测试程序,不仅能够实时测试手写识别的结果和调整k值,而且能够对识别错误的数字进行更正,将其加入训练库,使得该程序具有持续的学习能力,不断提高识别精度。



1.引言




K-近邻算法是数据分类中最简单有效的算法。通过计算未知样本与已知样本之间的距离,找出离未知样本最近的已知样本,并将该样本的类别赋予未知样本,即实现了对未知样本的分类。其中,样本之间的距离是通过对样本的特征向量进行计算得出的,每个样本在特征空间中是一个点,则只需在特征空间中计算的两点距离就能计算出两个样本之间的距离,距离越小,则说明两个样本之间越相似。在选择最近样本时,如果选择的不止一个,例如k个,则称为k-近邻,此时未知样本分类的准则为:在k个最近的样本中,将出现次数最多的样本所属的类别赋予未知样本,即完成未知样本的分类。


在本文中,首先使用python实现了一个k-近邻算法,能够对任意的样本进行k-近邻分类。然后研究了图像特征参数的提取,即从每副图像中提取特征向量用于分类算法。使用该方法对大量的样本进行研究,研究不同k值情况下的分类精度问题,最后使用该算法实现一个手写数字识别演示软件。



2.K-近邻算法实现






K-近邻算法实现较为简单,其主要过程如下:


1)计算已知类别数据集中的点与当前点之间的距离;


2)按距离递增次数排序;


3)选取与当前点距离最小的k个点;


4)确定当前k个点所在的类别的出现频率;


5)返回前k个点中出现频率最高的点所属的类作为当前点的预测分类。


Python代码实现如下(使用python下的科学计算库numpy):


def knn_classify(inX,dataSet,labels,k):
    '''
    knn算法
    inX 待分类向量
    dataSet 训练样本
    labels 标签向量
    k 最邻近元素的个数
    '''
    dataSetSize = dataSet.shape[0]  #numpy用法 获取训练样本数据的维度大小
    diffMat = tile(inX,(dataSetSize,1))-dataSet #将inX扩展为跟dataSet维数相同进行相减
    sqDiffMat = diffMat**2
    sqDistances = sqDiffMat.sum(axis=1)
    distances = sqDistances**0.5       #上三步用于计算欧式距离
    sortedDistIndicies = distances.argsort()  #按Distance从小到大排序 此处记录的是下标
    classCount={}
    for i in range(k):   #取前k个
        votelabel=labels[sortedDistIndicies[i]]
        classCount[votelabel]=classCount.get(votelabel,0)+1  #记录每个类别在最近的k个中出现了几个  例如 dict: {'A': 1, 'B': 2}
    sortedClassCount = sorted(classCount.iteritems(),
                                  key=operator.itemgetter(1),reverse=True)#按 value字段排列字典 
    return sortedClassCount[0][0]  #返回所属类别



3.图像特征向量提取




为了将图像能够表示成特征向量,首先需要对0-9这10个数字的图像进行二值化,背景值为10,并且统一大小,在此处使用32×32像素,最后将该图像保存成txt格式方便调用。下图给出了两个例子:





图1 图像二值化后生产的txt文档格式


由于二值化后的图像仍然是二维数组的形式,因此考虑将其转化为一维形式,即1*1024维的数组,每个像素的值就是1024维特征空间的一个坐标轴的值,这样一幅图像就能够表示成特征空间中的点,而k-近邻分类算法就是要对这些点的距离进行计算。


4.手写识别软件的实现



在K-近邻算法的基础上,本文实现了一个带有GUI界面的程序,能够通过鼠标进行绘制数字,然后通过训练样本进行识别。


GUI程序使用Python库wxPython编写,并且通过pyinstaller进行编译,将py脚本文件编译成exe可执行文件,在没有安装python的计算机上也能够执行。UI界面如下:


图2  手写识别GUI界面


图2中的红色部分是绘制数字的区域,通过鼠标进行绘制,数字大小最好能够填满整个红色部分。


【清空】表示对红色部分进行清空;


【识别】表示对绘制的数字进行识别,识别的结果会写在按钮下边的长文本框中;


【最邻近点个数】即k值,表示在选择最近点时,选择多少个进行位置样本的分类决策’


【输入正确的值并更正】表示当识别错误时,可以选择输入一个正确的值,然后点击更正,将该样本加入训练库中,表示软件对手写的学习,在下一次识别过程中能够提高识别精度。


使用例子:例如,在红色区域绘制一个3后,通过点击识别,即能够将识别结果写在按钮下边的文本框中;若本来绘制的是5,而被错误地识别为3,则可通过在【输入正确的值并更正】处填上5,并点击更正按钮,则该结果会作为正确的分类进入训练样本库中。



图3 使用举例


软件识别过程中通过对鼠标在红色画布上的移动,记录鼠标的坐标信息,并将其所到之处及周围(线宽)像素设置为1,即完成了测试样本的处理。获取测试样本之后,将该样本与训练样本进行比较,使用k-近邻算法,找出该样本的分类,最后输出该样本的分类结果。


总结:


分类精度评价来看,k近邻分类分类效果总体还是比较好的,正确率能够到98%以上,但是,运用于实际场景中,由于未知样本变化太多,不确定性太强,很多时候效果并不令人满意。


代码链接:



手写数字识别Python代码




版权声明:本文为u010329292原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。