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

来源:互联网 发布:软件靠流量赚钱 编辑:程序博客网 时间:2024/05/02 01:19
from numpy import *import osimport 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 resdef 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 returnVecdef 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

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


阅读全文
1 0
原创粉丝点击