K-近邻算法构造手写识别系统

  为了简单起见,这里构造的系统只能识别数字0到9,需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32像素的黑白图像。尽管采用文本格式存储图像不能有效地利用内存空间,但是为了方便理解,我们还是将图像转换为文本格式。

---1.收集数据:提供文本文件

  该数据集合修改自“手写数字数据集的光学识别”-一文中的数据集合,该文登载于2010年10月3日的UCI机器学习资料库中http://archive.ics.uci.edu/ml。

      

---2.准备数据:将图像转换为测试向量

  trainingDigits中包含了大约2000个例子,每个数字大约有200个样本;testDigits中包含了大约900个测试数据。两组数据没有重叠。

  我们先将图像格式化处理为一个向量。我们将一个32*32的二进制图像矩阵转换为1*1024的向量。

  我们首先编写函数img2vector,将图像转换为向量:该函数创建1*1024的NumPy数组,然后打开指定的文件,循环读出文件的前32行,并将每行的前32个字符值存储在NumPy数组中,最后返回数组。

#!/usr/bin/python
# -*- coding: utf-8 -*-
from numpy import *     #引入科学计算包numpy
from os import listdir
import operator         #经典python函数库,运算符模块

#算法核心
#inX:用户分类的输入向量,即将对其进行分类
#dataSet:训练样本集
#labels:标签向量
def classifyO(inX,dataSet,labels,k):
    #距离计算
    dataSetSize=dataSet.shape[0] #得到数组的行数,即知道有几个训练数据
    diffMat=tile(inX,(dataSetSize,1))-dataSet  #tile是numpy中的函数,tile将原来的一个数组,扩充成了4个一样的数组;diffMat得到目标与训练数值之间的差值
    sqDiffMat=diffMat**2         #各个元素分别平方
    sqDistances=sqDiffMat.sum(axis=1)
    distances=sqDistances**0.5   #开方,得到距离
    sortedDistIndicies=distances.argsort()  #升序排列
    #选择距离最小的k个点
    classCount={}
    for i in range(k):
        voteIlabel=labels[sortedDistIndicies[i]]
        classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
    #排序
    sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortedClassCount[0][0]

def img2vector(filename):
    returnVect=zeros((1,1024))
    fr=open(filename)
    for i in range(32):
        lineStr=fr.readline()
        for j in range(32):
            returnVect[0,32*i+j]=int(lineStr[j])
    return returnVect

  在python命令行中输入下列命令测试img2vector函数,然后与本文编辑器打开的文件进行比较:

>>> import kNN
>>> testVector=kNN.img2vector(‘digits/testDigits/0_13.txt‘) #根据自己的目录写
>>> testVector[0,0:31]
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.])
>>> testVector[0,32:63]
array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,
        1.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,
        0.,  0.,  0.,  0.,  0.])

---3.测试算法:使用k-近邻算法识别手写数字

  我们已经将数据处理成分类器可以识别的格式,现在要做的是将这些数据输入到分类器,检查分类器的执行结果。handwritingClassTest()是测试分类器的代码,将其写入kNN.py文件中。在写入之前,保证将from os import listdir写入文件的起始部分。这段代码主要功能是从os模块中导入函数listdir,它可以列出给定目录的文件名。

def handwritingClassTest():
    hwLabels=[]
    trainingFileList=listdir(‘E:\\python excise\\digits\\trainingDigits‘)
    m=len(trainingFileList)
    trainingMat=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,:]=img2vector(‘digits/trainingDigits/%s‘ %fileNameStr)
    testFileList=listdir(‘E:/python excise/digits/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=img2vector(‘digits/testDigits/%s‘%fileNameStr)
        classifierResult=classifyO(vectorUnderTest,trainingMat,hwLabels,3)
        print "the classifier came back with:%d,the real answeris:%d" %(classifierResult,classNumStr)
        if(classifierResult !=classNumStr):errorCount+=1.0
    print "\nthe total number of error is:%d"%errorCount
    print "\nthe total error rate is:%f"%(errorCount/float(mTest))

  解释:将E:\\python excise\\digits\\trainingDigits目录中的文件内容存储到列表trainingFileList中,然后可以得到文件中有有多少文件,并将其存储在变量m中。接着,代码创建一个m行1024列的训练矩阵,该矩阵的每行数据存储一个图像。我们可以从文件名中解析出分类数字,该目录下的文件按照规则命名,如文件9_45.txt的分类是9,它是数字9的第45个实例。然后我们可以将类代码存储到hwLabels向量中,使用前面的img2vector函数载入图像。

  下一步中,对E:/python excise/digits/testDigits目录中文件执行相似的操作,不同的是我们并不将这个目录下的文件载入矩阵,而是使用classifyO()函数测试该目录下的每个文件。由于文件中的值已经在0和1之间,所以不用归一化。

  在python命令提示符中输入kNN.handwritingClassTest(),测试该函数的输出结果。依赖于机器速度,夹在数据集可能需要话费很长时间,然后函数依次测试每个文件:

>>> kNN.handwritingClassTest()
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:0,the real answeris:0
the classifier came back with:1,the real answeris:1
the classifier came back with:1,the real answeris:1
the classifier came back with:1,the real answeris:1
the classifier came back with:1,the real answeris:1
...
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9
the classifier came back with:9,the real answeris:9

the total number of error is:11

the total error rate is:0.011628

总结
  k-近邻算法识别手写数字数据集,错误率为1.2%。改变变量k的值、修改函数handwritingClassTest随机选取训练样本、改变训练样本的数目,都会对k-近邻算法的错误率产生影响。

 

时间: 2024-10-12 03:58:29

K-近邻算法构造手写识别系统的相关文章

机器学习实战笔记-K近邻算法3(手写识别系统)

1 准备数据:将图像转换为测试向量 这次数据集还是有两种,训练数据集和测试数据集,分别有2000个,900个. 我们将把一个32*32的二进制图像矩阵转换为1 x 1024的向量,这样前两节使用的分类器就可以处理数字图像信息了. 代码: def img2vector(filename): returnVect = zeros((1,1024)) file = open(filename) for i in range(32): line = file.readline() for j in ra

Python 基于KNN算法的手写识别系统

本文主要利用k-近邻分类器实现手写识别系统,训练数据集大约2000个样本,每个数字大约有200个样本,每个样本保存在一个txt文件中,手写体图像本身是32X32的二值图像,如下图所示: 手写数字识别系统的测试代码: from numpy import * import operator from os import listdir #inX    要检测的数据 #dataSet   数据集 #labels    结果集 #k      要对比的长度 def classify0(inX, data

基于K-近邻分类算法的手写识别系统

前言 本文将继续讲解K-近邻算法的项目实例 - 手写识别系统. 该系统在获取用户的手写输入后,判断用户写的是什么. 为了突出核心,简化细节,本示例系统中的输入为32x32矩阵,分类结果也均为数字.但对于汉字或者别的分类情形原理都是一样的. 有了前面学习的基础,下面直接进入项目开发步骤. 第一步:收集并准备数据 在用户主目录的trainingDigits子目录中,存放的是2000个样本数据. 每个样本一个文件,其中一部分如下所示: 文件命名格式为: 分类标签_标签内序号 如 0_20.txt 就表

机器学习实战笔记——基于KNN算法的手写识别系统

本文主要利用k-近邻分类器实现手写识别系统,训练数据集大约2000个样本,每个数字大约有200个样本,每个样本保存在一个txt文件中,手写体图像本身是32X32的二值图像,如下图所示: 首先,我们需要将图像格式化处理为一个向量,把一个32X32的二进制图像矩阵通过img2vector()函数转换为1X1024的向量: def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i in range(

《机器学习实战》之k-近邻算法(手写识别系统)

这个玩意和改进约会网站的那个差不多,它是提前把所有数字转换成了32*32像素大小的黑白图,然后转换成字符图(用0,1表示),将所有1024个像素点用一维矩阵保存下来,这样就可以通过knn计算欧几里得距离来得到最接近的答案. 1 import os 2 import operator 3 from numpy import * 4 5 def classify0(inX, dataSet, labels, k): 6 dataSetSize = dataSet.shape[0] 7 diffMat

【机器学习算法实现】kNN算法__手写识别——基于Python和NumPy函数库

[机器学习算法实现]系列文章将记录个人阅读机器学习论文.书籍过程中所碰到的算法,每篇文章描述一个具体的算法.算法的编程实现.算法的具体应用实例.争取每个算法都用多种语言编程实现.所有代码共享至github:https://github.com/wepe/MachineLearning-Demo     欢迎交流指正! (1)kNN算法_手写识别实例--基于Python和NumPy函数库 1.kNN算法简介 kNN算法,即K最近邻(k-NearestNeighbor)分类算法,是最简单的机器学习算

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

下面的例子来源为<机器学习实战>,例子只能识别0-9. 首先需要将图像二进制数据转化为测试向量: def imgTransformVector(filename): # 将 32x32 二进制图像矩阵转化为 1x1024 向量 returnVector = np.zeros((1,1024)) fr = open(filename) for i in range(32): lineStr = fr.readline() for j in range(32): returnVector[0,32

《机器学习实战》菜鸟学习笔记(三)kNN手写识别系统

目的:利用kNN识别数字0-9 材料:32*32的数字方阵(保存形式是文本文件) #-*-coding:utf-8-*- from numpy import * def img2vector(filename): #生成一个1*1024的array(zeros是numpy的函数,至于array与list区别这里就不多介绍了) returnVect = zeros((1,1024)) #使用open函数打开一个文本文件 fr = open(filename) #循环读取文件内容 for i in

《机器学习实战》-k近邻算法

目录 K-近邻算法 k-近邻算法概述 解析和导入数据 使用 Python 导入数据 实施 kNN 分类算法 测试分类器 使用 k-近邻算法改进约会网站的配对效果 收集数据 准备数据:使用 Python 解析文本文件 分析数据:使用 Matplotlib 画二维散点图 准备数据:归一化数值 测试算法:验证分类器 使用算法:构建完整可用系统 手写识别系统 准备数据 测试算法 使用算法:构建完整可用系统 总结 K-近邻算法 k-近邻分类算法概述 使用 k-近邻算法改进约会网站的配对效果 手写识别系统