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

本节主要内容来自Peter Harrington的《Machine Learning in Action》的中文版本《机器学习实战》

本文中数据代码

示例3

本例中我们将构造一个使用k-近邻分类器的手写识别系统。为了降低难度,该分类器只识别数字0到9。

手写识别系统

  1. 收集数据:提供图像数据,由数字01构成32x32的文本数据
  2. 准备数据:编写函数imgToVector(),将图像数据转换为分类器可使用的向量格式
  3. 测试算法:编写函数handWritingClassTest(),用提供的测试数据测试分类器,统计错误率
  4. 使用算法:对网上找到的手写数字图片进行识别

收集数据

2000个图片测试样本, 样本文件中的数据由01构成,如文件4_xx.txt中的数据见下图

准备数据

编写函数imgToVector(),将图像数据处理为向量

def imgToVector(filename):
    imgVector = zeros((1, 1024))
    file = open(filename)
    for i in range(32):
        line = file.readline()
        for j in range(32):
            imgVector[0, 32*i+j] = int(line[j])
    return imgVector

测试程序

testVector = kNN.imgToVector('digits/testDigits/0_0.txt')
print(testVector[0, 0:32])

运行结果

[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0.]

测试算法

用提供的测试数据测试分类器

def handWritingClassTest():
    hwLabels = []
    trainingFileList = listdir('digits/trainingDigits') #导入所有训练文件
    numTrain = len(trainingFileList) #统计训练文件数目
    trainingMatrix = zeros((numTrain, 1024))
    # print(numTrain)
    for i in range(numTrain):
        fileNameStr = trainingFileList[i] #找处文件名
        fileStr = fileNameStr.split('.')[0] #文件名中点前的部分
        classNumStr = int(fileStr.split('_')[0]) #文件名中_前的部分
        hwLabels.append(classNumStr) #标签——与文件中数字一致的,文件名中的数字
        trainingMatrix[i, :] = imgToVector('digits/trainingDigits/%s' % fileNameStr)
    testFileList = listdir('digits/testDigits')
    errorCount = 0.0
    numTest = len(testFileList)
    for i in range(numTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        testVector = imgToVector('digits/testDigits/%s' % fileNameStr)
        classifierResult = classify0(testVector, trainingMatrix, hwLabels, 3)
        print("分类器返回的是 %d, 实际上是 %d" % (classifierResult, classNumStr))
        if(classifierResult != classNumStr): errorCount += 1.0
    print("\n 总错误个数:%d" % errorCount)
    print("\n 错误率:%f" % (errorCount/float(numTest)))

测试程序

kNN.handWritingClassTest()

运行结果

分类器返回的是 4, 实际上是 4
分类器返回的是 3, 实际上是 3
分类器返回的是 0, 实际上是 0
分类器返回的是 0, 实际上是 0
分类器返回的是 4, 实际上是 4
分类器返回的是 1, 实际上是 1
...
分类器返回的是 1, 实际上是 1
分类器返回的是 2, 实际上是 2
分类器返回的是 1, 实际上是 1
分类器返回的是 3, 实际上是 3

 总错误个数:11

 错误率:0.011628

使用算法

网上找到的一个手写图片

def classifyPicture(filename):
    hwLabels = []
    trainingFileList = listdir('digits/trainingDigits')  # 导入所有训练文件
    numTrain = len(trainingFileList)  # 统计训练文件数目
    trainingMatrix = zeros((numTrain, 1024))
    for i in range(numTrain):
        fileNameStr = trainingFileList[i]  # 找处文件名
        fileStr = fileNameStr.split('.')[0]  # 文件名中点前的部分
        classNumStr = int(fileStr.split('_')[0])  # 文件名中_前的部分
        hwLabels.append(classNumStr)  # 标签——与文件中数字一致的,文件名中的数字
        trainingMatrix[i, :] = imgToVector('digits/trainingDigits/%s' % fileNameStr)

    im = Image.open(filename) #读入图片
    out = im.resize((32, 32), Image.ANTIALIAS) #压缩为32x32
    out = out.convert("L") #转化黑白图片 
    data = out.getdata() #获得像素点数据
    data = np.array(data, dtype='int') #转化为数组
    data[data < 255] = int(0)   #设为0
    data[data > 1] = int(1)  #255为黑,设为1
    mMat = np.reshape(data, (32, 32))
    np.savetxt("5.txt", mMat, "%d") #数据输到文件5.txt
    classifierResult = classify0(data, trainingMatrix, hwLabels, 10)
    return classifierResult

测试程序

classifierResult = kNN.classifyPicture('digits/5.jpeg') 
print(classifierResult)

运行结果

5
posted @ 2018-04-20 22:51  Liupeng_Wang  阅读(573)  评论(0编辑  收藏  举报