机器学习实战笔记(Python实现)-02-k近邻算法(kNN)
2017-10-14 15:35
736 查看
k近邻算法(kNN)
本博客来源于CSDN:http://blog.csdn.net/niuwei22007/article/details/49703719
本博客源代码下载地址:CSDN免费下载、GitHub下载地址
均带有详细注释和测试数据
今天学习了《机器学习实战》这本书介绍的第一个机器学习算法—k近邻算法。书中介绍它对于分类非常有效,比如书中的例子是对电影的题材进行分类。
下面来看一下书上对这个算法的原理介绍:存在一个训练样本集,并且每个样本都存在标签(有监督学习)。输入没有标签的新样本数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出与样本集中特征最相似的数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,而且k通常不大于20。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
要解决给定一部电影,判断其属于哪一种电影这个问题,就需要知道这个未知电影存在多少个打斗镜头和接吻镜头,如上图所示,问号位置所代表的两种镜头次数分别是多少?
下面我们来看一下图中电影的特征值,如下表:
相信看过数据以后,即使不知道未知电影(?)属于哪一种类型,但是可以通过某个计算方法计算出来。
第一步:首先计算未知电影与已知电影的相似度(抽象距离--相似度越小,距离越远)。具体如何计算暂且不考虑。下面看一下相似度列表:
第二步:再将相似度列表排序,选出前k个最相似的样本。此处我们假设k=3,将上表中的相似度进行排序后前3分别是:He’s
Not Really into Dudes,Beautiful Woman,California
Man。
第三步:统计最相似样本的分类。此处很容易知道这3个样本均为爱情片。
第四步:将分类最多的类别作为未知电影的分类。那么我们就得出结论,未知电影属于爱情片。
下面贴一下书上总结的k近邻算法的一般流程:
第三节就是按照第二节中描述实现的算法。但是这只是最简单的分类,当遇到特征值相差很大的时候,分类效果就不好了。比如,原来的dataSet中有一个这样的样本:[1, 10000]。同时输入样本仍然为第三节中测试的[0.1,
0.1]。所以很明显,当求这两个样本之间的距离的时候就出问题,由于那个10000太大,对最终的结果影响最大,其他的0.1和1可以忽略不计了。因此就用到了数值归一化。如果还有不太清楚地,百度一下。详细实现看代码,有详细注释。
改进二:从文件中读入数据
要做一个稍微复杂一点的测试,就需要多准备点样本数据,而在第三节中,训练样本只有4个,而且是固定生成的。在新的算法里边加入了可以从文件中读取训练数据。代码有详细注释。
k近邻算法的另外一个缺陷是它无法给出任何数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。(就是说k近邻算法只能是单纯的比较样本特征值之间的大小关系,给出样本之间的欧氏距离,并不能给出这些特征数据的内在含义。还是比较抽象!用一句不太恰当的描述是:k近邻算法只是知道两个样本之间的有区别,长得像不像,机械的区分样本之间的差别,没有类似于人的理解能力。)
本博客来源于CSDN:http://blog.csdn.net/niuwei22007/article/details/49703719
本博客源代码下载地址:CSDN免费下载、GitHub下载地址
均带有详细注释和测试数据
今天学习了《机器学习实战》这本书介绍的第一个机器学习算法—k近邻算法。书中介绍它对于分类非常有效,比如书中的例子是对电影的题材进行分类。
一、算法原理
算法原理是什么?允许我不严谨的说一下:首先有一堆有标签的样本,比如有一堆各种各样的鸟(样本集),我知道各种鸟的不同外貌(特征),比如羽毛颜色、有无脚蹼、身体重量、身体长度以及最重要的它属于哪一种鸟(类别/标签);然后给我一只不是这堆鸟中的一只鸟(测试样本),让我观察了它的羽毛颜色等后,让我说出它属于哪一种鸟?我的做法是:遍历之前的一堆鸟,分别比较每一只鸟的羽毛颜色、身体重量等特征与给定鸟的相应特征,并给出这两只鸟的相似度。最终,从那一堆鸟中找出相似度最大的前k只,然后统计这k只鸟的分类,最后把分类数量最多的那只鸟的类别作为给定鸟的类别。虽然结果不一定准确,但是是有理论支持的,那就是概率论,哈哈。下面来看一下书上对这个算法的原理介绍:存在一个训练样本集,并且每个样本都存在标签(有监督学习)。输入没有标签的新样本数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取出与样本集中特征最相似的数据(最近邻)的分类标签。一般来说,我们只选择样本数据集中前k个最相似的数据,这就是k-近邻算法中k的出处,而且k通常不大于20。最后选择k个最相似数据中出现次数最多的分类,作为新数据的分类。
二、如何解决问题
没接触过的同学应该能懂了吧。书中的举例是对电影的题材进行分类:爱情片or动作片。依据电影中打斗镜头和接吻镜头的数量。下面来看一下如何用kNN来解决这个问题。要解决给定一部电影,判断其属于哪一种电影这个问题,就需要知道这个未知电影存在多少个打斗镜头和接吻镜头,如上图所示,问号位置所代表的两种镜头次数分别是多少?
下面我们来看一下图中电影的特征值,如下表:
相信看过数据以后,即使不知道未知电影(?)属于哪一种类型,但是可以通过某个计算方法计算出来。
第一步:首先计算未知电影与已知电影的相似度(抽象距离--相似度越小,距离越远)。具体如何计算暂且不考虑。下面看一下相似度列表:
第二步:再将相似度列表排序,选出前k个最相似的样本。此处我们假设k=3,将上表中的相似度进行排序后前3分别是:He’s
Not Really into Dudes,Beautiful Woman,California
Man。
第三步:统计最相似样本的分类。此处很容易知道这3个样本均为爱情片。
第四步:将分类最多的类别作为未知电影的分类。那么我们就得出结论,未知电影属于爱情片。
下面贴一下书上总结的k近邻算法的一般流程:
三、用python实现kNN算法之简单分类
#coding=UTF8 from numpy import * import operator def createDataSet(): """ 函数作用:构建一组训练数据(训练样本),共4个样本 同时给出了这4个样本的标签,及labels """ group = array([ [1.0, 1.1], [1.0, 1.0], [0. , 0. ], [0. , 0.1] ]) labels = ['A', 'A', 'B', 'B'] return group, labels def classify0(inX, dataset, labels, k): """ inX 是输入的测试样本,是一个[x, y]样式的 dataset 是训练样本集 labels 是训练样本标签 k 是top k最相近的 """ # shape返回矩阵的[行数,列数], # 那么shape[0]获取数据集的行数, # 行数就是样本的数量 dataSetSize = dataset.shape[0] """ 下面的求距离过程就是按照欧氏距离的公式计算的。 即 根号(x^2+y^2) """ # tile属于numpy模块下边的函数 # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2] # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2], # [0, 1, 2, 0, 1, 2]] # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]], # [[0, 1, 2, 0, 1, 2]]] # 上边那个结果的分开理解就是: # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的 # 然后C包含1个元素,即C=[E],同理D=[E] # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的 # F就是A了,基础元素 # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]] # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。 # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离 # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较; # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。 # 比如inX = [0,1],dataset就用函数返回的结果,那么 # tile(inX, (4,1))= [[ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0]] # 作差之后 # diffMat = [[-1.0,-0.1], # [-1.0, 0.0], # [ 0.0, 1.0], # [ 0.0, 0.9]] diffMat = tile(inX, (dataSetSize, 1)) - dataset # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。 # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。 # sqDiffMat = [[1.0, 0.01], # [1.0, 0.0 ], # [0.0, 1.0 ], # [0.0, 0.81]] sqDiffMat = diffMat ** 2 # axis=1表示按照横轴,sum表示累加,即按照行进行累加。 # sqDistance = [[1.01], # [1.0 ], # [1.0 ], # [0.81]] sqDistance = sqDiffMat.sum(axis=1) # 对平方和进行开根号 distance = sqDistance ** 0.5 # 按照升序进行快速排序,返回的是原数组的下标。 # 比如,x = [30, 10, 20, 40] # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3] # 那么,numpy.argsort(x) = [1, 2, 0, 3] sortedDistIndicies = distance.argsort() # 存放最终的分类结果及相应的结果投票数 classCount = {} # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数 for i in range(k): # index = sortedDistIndicies[i]是第i个最相近的样本下标 # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B') voteIlabel = labels[sortedDistIndicies[i]] # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0 # 然后将票数增1 classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 把分类结果进行排序,然后返回得票数最多的分类结果 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] if __name__== "__main__": # 导入数据 dataset, labels = createDataSet() inX = [0.1, 0.1] # 简单分类 className = classify0(inX, dataset, labels, 3) print 'the class of test sample is %s' %className
四、用python实现kNN算法之改进分类
#coding=UTF8 from numpy import * import operator from os import listdir def classify0(inX, dataset, labels, k): """ inX 是输入的测试样本,是一个[x, y]样式的 dataset 是训练样本集 labels 是训练样本标签 k 是top k最相近的 """ # shape返回矩阵的[行数,列数], # 那么shape[0]获取数据集的行数, # 行数就是样本的数量 dataSetSize = dataset.shape[0] """ 下面的求距离过程就是按照欧氏距离的公式计算的。 即 根号(x^2+y^2) """ # tile属于numpy模块下边的函数 # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2] # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2], # [0, 1, 2, 0, 1, 2]] # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]], # [[0, 1, 2, 0, 1, 2]]] # 上边那个结果的分开理解就是: # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的 # 然后C包含1个元素,即C=[E],同理D=[E] # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的 # F就是A了,基础元素 # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]] # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。 # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离 # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较; # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。 # 比如inX = [0,1],dataset就用函数返回的结果,那么 # tile(inX, (4,1))= [[ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0]] # 作差之后 # diffMat = [[-1.0,-0.1], # [-1.0, 0.0], # [ 0.0, 1.0], # [ 0.0, 0.9]] diffMat = tile(inX, (dataSetSize, 1)) - dataset # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。 # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。 # sqDiffMat = [[1.0, 0.01], # [1.0, 0.0 ], # [0.0, 1.0 ], # [0.0, 0.81]] sqDiffMat = diffMat ** 2 # axis=1表示按照横轴,sum表示累加,即按照行进行累加。 # sqDistance = [[1.01], # [1.0 ], # [1.0 ], # [0.81]] sqDistance = sqDiffMat.sum(axis=1) # 对平方和进行开根号 distance = sqDistance ** 0.5 # 按照升序进行快速排序,返回的是原数组的下标。 # 比如,x = [30, 10, 20, 40] # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3] # 那么,numpy.argsort(x) = [1, 2, 0, 3] sortedDistIndicies = distance.argsort() # 存放最终的分类结果及相应的结果投票数 classCount = {} # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数 for i in range(k): # index = sortedDistIndicies[i]是第i个最相近的样本下标 # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B') voteIlabel = labels[sortedDistIndicies[i]] # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0 # 然后将票数增1 classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 把分类结果进行排序,然后返回得票数最多的分类结果 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] def file2matrix(filename): """ 从文件中读入训练数据,并存储为矩阵 """ fr = open(filename) numberOfLines = len(fr.readlines()) #获取 n=样本的行数 returnMat = zeros((numberOfLines,3)) #创建一个2维矩阵用于存放训练样本数据,一共有n行,每一行存放3个数据 classLabelVector = [] #创建一个1维数组用于存放训练样本标签。 fr = open(filename) index = 0 for line in fr.readlines(): # 把回车符号给去掉 line = line.strip() # 把每一行数据用\t分割 listFromLine = line.split('\t') # 把分割好的数据放至数据集,其中index是该样本数据的下标,就是放到第几行 returnMat[index,:] = listFromLine[0:3] # 把该样本对应的标签放至标签集,顺序与样本集对应。 classLabelVector.append(int(listFromLine[-1])) index += 1 return returnMat,classLabelVector def autoNorm(dataSet): """ 训练数据归一化 """ # 获取数据集中每一列的最小数值 # 以createDataSet()中的数据为例,group.min(0)=[0,0] minVals = dataSet.min(0) # 获取数据集中每一列的最大数值 # group.max(0)=[1, 1.1] maxVals = dataSet.max(0) # 最大值与最小的差值 ranges = maxVals - minVals # 创建一个与dataSet同shape的全0矩阵,用于存放归一化后的数据 normDataSet = zeros(shape(dataSet)) m = dataSet.shape[0] # 把最小值扩充为与dataSet同shape,然后作差,具体tile请翻看 第三节 代码中的tile normDataSet = dataSet - tile(minVals, (m,1)) # 把最大最小差值扩充为dataSet同shape,然后作商,是指对应元素进行除法运算,而不是矩阵除法。 # 矩阵除法在numpy中要用linalg.solve(A,B) normDataSet = normDataSet/tile(ranges, (m,1)) return normDataSet, ranges, minVals def datingClassTest(): # 将数据集中10%的数据留作测试用,其余的90%用于训练 hoRatio = 0.10 datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] numTestVecs = int(m*hoRatio) errorCount = 0.0 for i in range(numTestVecs): classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) print "the classifier came back with: %d, the real answer is: %d, result is :%s" % (classifierResult, datingLabels[i],classifierResult==datingLabels[i]) if (classifierResult != datingLabels[i]): errorCount += 1.0 print "the total error rate is: %f" % (errorCount/float(numTestVecs)) print errorCount if __name__=="__main__" datingClassTest()改进一:数值归一化
第三节就是按照第二节中描述实现的算法。但是这只是最简单的分类,当遇到特征值相差很大的时候,分类效果就不好了。比如,原来的dataSet中有一个这样的样本:[1, 10000]。同时输入样本仍然为第三节中测试的[0.1,
0.1]。所以很明显,当求这两个样本之间的距离的时候就出问题,由于那个10000太大,对最终的结果影响最大,其他的0.1和1可以忽略不计了。因此就用到了数值归一化。如果还有不太清楚地,百度一下。详细实现看代码,有详细注释。
改进二:从文件中读入数据
要做一个稍微复杂一点的测试,就需要多准备点样本数据,而在第三节中,训练样本只有4个,而且是固定生成的。在新的算法里边加入了可以从文件中读取训练数据。代码有详细注释。
五、用python实现kNN算法之手写数字识别
识别手写数字,需要先把手写数字图片转换为相应的01矩阵格式,这里提供已经经过转换的数据文件。trainingDigits是2000个训练样本,testDigits是900个测试样本。#coding=UTF8 from numpy import * import operator from os import listdir def classify0(inX, dataset, labels, k): """ inX 是输入的测试样本,是一个[x, y]样式的 dataset 是训练样本集 labels 是训练样本标签 k 是top k最相近的 """ # shape返回矩阵的[行数,列数], # 那么shape[0]获取数据集的行数, # 行数就是样本的数量 dataSetSize = dataset.shape[0] # tile属于numpy模块下边的函数 # tile(A, reps)返回一个shape=reps的矩阵,矩阵的每个元素是A # 比如 A=[0,1,2] 那么,tile(A, 2)= [0, 1, 2, 0, 1, 2] # tile(A,(2,2)) = [[0, 1, 2, 0, 1, 2], # [0, 1, 2, 0, 1, 2]] # tile(A,(2,1,2)) = [[[0, 1, 2, 0, 1, 2]], # [[0, 1, 2, 0, 1, 2]]] # 上边那个结果的分开理解就是: # 最外层是2个元素,即最外边的[]中包含2个元素,类似于[C,D],而此处的C=D,因为是复制出来的 # 然后C包含1个元素,即C=[E],同理D=[E] # 最后E包含2个元素,即E=[F,G],此处F=G,因为是复制出来的 # F就是A了,基础元素 # 综合起来就是(2,1,2)= [C, C] = [[E], [E]] = [[[F, F]], [[F, F]]] = [[[A, A]], [[A, A]]] # 这个地方就是为了把输入的测试样本扩展为和dataset的shape一样,然后就可以直接做矩阵减法了。 # 比如,dataset有4个样本,就是4*2的矩阵,输入测试样本肯定是一个了,就是1*2,为了计算输入样本与训练样本的距离 # 那么,需要对这个数据进行作差。这是一次比较,因为训练样本有n个,那么就要进行n次比较; # 为了方便计算,把输入样本复制n次,然后直接与训练样本作矩阵差运算,就可以一次性比较了n个样本。 # 比如inX = [0,1],dataset就用函数返回的结果,那么 # tile(inX, (4,1))= [[ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0], # [ 0.0, 1.0]] # 作差之后 # diffMat = [[-1.0,-0.1], # [-1.0, 0.0], # [ 0.0, 1.0], # [ 0.0, 0.9]] diffMat = tile(inX, (dataSetSize, 1)) - dataset # diffMat就是输入样本与每个训练样本的差值,然后对其每个x和y的差值进行平方运算。 # diffMat是一个矩阵,矩阵**2表示对矩阵中的每个元素进行**2操作,即平方。 # sqDiffMat = [[1.0, 0.01], # [1.0, 0.0 ], # [0.0, 1.0 ], # [0.0, 0.81]] sqDiffMat = diffMat ** 2 # axis=1表示按照横轴,sum表示累加,即按照行进行累加。 # sqDistance = [[1.01], # [1.0 ], # [1.0 ], # [0.81]] sqDistance = sqDiffMat.sum(axis=1) # 对平方和进行开根号 distance = sqDistance ** 0.5 # 按照升序进行快速排序,返回的是原数组的下标。 # 比如,x = [30, 10, 20, 40] # 升序排序后应该是[10,20,30,40],他们的原下标是[1,2,0,3] # 那么,numpy.argsort(x) = [1, 2, 0, 3] sortedDistIndicies = distance.argsort() # 存放最终的分类结果及相应的结果投票数 classCount = {} # 投票过程,就是统计前k个最近的样本所属类别包含的样本个数 for i in range(k): # index = sortedDistIndicies[i]是第i个最相近的样本下标 # voteIlabel = labels[index]是样本index对应的分类结果('A' or 'B') voteIlabel = labels[sortedDistIndicies[i]] # classCount.get(voteIlabel, 0)返回voteIlabel的值,如果不存在,则返回0 # 然后将票数增1 classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 # 把分类结果进行排序,然后返回得票数最多的分类结果 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] def file2matrix(filename): """ 从文件中读入训练数据,并存储为矩阵 """ fr = open(filename) numberOfLines = len(fr.readlines()) #获取 n=样本的行数 returnMat = zeros((numberOfLines,3)) #创建一个2维矩阵用于存放训练样本数据,一共有n行,每一行存放3个数据 classLabelVector = [] #创建一个1维数组用于存放训练样本标签。 fr = open(filename) index = 0 for line in fr.readlines(): # 把回车符号给去掉 line = line.strip() # 把每一行数据用\t分割 listFromLine = line.split('\t') # 把分割好的数据放至数据集,其中index是该样本数据的下标,就是放到第几行 returnMat[index,:] = listFromLine[0:3] # 把该样本对应的标签放至标签集,顺序与样本集对应。 classLabelVector.append(int(listFromLine[-1])) index += 1 return returnMat,classLabelVector def autoNorm(dataSet): """ 训练数据归一化 """ # 获取数据集中每一列的最小数值 # 以createDataSet()中的数据为例,group.min(0)=[0,0] minVals = dataSet.min(0) # 获取数据集中每一列的最大数值 # group.max(0)=[1, 1.1] maxVals = dataSet.max(0) # 最大值与最小的差值 ranges = maxVals - minVals # 创建一个与dataSet同shape的全0矩阵,用于存放归一化后的数据 normDataSet = zeros(shape(dataSet)) m = dataSet.shape[0] # 把最小值扩充为与dataSet同shape,然后作差,具体tile请翻看 第三节 代码中的tile normDataSet = dataSet - tile(minVals, (m,1)) # 把最大最小差值扩充为dataSet同shape,然后作商,是指对应元素进行除法运算,而不是矩阵除法。 # 矩阵除法在numpy中要用linalg.solve(A,B) normDataSet = normDataSet/tile(ranges, (m,1)) return normDataSet, ranges, minVals def img2vector(filename): """ 将图片数据转换为01矩阵。 每张图片是32*32像素,也就是一共1024个字节。 因此转换的时候,每行表示一个样本,每个样本含1024个字节。 """ # 每个样本数据是1024=32*32个字节 returnVect = zeros((1,1024)) fr = open(filename) # 循环读取32行,32列。 for i in range(32): lineStr = fr.readline() for j in range(32): returnVect[0,32*i+j] = int(lineStr[j]) return returnVect def handwritingClassTest(): hwLabels = [] # 加载训练数据 trainingFileList = listdir('trainingDigits') m = len(trainingFileList) trainingMat = zeros((m,1024)) for i in range(m): # 从文件名中解析出当前图像的标签,也就是数字是几 fileNameStr = trainingFileList[i] fileStr = fileNameStr.split('.')[0] #take off .txt classNumStr = int(fileStr.split('_')[0]) hwLabels.append(classNumStr) trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr) # 加载测试数据 testFileList = listdir('testDigits') #iterate through the test set errorCount = 0.0 mTest = len(testFileList) for i in range(mTest): fileNameStr = testFileList[i] fileStr = fileNameStr.split('.')[0] #take off .txt classNumStr = int(fileStr.split('_')[0]) vectorUnderTest = img2vector('testDigits/%s' % fileNameStr) classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3) print "the classifier came back with: %d, the real answer is: %d, The predict result is: %s" % (classifierResult, classNumStr, classifierResult==classNumStr) if (classifierResult != classNumStr): errorCount += 1.0 print "\nthe total number of errors is: %d / %d" %(errorCount, mTest) print "\nthe total error rate is: %f" % (errorCount/float(mTest)) if __name__== "__main__": handwritingClassTest()
六、小结
引用原话:k近邻算法是分类数据最简单最有效的算法。k紧邻算法必须保存全部数据集,如果训练数据集很大,必须使用大量的存储空间。此外,由于必须对数据集中的每个数据计算距离值,实际使用时可能非常耗时。(这些是很容易理解的)k近邻算法的另外一个缺陷是它无法给出任何数据的基础结构信息,因此我们也无法知晓平均实例样本和典型实例样本具有什么特征。(就是说k近邻算法只能是单纯的比较样本特征值之间的大小关系,给出样本之间的欧氏距离,并不能给出这些特征数据的内在含义。还是比较抽象!用一句不太恰当的描述是:k近邻算法只是知道两个样本之间的有区别,长得像不像,机械的区分样本之间的差别,没有类似于人的理解能力。)
相关文章推荐
- 机器学习实战笔记(Python实现)-02-k近邻算法(kNN)
- 机器学习实战笔记(Python实现)-02-k近邻算法(kNN)
- 机器学习实战笔记(Python)-01-K近邻算法(KNN)
- 机器学习实战 KNN算法 python3实现
- 机器学习实战2:k近邻算法KNN(python)
- 【机器学习实战-kNN:约会网站约友分类】python3实现-书本知识【2】
- 机器学习实战笔记(Python实现)-01-机器学习实战
- 机器学习实战笔记(Python实现)-07-模型评估与分类性能度量
- Python机器学习实战笔记之KNN算法
- 【机器学习实战-kNN:手写识别】python3实现-书本知识【3】
- 机器学习实战笔记(Python实现)-01-机器学习实战
- 机器学习实战python3 K近邻(KNN)算法实现
- 机器学习实战_kNN算法python3.6实现与理解
- 机器学习实战笔记(Python实现)-09-树回归
- 【机器学习系列】kNN(k近邻算法)的python实现
- 【机器学习实战-kNN(k-近邻)】python3实现-书本知识【1】
- 机器学习实战笔记(四):Logist线性回归算法的Python实现
- 步步学习之用python实战机器学习1-kNN (K-NearestNeighbors)算法(a)
- 机器学习实战学习1:python实现KNN
- Python实战之KNN实现