任务描述:

        在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-近邻算法的优化版,可以节省大量的计算开销。
 

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐