1.示例描述:
系统识别的数字为0-9。数字图像为32*32的二进制图像,目录trainingDigits中大约2000个样本用于训练算法,目录testDigits中大约有900个样本用于测试。
数字图像以二进制的形式存储在记事本中。数字图像的形式如下所示,文件以数字的标签命名,下面这个数字图像的命名为“0_1.txt”,表示数字0的第1个样本。
2.KNN分类算法识别数字的步骤如下:
1.从trainingDigits文件中将所有的二进制图像进行解析,解析成数据集dataSet和对应样本的分类标签labels。
2.测试算法,并计算错误率。对testDigits中的文件进行解析,使用KNN算法判别每个二进制文件代表什么数字,并于测试样本的原有标签做对比,计算算法的错误率。
3.算法中涉及的函数如下:
1.image2vector(filename):对二进制图像进行解析。
2.classify(inX,dataSet,labels,k):对测试样本inX进行分类。
3.handWritingClassTest():测试算法,计算算法的错误率。
4.代码实现:
from numpy import *
import operator
from os import listdir #用于获取目录中的文件名
#将32*32的二进制图像矩阵转换为1*1024的向量
def image2vector(filename):
returnVector=zeros((1,1024))
with open(filename) as file:
for i in range(32):
line=file.readline()
for j in range(32):
returnVector[0,32*i+j]=int(line[j])
return returnVector
#k-近邻算法
def classify(inX,dataSet,labels,k):
num=dataSet.shape[0] #数据集中的样本个数
diffMatrix=tile(inX,(num,1))-dataSet #将测试向量转换为dataSet的同型矩阵并与dataSet做差
#使用欧式距离公式求测试样本与训练集中样本的距离
sqDiffMatrix=diffMatrix**2
sqDistance=sqDiffMatrix.sum(axis=1)
distance=sqDistance**0.5
sortedDistIndicies=distance.argsort() #对距离进行排序,返回排序后的索引值
classCount={}
for i in range(k):
label=labels[sortedDistIndicies[i]]
classCount[label]=classCount.get(label,0)+1 #若字典中存在label键,则对应的值+1,如果不存在,则添加这个键设置为0并+1
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #按照字典中的值对字典进行降序排列
return sortedClassCount[0][0]
#手写数字识别的测试代码
def handWritingClassTest():
labels=[]
trainingFileList=listdir('trainingDigits') #获取训练集目录下的文件名
m=len(trainingFileList) #计算训练样本个数
dataSet=zeros((m,1024)) #初始化数据集
for i in range(m):
fileName=trainingFileList[i]
number=int(fileName.split('_')[0]) #number为每个样本的分类
labels.append(number)
dataSet[i,:]=image2vector('trainingDigits\%s'%fileName)
testFileList=listdir('testDigits')
mTest=len(testFileList)
error=0.0
for i in range(mTest):
fileName=testFileList[i]
number=int(fileName.split('_')[0])
testVector=image2vector('testDigits\%s'%fileName)
resultNumber=classify(testVector,dataSet,labels,3) #使用算法估计样本所属类别
if number!=resultNumber: #算法结果与样本的实际分类做对比
error+=1.0
print('the total number of errors is:',error)
print('the total error rate is:',error/mTest)
handWritingClassTest()
运行结果:
the total number of errors is: 10.0
the total error rate is: 0.010570824524312896
5.KNN算法分析:
1.算法执行效率低:算法需要为每个测试向量做大约2000次距离计算,每个距离计算包括了1024个维度浮点计算,总共要执行900次。此外,还需要为测试向量准备一定的存储空间。所以这个算法不仅耗时,而且需要不少的存储空间。
2.k-临近算法的另一个缺陷就是它无法给出任何数据的基础结构信息,因此我们无法得知平均实例样本和典型实例样本具体有什么特征。
3.k-近邻算法是分类数据最简单最有效的算法。