机器学习 & python k-近邻算法处理手写识别系统

参考自:《Machine Learning In Action》第二章


##########################################################


识别数字0-9。需要识别的数字已经使用图形处理软件,处理成具有相同的色彩和大小:宽高是32x32像素的黑白图像


程序所需文件:http://download.csdn.net/detail/u012005313/9191581


程序代码:

[python] view plain copy
print ?
  1. #!/usr/local/env python  
  2. #-*- coding: utf-8 -*-  
  3.   
  4. from numpy import * #导入科学计算包numpy模块  
  5. import operator  #导入运算符模块  
  6. from os import listdir #导入os模块  
  7.   
  8. #k-近邻分类算法  
  9. def classify0(inX, dataSet, labels, k): #4个输入参数分别为:用于分类的输入向量inX,输入的训练样本集dataSet,标签向量labels,选择最近邻居的数目k  
  10.     #计算距离  
  11.     dataSetSize=dataSet.shape[0]  #获取数据集的宽  
  12.     diffMat=tile(inX, (dataSetSize, 1))-dataSet #使用欧式距离度量,故将输入向量和数据集中各向量相减  
  13.     sqDiffMat=diffMat**2  #平方  
  14.     sqDistances=sqDiffMat.sum(axis=1)  #计算输入向量和数据集中各向量之间的差的平方和  
  15.     distances=sqDistances**0.5  #计算欧式距离  
  16.     #选择距离最小的k个点 计算所属类别的出现频率  
  17.     sortedDistIndicies=distances.argsort() #取得输入向量和数据集中各向量欧式距离的从小到大排序的下标值  
  18.     classCount={}  #定义一个空字典  
  19.     for i in range(k):  #取计算欧氏距离排序后最小的前k个值  
  20.         voteIlabel=labels[sortedDistIndicies[i]]  
  21.         classCount[voteIlabel]=classCount.get(voteIlabel,0)+1  
  22.     #排序 选择前k个点中出现最多的那一个类  
  23.     sortedClassCount=sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)  
  24.     return sortedClassCount[0][0]  
  25.   
  26. #将图像转换为向量  
  27. def img2vector(filename): #输入参数为文件名字符串  
  28.     returnVect=zeros((1,1024)) #初始化1x1024大小的向量  
  29.     fr=open(filename) #打开文件  
  30.     for i in range(32): #循环读取文件的前32行  
  31.         lineStr=fr.readline() #返回文件的一行数据  
  32.         for j in range(32): #读取每行的前32个字符值  
  33.             returnVect[032*i+j]=int(lineStr[j])  
  34.     return returnVect #返回数组  
  35.       
  36. #手写数字识别系统的测试代码  
  37. def handwritingClassTest():  
  38.     hwLabels=[]  
  39.     trainingFileList=listdir('digits/trainingDigits'#以列表形式返回path路径下的所有文件名  
  40.     m=len(trainingFileList) #文件的数量    
  41.     trainingMat=zeros((m, 1024))      
  42.     for i in range(m):   
  43.         #从文件名解析分类数字  
  44.         fileNameStr=trainingFileList[i]  
  45.         fileStr=fileNameStr.split('.')[0#例:0_0.txt  
  46.         classNumStr=int(fileStr.split('_')[0])  
  47.         hwLabels.append(classNumStr)  
  48.         trainingMat[i,:]=img2vector('digits/trainingDigits/%s'%fileNameStr)  
  49.     testFileList=listdir('digits/testDigits')  
  50.     errorCount=0.0  
  51.     mTest=len(testFileList)  
  52.     for i in range(mTest):  
  53.         fileNameStr=testFileList[i]  
  54.         fileStr=fileNameStr.split('.')[0]  
  55.         classNumStr=int(fileStr.split('_')[0])  
  56.         vectorUnderTest=img2vector('digits/testDigits/%s'%fileNameStr)  
  57.         classifierResult=classify0(vectorUnderTest, trainingMat, hwLabels, 3)  
  58.         print "the classifier came back with: %d, the real answer is: %d"%(classifierResult, classNumStr)  
  59.         if (classifierResult != classNumStr):  
  60.             errorCount += 1.0  
  61.     print "\nthe total number of errors is: %d"%errorCount  
  62.     print "\nthe total error rate is: %f"%(errorCount/float(mTest))  
#!/usr/local/env python
#-*- coding: utf-8 -*-

from numpy import * #导入科学计算包numpy模块
import operator  #导入运算符模块
from os import listdir #导入os模块

#k-近邻分类算法
def classify0(inX, dataSet, labels, k): #4个输入参数分别为:用于分类的输入向量inX,输入的训练样本集dataSet,标签向量labels,选择最近邻居的数目k
	#计算距离
	dataSetSize=dataSet.shape[0]  #获取数据集的宽
	diffMat=tile(inX, (dataSetSize, 1))-dataSet #使用欧式距离度量,故将输入向量和数据集中各向量相减
	sqDiffMat=diffMat**2  #平方
	sqDistances=sqDiffMat.sum(axis=1)  #计算输入向量和数据集中各向量之间的差的平方和
	distances=sqDistances**0.5  #计算欧式距离
	#选择距离最小的k个点 计算所属类别的出现频率
	sortedDistIndicies=distances.argsort() #取得输入向量和数据集中各向量欧式距离的从小到大排序的下标值
	classCount={}  #定义一个空字典
	for i in range(k):  #取计算欧氏距离排序后最小的前k个值
		voteIlabel=labels[sortedDistIndicies[i]]
		classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
	#排序 选择前k个点中出现最多的那一个类
	sortedClassCount=sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
	return sortedClassCount[0][0]

#将图像转换为向量
def img2vector(filename): #输入参数为文件名字符串
	returnVect=zeros((1,1024)) #初始化1x1024大小的向量
	fr=open(filename) #打开文件
	for i in range(32): #循环读取文件的前32行
		lineStr=fr.readline() #返回文件的一行数据
		for j in range(32): #读取每行的前32个字符值
			returnVect[0, 32*i+j]=int(lineStr[j])
	return returnVect #返回数组
	
#手写数字识别系统的测试代码
def handwritingClassTest():
	hwLabels=[]
	trainingFileList=listdir('digits/trainingDigits') #以列表形式返回path路径下的所有文件名
	m=len(trainingFileList) #文件的数量	
	trainingMat=zeros((m, 1024))	
	for i in range(m): 
		#从文件名解析分类数字
		fileNameStr=trainingFileList[i]
		fileStr=fileNameStr.split('.')[0] #例:0_0.txt
		classNumStr=int(fileStr.split('_')[0])
		hwLabels.append(classNumStr)
		trainingMat[i,:]=img2vector('digits/trainingDigits/%s'%fileNameStr)
	testFileList=listdir('digits/testDigits')
	errorCount=0.0
	mTest=len(testFileList)
	for i in range(mTest):
		fileNameStr=testFileList[i]
		fileStr=fileNameStr.split('.')[0]
		classNumStr=int(fileStr.split('_')[0])
		vectorUnderTest=img2vector('digits/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
	print "\nthe total number of errors is: %d"%errorCount
	print "\nthe total error rate is: %f"%(errorCount/float(mTest))

实际图像存储在digits目录下的两个子目录内:目录trainingDigits中包含了大约2000个例子,每个数字大约有200个样本;目录testDigits中包含了大约900个测试数据。

使用目录trainingDigits中的数据训练分类器,使用目录testDigits中的数据测试分类器的效果


首先编写函数img2vector,将图像转换为向量:该函数创建1x1024的Numpy数组,然后打开给定文件,循环读取文件的前32行,并将每行的头32个字符值存储在Numpy数组中,最后返回数组


你可能感兴趣的:(机器学习)