手写字符集
训练样本:trainingDigits
测试样本:testDigits
用到的库:
#需要的库
from numpy import *
import numpy as np #支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。
import operator #提供了一系列的函数操作
from os import listdir #Os库提供通用的、基本的操作系统交互功能
#数据处理:img2vector() :把一个测试/训练文件.txt转化为1个1行1024列的矩阵
def img2vector(filename):
returnVect = np.zeros((1, 1024))
# 创建1个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
#例如:
testVector = img2vector('testDigits/0_0.txt')
print(np.shape(testVector)) # (1, 1024)
print(testVector[0,0:31])
# [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 1. 1. 1. 0. 0. 0. 0. 0. 0. 0.0. 0. 0. 0. 0. 0. 0.]
##函数classfy0(),调用时传入classify0(vectorUnderTest当前测试文件(1×1024),trainingMat(训练总集合,m×1024),hwLabels,3)
tile()用法:python——numpy_jfoucti的博客-优快云博客
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
# shape()的功能是查看矩阵或者数组的维数,此处输出矩阵的行数,即m:文件个数
diffMat = tile(inX, (dataSetSize, 1)) - dataSet
# 传入dataSetSize=m
sqDiffMat = diffMat ** 2
# 求幂
sqDistances = sqDiffMat.sum(axis=1)
# axis=1就是将一个矩阵的每一行向量相加
distances = sqDistances ** 0.5
sortedDistIndicies = distances.argsort()
# argsort函数返回的是数组值从小到大的索引值
classCount = {}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
# 取测试与训练最近的三(k)个
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
# get()返回指定键的值,default=0——如果指定键的值不存在时,返回该默认值值0。
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1),reverse=True)
# classCount.items()将classCount字典分解为元组列表,operator.itemgetter(1)按照第二个元素的次序对元组进行排序,reverse=True是逆序,即按照从大到小的顺序排列
# 参考讲解:https://zhuanlan.zhihu.com/p/262568171
return sortedClassCount[0][0]
#handWrithingClassTest():
def handWrithingClassTest():
hwLabels = [] # 创建标签列表
trainingFileList = listdir('trainingDigits')
# listdir可以得到指定目录下的所有文件名,返回一个列表
m = len(trainingFileList)
# 返回文件个数
trainingMat = np.zeros((m, 1024))
# m行1024列的零矩阵
for i in range(m): # 获取训练样本的标签
fileNameStr = trainingFileList[i]
#得到每个文件名称,如 “0_0.txt”
fileStr = fileNameStr.split('.')[0]
# 把名字按.分成几个部分,装入列表,得到第[0]个部分,如0_0
classNumStr = int(fileStr.split('_')[0])
# 按下划线分,取第一个元素为作为标签
hwLabels.append(classNumStr)
# 将文件的标签加入标签列表
trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr)
# 把每个训练样本存入矩阵,%s既代入fileNameStr
errorCount = 0.0
#错误个数
testFileList = listdir('testDigits')
#获取所有测试样本
mTest = len(testFileList)
#得测试样本个数
##该循环将测试所有测试集,并给出答案
for i in range(mTest): #得测试样本标签
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
#将当前测试集存入矩阵1*1024
classifierResult = classify0(vectorUnderTest,trainingMat,hwLabels,3)
print ("the classifier came back with: %d, the read answer is:%d" %(classifierResult,classNumStr) )
if (classifierResult !=classNumStr):
errorCount += 1.0
'''
##该段注释代码将针对性输出判定结果,可自行选取样本进行测试
TestMat = img2vector('testDigits/3_23.txt')
fileNameStr = '3_23.txt'
#此处选取3_23.txt,可换成其他测试数据
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
classifierResult = classify0(TestMat, trainingMat, hwLabels, 3)
print("the classifier came back with: %d, the read answer is:%d" % (classifierResult, classNumStr))
'''
print("the total number of errors is %d" % errorCount)
print("the total error rate is: %f" % (errorCount / float(mTest)))
handWrithingClassTest()