机器学习笔记--K-近邻算法(三)

手写识别系统

0、说明

环境:window7 64位 python 3.5

与python2.7原文的代码有些不一样。

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

示例:使用允-近邻算法的手写识别系统

(1)收集数据:提供文本文件。

(2)准备数据:编写函数classify0(),将图像格式转换为分类器使用的制格式。

(3)分析数据:在python命令提示符中检查数据,确保它符合要求。

(4)训练算法:此步驟不适用于K-近邻算法。

(5)测试算法:编写函数使用提供的部分数据集作为测试样本,测试样本与非测试样本的区别在于测试样本是已经完成分类的数据,如果预测分类与实际类别不同,则标记为一个错误。

(6)使用算法:本例没有完成此步驟,若你感兴趣可以构建完整的应用程序,从图像中提取数字,并完成数字识别,美国的邮件分拣系统就是一个实际运行的类似系统。

1、准备数据:图像转换为测试数据

数据样本之一:文件0_1.txt

00000000000111110000000000000000
00000000001111111000000000000000
00000000011111111100000000000000
00000000111111111110000000000000
00000001111111111111000000000000
00000011111110111111100000000000
00000011111100011111110000000000
00000011111100001111110000000000
00000111111100000111111000000000
00000111111100000011111000000000
00000011111100000001111110000000
00000111111100000000111111000000
00000111111000000000011111000000
00000111111000000000011111100000
00000111111000000000011111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000111111000000000001111100000
00000011111000000000001111100000
00000011111100000000011111100000
00000011111100000000111111000000
00000001111110000000111111100000
00000000111110000001111111000000
00000000111110000011111110000000
00000000111111000111111100000000
00000000111111111111111000000000
00000000111111111111110000000000
00000000011111111111100000000000
00000000001111111111000000000000
00000000000111111110000000000000
我们将把一个32X32的二进制图像矩阵转换为1x1024的向量,这样前两节使用的分类器就可以处理数字图像信息了。

from numpy import *
import operator
import os, sys
# classify0是K-近邻的分类函数
# 参数:
#      inX:待测数据
#      dataSet:训练的数据集
#      labels:训练集的标签向量
#      K:K-近邻的值
def classify0(inX,dataSet,labels,k):
    dataSetSize = dataSet.shape[0]           #计算有多少条记录
    #tile(X,(a,b))   a 表示数据集X每条记录复制的次数,b表示每一条记录中元素按顺序重复的次数
    #因为要将待测是数据集与已知的数据集做差,所以将待测数据集的记录复制已知数据集的记录数,然后再减去原来的数据集,就可以获得相应的差值

    diffMat = tile(inX,(dataSetSize,1))-dataSet
    sqDifMat = diffMat ** 2
    #axis = 1对行求和
    sqDistances = sqDifMat.sum(axis = 1)
    distances = sqDistances ** 0.5
    sortedDistIndicies = distances.argsort()   #indices
    classCount = { }
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
    #这里的classCount.items() python3.x与python 2.X iteritems不一样
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]
#将32*32的矩阵读到1*1024的矩阵
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]) #转换成int类型
    return returnVect
#手写数字识别系统测试
def handwritingClassTest():
    #存放标签的向量
    hwLabels = []
    #获取目录内容   返回子文件目录名的数组
    trainingFileList = os.listdir('C:\\machinelearninginaction\\Ch02\\digits\\trainingDigits')
    #计算该目录下子文件的个数
    m = len(trainingFileList)
    #因为每个子文件都存放一张数字的文本信息32*32
    trainingMat = zeros((m,1024))
    for i in range(m):
        #目录格式为9_106.txt,目标是将9取出来
        fileNameStr = trainingFileList[i]
        #取出9_106
        fileStr = fileNameStr.split('.')[0]
        #取出9字符串,将其转换成整形
        classNumStr = fileStr.split('_')
        classNumStr = int(classNumStr[0])
        #将读取到的标签值添加到向量中
        hwLabels.append(classNumStr)
        trainingMat[i,:] = img2vector('C:\\machinelearninginaction\\Ch02\\digits\\trainingDigits\\%s' % fileNameStr)
    #获取测试集文件的目录
    testFileList = os.listdir('C:\\machinelearninginaction\\Ch02\\digits\\testDigits')
    errorCount = 0.0
    #计算测试集目录的长度
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        # 提取出测试集的标签值,为以后比较
        classNumStr = fileStr.split('_')
        classNumStr = int(classNumStr[0])
        # vectorUnderTest测试文件向量化
        vectorUnderTest = img2vector('C:\machinelearninginaction\Ch02\digits\\testDigits\%s' % fileNameStr)
        classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3)
#         print("the classifier came back with: %d,the real answer is %d"%(classifierResult,classNumStr))
        #如果训练出来的值与测试集的值不一样,记为错误
        if(classifierResult != classNumStr):
            errorCount += 1.0
    print("\n the total number of errors is %d"%errorCount)
    print("\n the total error rate is %f"%(errorCount/float(mTest)))
handwritingClassTest()
 the total number of errors is 11

 the total error rate is 0.011628

你可能感兴趣的:(机器学习实战)