机器学习实战之分类篇 一 k-近邻算法(高级应用:手写数字识别)

  • Post author:
  • Post category:其他



任务描述:





digits

目录下存在1934张手写数字训练数据集(trainSet,标签为文本_前数字)和946张手写数字测试训练集(testSet,真实值为标签文本_前数字),使用kNN算法对测试集数字进行识别。

部分图片内容如下:



实现步骤与上一节

机器学习实战之分类篇 一 k-近邻算法(从电影分类到海伦约会)

基本一致,都是将信息(图像)转换为向量,计算未知向量到训练数据集的前k个最近距离,通过频率得出识别类别。

使用sklearn机器学习算法库,其分类算法库目录

sklearn Classification

.在1.6.2节介绍了kNeighborsClassifier分类器。

API实例及介绍如下:

使用sklearn库的目的在于,该库算法底层进行了优化算法,而且像很多分类器一样,具有一致的参数接口和函数名,使用也极其方便。使用KNN算法的关键调用语句为:

#call the kNN classifier
from sklearn.neighbors import KNeighborsClassifier as kNN
#set parameters
neigh = kNN(n_neighbors = 3, algorithm = 'auto')
#train classifier
neigh.fit(trainMatrix, labels)
#claddifier prediction
predLabel = neigh.predict(vectorImg)

最终实现代码如下:

import operator
import numpy as np
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN

'''
Function :	img2vector(filename)
	Description :	to covert img(in filename) to vector
	Args :	filename
	Rets :	vectorImg
'''

def img2vector(filename):
	vectorImg = np.zeros((1, 1024))
	fr = open(filename)
	for i in range(32):
		line = fr.readline()
		for j in range(32):
			vectorImg[0, 32*i + j] = int(line[j])
	return vectorImg

'''
Function : train()
	Description :	use kNN to train and test digits
	Args :	None
	Rets :	None
'''
def train():
	labels = []
	trainSet = listdir('./digits/trainSet')
	numTrain = len(trainSet)
	trainMatrix = np.zeros((numTrain, 1024)) #32*32 img size
	for i in range(numTrain):
		filename = trainSet[i]
		label = int(filename.split('_')[0])
		labels.append(label)
		trainMatrix[i, :] = img2vector('./digits/trainSet/%s'%(filename))
	neigh = kNN(n_neighbors = 3, algorithm = 'auto')
	neigh.fit(trainMatrix, labels)
	testSet = listdir('./digits/testSet')
	errorCount = 0.0
	numTest = len(testSet)
	for i in range(numTest):
		filename = testSet[i]
		label = int(filename.split('_')[0])
		vectorImg = img2vector('./digits/testSet/%s'%(filename))
		predLabel = neigh.predict(vectorImg)
		print('label: %d  vs  predLabel: %d'%(label, predLabel))
		if(label != predLabel):
			errorCount += 1.0
	print('Error Rate : %f%%'%(errorCount / numTest * 100))

if __name__ == '__main__':
	train()

实验结果:


注:

实际使用这个算法时,算法的执行效率并不高。因为算法需要为每个测试向量做2000次距离计算,每个距离计算包括了1024个维度浮点运算,总计要执行900次,此外,我们还需要为测试向量准备2MB的存储空间。是否存在一种算法减少存储空间和计算时间的开销呢?

k决策树就是k-近邻算法的优化版,可以节省大量的计算开销。