《机器学习实战二》K近邻学习之手写数字识别及检测识别错误率

使用k-近邻的手写识别系统算法实现步骤

  1. 收集数据
  2. 准备数据
  3. 分析数据
  4. 训练数据
  5. 测试算法
  6. 使用算法

首先还是按照书上的例子,将训练集和测试集下载到本地,
此次只是为了测试之前写的识别器的错误率,并没有实际对手写字体进行识别,不过看了学长的博客,也算是把识别的代码写了一些,把jpg格式的手写数字转换为txt格式的,其实就是求出图像相应灰度值,然后写上对应的asscii_char 01数字 如图
这里写图片描述这里写图片描述
这里写图片描述
87的由于写的比较细,看起来效果不是太好

下面第一步(我没有添加到之前写的knn.py文件中,直接在jupyter交互环境下写的)

#手写数字识别系统的测试代码
from numpy import *
import knn
import operator
from os import listdir
filename2 = "数据集/trainingDigits"
testDigitFile = "数据集/testDigits"
import time



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


#def hadwritingClassTest():
hwLabels = []
#将该含有训练集目录中所有需要训练的数据列出来
trainingFileList = listdir(filename2)
trainingFileList
#获取文件数量
m = len(trainingFileList)
m
#创建一个m行1024列的ndarray矩阵
trainingMat = zeros((m,1024))
trainingMat
for i in range(m):
    #将文件目录中每个txt文件都导出来
    if trainingFileList[i] ==".ipynb_checkpoints":
        continue
    fileNameStr = trainingFileList[i]
#     print(fileNameStr)
    fileStr = fileNameStr.split('.')[0]
    #print(fileStr)
    #为了将空行去掉 才能将字符型数字转化为int型数字
    if fileStr:
        classNumStr = int(fileStr.split('_')[0])
        #print(classNumStr)
    #将数字添加到数组中
    hwLabels.append(classNumStr)
    #print('数据集/trainingDigits/%s'%fileNameStr)
    trainingMat[i,:] = img2vector('数据集/trainingDigits/%s'%fileNameStr)#将对应目录添加到矩阵中
#print(trainingMat)

#获取到测试集
testFileList = listdir(testDigitFile)
#print(testFileList)
#统计错误率
errorCount = 0.0
mTest = len(testFileList)
#print(mTest) #'''获取到的测试集的数据长度 946'''

t1 = time.time()
for i in range(mTest):
    fileNameStr = testFileList[i]
#     print(fileNameStr)
    fileStr = fileNameStr.split('.')[0]
    #print(fileStr)
    classNumStr = int(fileStr.split('_')[0])
    #print(classNumStr)
    vectorUnderTest = img2vector('数据集/testDigits/%s' % fileNameStr)
    #使用分类器进行分类
    classifierResult = knn.classify(vectorUnderTest,trainingMat,hwLabels,3)
    #print("分类器测试的结果是:",classifierResult,"真正的结果是:",classNumStr)
    if (classifierResult != classNumStr):
        errorCount += 1.0
t2 = time.time()


print("分类器分类的错误个数是%s"%errorCount)
print("手写字体识别错误率是:%f" % (errorCount/float(mTest)))
print("所花费的时间为:%.2fmin,%.4fs" % ((t2-t1)//60,(t2-t1)%60))

#结果 
'''
    分类器分类的错误个数是10.0
    手写字体识别错误率是:0.010571
    所花费的时间为:0.00min,21.5465s
    主要原因是7和9,7和1之间不好判断
    可以改变k的值重新调整错误率,也可以使用交叉验证法修改测试集来验证
    缺点,:效率太低,耗时长,每个测试向量计算月2000次欧式距离,每个距离计算1024个维度浮点运算,全部测试赝本有946次
    所以耗时才那么长

'''


至于分类器代码,就不再这在写一遍了,之前我写的改进约会网站的配对实例里面都有的。

下面是对手写数字进行jpg图像转换为txt格式的,

#将手写数字 jpg格式的转化为只有0和1表示的txt文档表示
from PIL import Image
import argparse

#代码核心的思想是怎样求出对应图片灰度值后填充自己规定的ascii_char
ascii_char = '10'

#核心代码,按照灰度值转化成ascii_char值
def select_ascii_char(r,g,b):
    #获取灰度值
    gray = int((19595 * r + 38469 *g + 7472 * b)>> 16)#位运算 右移一位相当于除以2
    unit = 256.0/len(ascii_char)
    #print(gray)
    return ascii_char[int(gray/unit)]


#将原图自定义大小
def preimg(img_name, width, height):  
    img = Image.open(img_name)  
    print(img.size)  
    img = img.resize((width, height), Image.NEAREST)  
    print(img.size)  

    #将图像灰度化
    img.convert('L')  
    return img 


#将图像转换为矩阵格式
def img2char(img):  
    res = ''  
    width, height = img.size  
    for h in range(height):  
        for w in range(width):  
                res += select_ascii_char(*img.getpixel((w,h))[:3])  
        res += '\n'  
    return res  



if __name__ == '__main__':  
    img_name='87.png' 
    image = Image.open(img_name)

    width = 80  
    height = 50  
    file = 'test.txt'  
    img = preimg(img_name, width, height)  
    #img.show()
    pic_str = img2char(img)
    print(pic_str)

代码主要还是看学长的,然后自己分析了一下,加上了一点自己的理解。
http://blog.csdn.net/qq_33638791/article/details/54578560
学长写的还是要比我强的多的,其实这里面有些我还是不太明白,不过这都是次要的,用opencv搞着应该是比较容易的,回头学一下opencv

猜你喜欢

转载自blog.csdn.net/karmacode/article/details/78796201