机器学习实战--K近邻算法的实现(三)

                                      使用K近邻算法识别手写数字

这里构造的系统只能识别数字0-9,需要识别的数字已经使用图形处理软件处理成32*32大小的黑白图像,并将其转换为图像格式。

实际图像存储在两个子目录中:目录trainingDigits中,大约包含2000个例子,每个数字大约有200个样本,同一个数字有多种书写形态,数字样本被命名为:数字(0-9)_次序(0-xxx).txt文本的形式。testDigits中包含了大约900个测试数据,使用目录trainingDigits的数据来训练分类器,使用testDigits的数据来测试分类器的效果。

为使用前面的分类器,需要按照一行代表一个样本,每列一个特征的原则将图像格式化为一个向量。将32*32的二进制图像矩阵转化为一个1*1024的向量。首先编写函数img2vector:创建1*1024的Numpy数组,打开文件并循环读出文件的前32行,并将每行的头32个字符存储在Numpy数组中。源码如下:

#将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])
    return returnVect

 遍历最里层的returnVect[0,32*i+j] = int(lineStr[j])语句实现将矩阵的元素赋予到行向量数组上的功能,前面的0代表该行向量的索引。

写入代码之前,需要将from os import listdir写入文件起始部分,它可以列出给定目录的文件名。以下是源码:

#对测试集进行测试并得到错误率
def handwritingClassTest():
    hwLabels = []
    #得到trainingDigits目录下的文件列表
    trainingFileList = listdir('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)
        #2维数组的行赋值,遍历结束得到训练集,每一行代表一个图形样本
        trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr)
    #得到测试集文件列表
    testFileList = listdir('testDigits')
    errorCount = 0.0
    mTest = len(testFileList)
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = fileStr.split('_')[0]
        vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
        #得到测试集的预估值
        classiferResult = classify0(vectorUnderTest,trainingMat,hwLabels,3)
        print("the classifier cameback with:%d,the real answer is %s"\
              % (classiferResult,classNumStr))
        #将预估值与实际值进行比较
        if (classiferResult != int(classNumStr)):errorCount+=1.0
    print("\nThe total number of errors is:%d" %errorCount)
    print("\nThe total error rate is:%f" %(errorCount/float(mTest)))

listdir函数返回参数目录下的文件列表,通过遍历训练文件列表,提取文件名的数字项即样本的实际目标值,将实际目标值添加到标签列表中。然后通过字符串格式方法将文件路径传递到img2vector函数,并将返回的行向量赋给以i为索引的二维行向量中,遍历结束后是训练矩阵。再对测试集进行遍历,按照同样的方法得到测试数据的行向量,并将其作为参数传递给分类函数,得到预估值,并将预估值与实际目标值进行比较,得到错误计数,并计算错误率。

实际上这个算法的执行效率不高,每次测试数据都需要重新训练,适用于数据集小的情景,时间和存储花销较大。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值