参考网址:https://my.oschina.net/fengcunhan/blog/101281
http://www.cnblogs.com/geniferology/p/what_is_kNN_algorithm.html
kNN 的算法就是: 在已知的 data points 中,逐一点检视(把這每一點叫作 P): 1、首先计算「?」和 P 之间的距离 2、所有距离计算之后,将他们由小至大 sort 好 3、从 sort 好的序列,取最前的 k 个(即距离最接近「?」的 k 个点子) 4、对这 k 个点,读出他们的 label(颜色)是什么,这是问题中已经知道的 5、所有这些 labels(颜色),哪个出现最多? (亦即是说,最接近「?」的 k 个点子,它们最普遍是什么颜色?) 这出现次数最多的颜色,就是答案
距离算法也有很多种,可以选择一种即可。。
from numpy import * import operator def classify(inMat,dataSet,labels,k): dataSetSize=dataSet.shape[0] #KNN的算法核心就是欧式距离的计算,一下三行是计算待分类的点和训练集中的任一点的欧式距离 diffMat=tile(inMat,(dataSetSize,1))-dataSet sqDiffMat=diffMat**2 distance=sqDiffMat.sum(axis=1)**0.5 #接下来是一些统计工作 sortedDistIndicies=distance.argsort() #将x中的元素从小到大排列,提取其对应的index(索引) classCount={} for i in range(k): #k =3 训练数据最近的K个点看看这几个点属于什么类型 labelName=labels[sortedDistIndicies[i]] classCount[labelName]=classCount.get(labelName,0)+1; #get(labelName,0)如果存在键labelName,返回它的value,否则返回0 sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) return sortedClassCount[0][0] def file2Mat(testFileName,parammterNumber): fr=open(testFileName) lines=fr.readlines() lineNums=len(lines) resultMat=zeros((lineNums,parammterNumber)) classLabelVector=[] for i in range(lineNums): line=lines[i].strip() itemMat=line.split(' ') resultMat[i,:]=itemMat[0:parammterNumber] classLabelVector.append(itemMat[-1]) fr.close() return resultMat,classLabelVector; #为了防止某个属性对结果产生很大的影响,所以有了这个优化,比如:10000,4.5,6.8 10000就对结果基本起了决定作用 def autoNorm(dataSet): #dataset[n*3] minVals=dataSet.min(0) #数组每列的最小值 minVals[1*3] maxVals=dataSet.max(0) #数组每列的最小值 ranges=maxVals-minVals normMat=zeros(shape(dataSet)) #全零数组(与原数据数组大小一致) size=normMat.shape[0] #列数 normMat=dataSet-tile(minVals,(size,1)) #tile(minVals,(size,1))是等同于dataset大小的n*3数组 normMat=normMat/tile(ranges,(size,1)) #差距除以范围:比率? return normMat,minVals,ranges def test(trainigSetFileName,testFileName): trianingMat,classLabel=file2Mat(trainigSetFileName,3) trianingMat,minVals,ranges=autoNorm(trianingMat) #正则矩阵每个数据减去最小值除以数据变化范围宽度 testMat,testLabel=file2Mat(testFileName,3) testSize=testMat.shape[0] #取第一列的维度 errorCount=0.0 for i in range(testSize): #测试集一个一个数据测试 result=classify((testMat[i]-minVals)/ranges,trianingMat,classLabel,3) if(result!=testLabel[i]): errorCount+=1.0 errorRate=errorCount/(float)(len(testLabel)) return errorRate; if __name__=="__main__": errorRate=test('train.txt','test.txt') print("the error rate is :%f"%(errorRate))
训练集&测试集特点(最后一列是标签):
40920 8.326976 0.953952 3 14488 7.153469 1.673904 2 26052 1.441871 0.805124 1 75136 13.147394 0.428964 1 38344 1.669788 0.134296 1 72993 10.141740 1.032955 1 35948 6.830792 1.213192 3 42666 13.276369 0.543880 3 67497 8.631577 0.749278 1 35483 12.273169 1.508053 3