【《机器学习实战》第2章读书笔记】手写数字识别系统剖析

用Python构建一个K近邻分类器,识别手写数字,其中书中给出的训练集数据1934个,测试集数据946个,

在没有交叉验证的情况下,最终的识别率为98.2%

手写数字经过图像处理之后,变成只由0、1构成32*32矩阵,存放在.txt文件中,如下图:



好了,详细剖析如下:

"""
用 k-nearest neighbors实现手写数字识别

"""
import os
import numpy as np

project_path = '/Users/lan2720/Documents/lan/machinelearninginaction/Ch02/digits/'

def img2vector(filename): #dateSet_path type: string--path
	#list_dir = os.listdir(dir)
	
	
	returnVector = np.zeros((1,1024))  #代表1行1024列
	"""
	创建一个(1,1024)全零向量,每读一行就将读到的内容赋值到这个向量中去,每一行都是纯数字,0或1,而不是string类型的
	"""
	"""
	numpy中二维:a = np.array([[x,x,x],[x,x,x],(x,x,x)])  一定要有外部的中括号---代表一个矩阵  每一行也是用[]包含
	       一维: a = np.array([x,x,x])

	     下标从0开始
	     numpy默认是形成float64型0.0  64位机
	"""
	fn = open(filename)

	for row in range(32):
		line = fn.readline()
		for column in range(32):
			returnVector[0][row*32+column] = int(line[column])
	
		
	fn.close()

	return returnVector

	#print line

def classify0(inX , dataSet , labels , k):   #此时dateSet给的是一个矩阵
	"""
	np.tile() : a = [1,2,3]
				则 a1 = np.tile(a , 2)  -->  [1,2,3,1,2,3]   此时是一个向量
				   a2 = np.tile(a, (1,2))  -->  [[1,2,3,1,2,3]]  与上一中的区别在于,这是个矩阵了,只有一行的矩阵
				   a3 = np.tile(a , (2,1,2))  -->  最前面那个2代表现在有2个矩阵了
	"""

	""".sort() : 把当前序列变得有序
	   sorted() : 原序列不变,返回一个排好序的序列,可以另赋值
	"""

	"""
	.shape  可以求出一个矩阵的维,多少行,多少列(row , column)
	.shape[0]   得到矩阵的行数
	.shape[1]   得到矩阵的列数
	"""

	
	"""思路:"""
	"""1、求出dataset是有多少行,才好将这个inX和每一行进行处理"""
	dataSetRow = dataSet.shape[0]
	"""2、将inX向量扩展成这么多行的,以便每行对应处理,用到np.tile(瓦片)"""
	diffMat = np.tile(inX , (dataSetRow , 1)) - dataSet  #dataSetRow行,1整个列,1个矩阵
	sqDiffMat = diffMat**2   #差的每一项都要平方
	"""3、将sqDiffMat按行求和,每一行代表着inX和数据集中每一个数据比较的结果"""
	sqDistance = sqDiffMat.sum(axis = 1)   #axis = 0 代表按列求和,  这个可以按行或列求和的sum,是numpy中的,所以需要.sum(axis = ...)
	# 按行求和之后的sqDistance是一个向量
	distance = sqDistance**0.5  #向量
	"""4、既然得到了距离,接下来就是排序了,找到距离最小的K个,
	这时希望有一个函数,能排序,且返回的是元素在原序列中的位置信息--这样就能用位置信息快速找到他们的label,方便接下来统计他们的label
	np.argsort()就可以返回位置信息
	"""
	sortedDistIndice = distance.argsort()
	"""5、得到位置信息之后,取前K个,统计前K个中哪个label最多"""
	countLabels = {}
	for i in range(k):
		voteLabel = labels[sortedDistIndice[i]]
		countLabels[voteLabel] = countLabels.get(voteLabel , 0) + 1  
	"""6、将得到的字典{(label , count)}按照count值排序,取count最大的,代表inX就最可能是这个label"""
	sortedLabels = sorted(countLabels.iteritems() , key = lambda aa: aa[1] , reverse = True)  # .iteritems()返回的(key ,value),则aa[1]代表的是按第1域value排序
	"""返回,注:sortedLabels还是一个dict"""
	return sortedLabels[0][0]

def createDateSet():
	group = np.array([[1.0,1.1],
					  [1.0,1.0],
					  [ 0 , 0 ],
					  [ 0 ,0.1]])

	labels = [ 'A' , 'A' , 'B' , 'B']
	return (group , labels)

"""但是如何让.txt文件中存储的数据变成一个matirx?"""

def handWritingClassTest():
	"""  /Users/lan2720/Documents/lan/machinelearninginaction/Ch02/digits/testDigits   """
	hwTrainLabels = []
	trainFileList = os.listdir(project_path + 'trainingDigits')
	"""1、提取每个样本的label---究竟是哪个数字,存到labels列表中"""
	trainDataNum = len(trainFileList)
	trainMat = np.zeros((trainDataNum , 1024))
	for i in range(trainDataNum):  #每处理一个txt文件,就将他的label取出,特征向量取出
		processed_filename = trainFileList[i].strip('.txt')
		label = int(processed_filename.split('_')[0])
		hwTrainLabels.append(label)
		trainMat[i,:] = img2vector(project_path + 'trainingDigits/' + trainFileList[i])  #第i行整体赋值

	"""接下来,处理测试集"""
	hwTestLabels = []
	testFileList = os.listdir( project_path + 'testDigits')
	testDataNum = len(testFileList)

	correctCount = 0
	#testMat = np.zeros((m,1024))
	for i in range(testDataNum):
		processed_filename = testFileList[i].strip('.txt')
		correctLabel = int(processed_filename.split('_')[0])
		feaVector = img2vector(project_path + 'testDigits/' + testFileList[i]) 
		resultLabel = classify0(feaVector , trainMat , hwTrainLabels , k = 5)
		if resultLabel == correctLabel:
			correctCount += 1

	"""计算正确率"""
	correctRate = correctCount/float(testDataNum)

	return (trainDataNum ,testDataNum , correctRate)


def main():
	(traindata, testdata, correctrate) = handWritingClassTest()
	print 'data for training: %s' % traindata
	print 'data for testing : %s' % testdata
	print 'Corerect Rate : %s%%' % (correctrate*100)





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值