一.背景简要说明
书中假设待识别的数字已经使用图形处理软件将其处理为32*32的黑白图像,并将图片转换为文本格式。如下图代表数字0:
每个数字的训练样本大概有200个,每个数字的测试样本大概有100个,分别放在trainingDigits和testDigits中。
二.模块代码及注释
from numpy import *
from os import listdir
import operator
import time
#k-NN简单实现函数
def classify0(inX,dataSet,labels,k):
#求出样本集的行数,也就是labels标签的数目
dataSetSize = dataSet.shape[0]
#构造输入值和样本集的差值矩阵
diffMat = tile(inX,(dataSetSize,1)) - dataSet
#计算欧式距离
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
#求距离从小到大排序的序号
sortedDistIndicies = distances.argsort()
#对距离最小的k个点统计对应的样本标签
classCount = {}
for i in range(k):
#取第i+1近邻的样本对应的类别标签
voteIlabel = labels[sortedDistIndicies[i]]
#以标签为key,标签出现的次数为value将统计到的标签及出现次数写进字典
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#对字典按value从大到小排序
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#返回排序后字典中最大value对应的key
return sortedClassCount[0][0]
#----------------------------------------------------------------------------
#函数运行耗时统计函数
def time_me(fn):
def _wrapper(*args, **kwargs):
start = time.clock()
fn(*args, **kwargs)
print ("\n%s cost %s second"%(fn.__name__, time.clock() - start))
return _wrapper
#----------------------------------------------------------------------------
#图像转换函数(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
#----------------------------------------------------------------------------
#手写数字识别测试函数
@time_me
def handwritingClassTest():
#初始化类别标签为空列表
hwLabels = []
#列出给定目录下所有训练数据的文件名
trainingFileList = listdir('F:/machinelearninginaction/Ch02/trainingDigits')
#求训练数据数目
m = len(trainingFileList)
#初始化m个图像的训练矩阵
trainingMat = zeros((m,1024))
#遍历每一个训练数据
for i in range(m):
#取出一个训练数据的文件名
fileNameStr = trainingFileList[i]
#去掉该训练数据的后缀名.txt
fileStr = fileNameStr.split('.')[0]
#取出代表该训练数据类别的数字
classNumStr = int(fileStr.split('_')[0])