您的位置:首页 > 其它

【机器学习】Knn算法实现手写数字识别

2017-05-26 21:19 786 查看
from numpy import *
import os
import time

#inputX表示输入向量
#dataSet表示训练样本
#label表示训练样本的标签
#k是最近邻的参数,选最近k个
def kNNclassify(inputX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]#计算有几个训练数据,shape[0]计算出第一维度长度即列数,属于Python中operator模块的内置操作
#开始计算欧几里得距离
# 先将待分类项扩展成和数据集一样列数的dataSetSize行矩阵,再作差,得到差值矩阵
diffMat = tile(inputX, (dataSetSize,1)) - dataSet
# 差值矩阵平方 (x**2是x的二次方)
sqDiffMat = diffMat ** 2
# 计算每一行上元素的和
sqDistances = sqDiffMat.sum(axis=1)#矩阵每一行向量相加
# 开方得到欧拉距离矩阵
distances = sqDistances ** 0.5
sortedDistance = distances.argsort()
# 选择距离最小的k个点
#创建一个字典
classCount = {}
for i in range(k):
#取得第i个近邻的标签
voteLabel = labels[sortedDistance[i]]
#get(voteLabel,0)从字典中取键votelabel也就是数字多对应的出现次数若没有则取0然后加1;
classCount[voteLabel] = classCount.get(voteLabel,0) + 1
#返回字典中值最大的那个键
res = max(classCount)
return res

def img2vec(filename):
#创建一行1024列的矩阵(行向量)
returnVec = zeros((1,1024))
#读取文件
fr = open(filename)
for i in range(32):
#每次读取一行
lineStr = fr.readline()
for j in range(32):
#将每行元素存入行向量中
returnVec[0,32*i+j] = int(lineStr[j])
#返回每个文件转化为的行向量
return returnVec

def handwritingClassTest(trainingFloder,testFloder,K):
#定义序列
hwLabels = []
#获取训练集目录的内容放在列表中
trainingFileList = os.listdir(trainingFloder)
#计算出列表长度(训练集个数)
m = len(trainingFileList)
#m行1024列全是零的矩阵
trainingMat = zeros((m,1024))
for i in range(m):
#取第i个训练数据的目录文件名
fileName = trainingFileList[i]
#将文件名字符串由‘.’为分割点分割,取前面那部分类似于“0_3”
fileStr = fileName.split('.')[0]
#将filestr分割取前面数字部分即所代表的数字
classNumStr = int(fileStr.split('_')[0])
#将文件所代表的数字添加到hwlabels序列中
hwLabels.append(classNumStr)
#将训练集中每个文件转化为行向量,且存入矩阵trainingMat作为相应的行
trainingMat[i,:] = img2vec(trainingFloder+'/'+fileName)
#获取测试集目录的内容放在列表中
testFileList = os.listdir(testFloder)
#初始化错误个数为0
errorCount = 0.0
#计算出列表长度(测试集个数)
mTest = len(testFileList)
for i in range(mTest):
#获取测试的文件名
fileName = testFileList[i]
#将文件名去掉格式后缀
fileStr = fileName.split('.')[0]
#获取文件所代表的数字
classNumStr = int(fileStr.split('_')[0])
#将测试的数据装化为行向量
vectorUnderTest = img2vec(testFloder+'/'+fileName)
#将用于测试的行向量,训练出的矩阵模型,训练集所匹配的标签,以及K值传入KNN算出与谁近邻
classifierResult = kNNclassify(vectorUnderTest, trainingMat, hwLabels, K)
if classifierResult != classNumStr:
#如果识别出的和文件本身代表的不是一个则错误数加一
errorCount +=1
print(classifierResult,' ',classNumStr)
print("\nthe total number of tests is: %d" % mTest)    #输出测试总样本数
print("\nthe total number of error is: %d" %errorCount)#输出测试错误样本数
print("\nthe total error rate is: %f" %(errorCount/mTest)) #输出错误率
print("\nthe total accuracy is:%f"%(1-errorCount/mTest)) #输出正确率

def main():
t1 = time.clock()
handwritingClassTest('trainingDigits','testDigits',3)
t2 = time.clock()
print('Cost time: ',t2-t1)#输出耗时
if __name__=='__main__':
main()
使用的数据集在网盘上链接:http://pan.baidu.com/s/1dFaNCh7 密码:uhr9

数据集与上面代码放一个文件夹

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: