# coding=utf-8from numpy import *
from os import listdir
import operator # 運算符模塊,執行排序操作時將用到import matplotlib.pyplot as plt
import re,time# 圖像數據處理得到分類器可識別的格式defimg2vector(filename):# 創建一個行向量1*1024的數組,而不是單個1*1024的向量returnVect = zeros((1,1024))fr=open(filename,'r')for i in range(32):lineStr = fr.readline()for j in range(32):returnVect[0,32*i+j] = int(lineStr[j])#print returnVect[0,32*i+j]fr.close()return returnVect# 分類,參考上一篇KNN簡單實現defclassify0(inX, dataSet, labels, k):dataSetSize = dataSet.shape[0]diffMat = tile(inX, (dataSetSize,1)) - dataSetsqDiffMat = diffMat**2sqDistances = sqDiffMat.sum(axis=1)distances = sqDistances**0.5sortedDistIndicies = distances.argsort() classCount={} for i in range(k):voteIlabel = labels[sortedDistIndicies[i]]classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)return sortedClassCount[0][0]# 測試分類器的識別效果defhandwritingClassTest():hwLabels = []# listdir可以列出給定目錄下的文件名trainingFileList = listdir('trainingDigits')# 得到訓練集的文件個數m = len(trainingFileList)print'Number of training data sets:', m# 創建m行數組存放格式化后的訓練數據print'..training set Processing......'trainingMat = zeros((m,1024))for i in range(m):# 數字圖像的文件名,要提取出其代表的數字,即標簽 fileNameStr = trainingFileList[i]# 正則匹配#tt=re.match(r'(\d*)\_(\d*)(.txt)',fileNameStr).group(1)fileStr = fileNameStr.split('.')[0] classNumStr = int(fileStr.split('_')[0])# 得到標簽listhwLabels.append(classNumStr)#print hwLabels#得到訓練集數組,又學習了一種新的方法trainingMat[i,:] = img2vector('trainingDigits\%s' % fileNameStr)print'Number of trainingMat..',trainingMat.shape[0]print'..trainingset procesing end'# 列出測試集文件testFileList = listdir('testDigits') #iterate through the test seterrorCount = 0.0mTest = len(testFileList)print'Number of testing data sets:',mTestprint'..testing set Processing......'for i in range(mTest):fileNameStr = testFileList[i]fileStr = fileNameStr.split('.')[0] #take off .txtclassNumStr = int(fileStr.split('_')[0])vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)# 開始分類classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)print"the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr)if (classifierResult != classNumStr): errorCount += 1.0#換行注釋\nprint"\nthe total number of errors is: %d" % errorCountprint"\nthe total error rate is: %f" % (errorCount/float(mTest))if __name__== "__main__": start=time.time()handwritingClassTest()end=time.time()print'\nRunning time:',end-start
結果:
Number of training data sets: 1934
..training set Processing......
Number of trainingMat.. 1934
..trainingset procesing end
Number of testing data sets: 946
..testing set Processing......
the classifier came backwith: 0, thereal answer is: 0the classifier came backwith: 0, thereal answer is: 0the classifier came backwith: 0, thereal answer is: 0the classifier came backwith: 0, thereal answer is: 0the classifier came backwith: 0, thereal answer is: 0the classifier came backwith: 0, thereal answer is: 0
...,
the classifier came backwith: 9, thereal answer is: 9the classifier came backwith: 9, thereal answer is: 9the classifier came backwith: 9, thereal answer is: 9the classifier came backwith: 9, thereal answer is: 9the classifier came backwith: 9, thereal answer is: 9the classifier came backwith: 9, thereal answer is: 9the total numberof errors is: 11the total error rate is: 0.011628Running time: 29.5639998913
錯誤率為1.16%,耗時29
在其中遇到了一個問題: 就是使用open()函數時報錯: TypeError: an integer is required 查資料后: 錯誤是由于從os模塊引入了所有的函數導致的,即“from os import *”
os模塊下也有一個open函數,接受整型的文件描述符和打開模式,from os import *引入os模塊的open函數,覆蓋了python內建的open函數,導致錯誤。
修改from os import listdir 這行,即根據需要,指定引入os模塊下的函數,盡量不要使用from module import *方式引入模塊函數。