k-近邻算法3——手写识别系统
本节主要内容来自Peter Harrington的《Machine Learning in Action》的中文版本《机器学习实战》
示例3
本例中我们将构造一个使用k-近邻分类器的手写识别系统。为了降低难度,该分类器只识别数字0到9。
手写识别系统
- 收集数据:提供图像数据,由数字01构成32x32的文本数据
- 准备数据:编写函数
imgToVector()
,将图像数据转换为分类器可使用的向量格式 - 测试算法:编写函数
handWritingClassTest()
,用提供的测试数据测试分类器,统计错误率 - 使用算法:对网上找到的手写数字图片进行识别
收集数据
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