1:算法是简单的叙述说明
由于训练数据样本和标签,为测试数据的示例,从最近的距离k训练样本,此k练样本中所属类别最多的类即为该測试样本的预測标签。
简称kNN。通常k是不大于20的整数,这里的距离通常是欧式距离。
2:python代码实现
创建一个kNN.py文件,将核心代码放在里面了。
(1) 创建数据
#创造数据集 def createDataSet(): group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) labels = ['A', 'A', 'B', 'B'] return group, labels
(2) 构照kNN分类器
#第一个kNN分类器 inX-測试数据 dataSet-样本数据 labels-标签 k-邻近的k个样本 def classify0(inX,dataSet, labels, k): #计算距离 dataSetSize = dataSet.shape[0] diffMat = tile(inX, (dataSetSize,1))- dataSet sqDiffMat = diffMat ** 2 sqDistances = sqDiffMat.sum(axis = 1) distances = sqDistances **0.5 sortedDistIndicies = distances.argsort() classCount = {} #选择距离最小的k个点 for i in range(k): voteIlabel = labels[sortedDistIndicies[i]] classCount[voteIlabel] = classCount.get(voteIlabel,0)+1 #排序 sortedClassCount = sorted(classCount.iteritems(), key = operator.itemgetter(1),reverse = True) return sortedClassCount[0][0]
代码解说:(a)tile函数 tile(inX, i);扩展长度 tile(inX, (i,j)) ;i是扩展个数,j是扩展长度。
如:
(b) python代码路径。须要导入os文件,os.getcwd()显示当前文件夹。os.chdir(‘’)改变文件夹,listdir()显示当前文件夹的全部文件。
此外假设改动了当前.py文件,须要在python shell中又一次载入该py文件(reload(kNN.py)),以确保更新的内容能够生效。否则python将继续使用上次载入的kNN模块。如:
(c)注意列表求平方,求和
如:
3:案例—约会站点
案例描写叙述:
(1) 从文本文件里解析数据
# 将文本记录到转换numPy的解析程序 def file2matrix(filename): #打开文件并得到文件行数 fr = open(filename) arrayOLines = fr.readlines() numberOfLines = len(arrayOLines) #创建返回的numPy矩阵 returnMat = zeros((numberOfLines, 3)) classLabelVector = [] index =0 #解析文件数据到列表 for line in arrayOLines: line = line.strip() listFormLine = line.split('\t') returnMat[index,:] = listFormLine[0:3] classLabelVector.append(int(listFormLine[-1])) index += 1 return returnMat, classLabelVector
代码解说:(a)首先使用函数line.strip()截取掉全部的回车字符,然后使用tab字符\t将上一步得到的整行数据切割成一个元素列表
(b)int(listFormLine[-1]);python中能够使用索引值-1表示列表中的最后一列元素。此外这里我们必须明白的通知解释器,告诉它列表中存储的元素值为整型。否则python语言会将这些元素当做字符串处理。
(2)使用画图工具matplotlib创建散点图—能够分析数据
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvTHU1OTcyMDM5MzM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" width="521" height="389" >
(3)归一化数值
为了防止特征值数量的差异对预測结果的影响(比方计算距离,量值较大的特征值影响肯定非常大)。我们将全部的特征值都归一化到[0,1]
#归一化特征值 def autoNorm(dataSet): minVals = dataSet.min(0); maxVals = dataSet.max(0); ranges = maxVals - minVals; normDataSet = zeros(shape(dataSet)) m = dataSet.shape[0] normDataSet = dataSet - tile(minVals, (m,1)) normDataSet = normDataSet/tile(ranges,(m,1)) return normDataSet, ranges, minVals
(4)測试代码
測试代码以90%的作为训练样本。10%的作为測试数据
#測试代码 def datingClassTest(): hoRatio = 0.10 #測试数据占的百分比 datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') 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' %(classifierResult, datingLabels[i]) if(classifierResult != datingLabels[i]): errorCount += 1.0 print "the total error rate is: %f " % (errorCount/float(numTestVecs))
(5)输入某人的信息。便得出对对方的喜欢程度
#输入某人的信息,便得出对对方喜欢程度的预測值 def classifyPerson(): resultList = ['not at all', 'in small doses', 'in large doses'] percentTats = float(raw_input("percentage of time spent playing video games? ")) ffMiles = float(raw_input("frequent flier miles earned per year? ")) iceCream = float(raw_input("liters of ice cream consumed per year? ")) datingDataMat, datingLabels = file2matrix('datingTestSet2.txt') normMat, ranges, minVals = autoNorm(datingDataMat) inArr = array([ffMiles, percentTats, iceCream]) classifierResult = classify0((inArr - minVals)/ranges, normMat, datingLabels,3) print 'You will probably like this person: ', resultList[classifierResult - 1]
代码解说:python中raw_input同意用户输入文本行命令并返回用户所输入的命令
4:案例—手写识别系统
这里能够将手写字符看做由01组成的32*32个二进制文件,然后转换为1*1024的向量即为一个训练样本。每一维即为一个特征值
(1) 将一个32*32的二进制图像转换成1*1024的向量
#将一个32*32的二进制图像矩阵转换成1*1024的向量 def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i in range(32): lineStr = fr.readline() for j in range(32): returnVect[0, 32*i+j] = int(lineStr[j]) return returnVect
(2) 手写识别系统測试代码
#手写识别系统測试代码 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] classStr = int(fileStr.split('_')[0]) hwLabels.append(classStr) #測试例子标签 trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr) testFileList = listdir('testDigits') errorCount = 0.0 mTest = len(testFileList) for i in range(mTest): fileNameStr = testFileList[i] fileStr = fileNameStr.split('.')[0] classStr = 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' % (classifierResult, classStr) if(classifierResult != classStr): errorCount += 1.0 print "\nthe total numbers of errors is : %d" % errorCount print "\nthe total error rate is: %f" % (errorCount/float(mTest))
注明:1:本笔记来源于书籍<机器学习实战>
2:kNN.py文件及笔记所用数据在这下载(http://download.csdn.net/detail/lu597203933/7653991).
作者:小村长 出处:http://blog.csdn.net/lu597203933 欢迎转载或分享。但请务必声明文章出处。 (新浪微博:小村长zack, 欢迎交流! )
版权声明:本文博客原创文章,博客,未经同意,不得转载。