注:本文借鉴于《机器学习实战》这本书
对于KNN的介绍在这里就不详细说了,在我的另一篇文章有。简单来说,k-近邻算法采用测量不同特征值之间的距离方法进行分类。
1.K-近邻算法
优点:精度高、对异常值不敏感、无数据输入假定
缺点:计算复杂度高、空间复杂度高
适用数据范围:数值型和标称型
2.K-近邻算法一般流程
(1)收集数据:可以使用任何方法
(2)准备数据:距离计算所需要的数值,最好是结构化 的数据格式
(3)分析数据:可以使用任何方法
(4)训练数据:此步骤不适用于k-近邻算法
(5)测试数据:计算错误率
(6)使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理
3.对未知类别属性的数据集中的每个点依次执行以下操作:
(1)计算已知类别数据集中的点与当前点之间的距离
(2)按照距离递增次序排序
(3)选取与当前点距离最小的K个点
(4)确定前K个点所在类别的出现频率
(5)返回前K个点出现频率最高的类别作为当前点的预测类别
4.下面给出一些例子
(1)一个简单的预测
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
def creatDataSet():
group=array([ [1.0,1.1],[1.0,1.0],[0,0],[0,0.1] ])
labels=['A','A','B','B']
return group,labels
def classify(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
distance=sqDiffMat.sum(axis=1)**0.5
sortedDistIndicies=distance.argsort()
classCount={}
for i in range(k):
labelName=labels[sortedDistIndicies[i]]
classCount[labelName]=classCount.get(labelName,0)+1;
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
group,labels=creatDataSet()
print group
print labels
print classify([0,0],group,labels,3)
结果:
(2)分类:
from numpy import *
import operator
def classify(inMat,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(inMat,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
distance=sqDiffMat.sum(axis=1)**0.5
sortedDistIndicies=distance.argsort()
classCount={}
for i in range(k):
labelName=labels[sortedDistIndicies[i]]
classCount[labelName]=classCount.get(labelName,0)+1;
sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
return sortedClassCount[0][0]
def file2Mat(filename):
fr=open(filename)
arrayOLines=fr.readlines()
numberOfLines=len(arrayOLines)
returnMat=zeros((numberOfLines,6))
classLabelVector=[]
index=0
for line in arrayOLines:
line = line.strip()
listFromLine=line.split(' ')
returnMat[index,:]=listFromLine[0:6]
classLabelVector.append(int(listFromLine[-1]))
index+=1
return returnMat,classLabelVector;
def autoNorm(dataSet):
minVals=dataSet.min(0)
maxVals=dataSet.max(0)
ranges=maxVals-minVals
normMat=zeros(shape(dataSet))
size=normMat.shape[0]
normMat=dataSet-tile(minVals,(size,1))
normMat=normMat/tile(ranges,(size,1))
return normMat,minVals,ranges
def test(trainigSetFileName,testFileName):
trianingMat,classLabel=file2Mat(trainigSetFileName)
trianingMat,minVals,ranges=autoNorm(trianingMat)
testMat,testLabel=file2Mat(testFileName)
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('TrainSet.txt','TestSet.txt')
print("the error rate is :%f"%(errorRate))
结果:
结果不是很好,因为数据是我自己搞的。。。。
在这个编程过程中遇到了一些问题,在这里和大家分享以下,希望大家以后注意!
这是错误!
在将文本记录转换为Numpy的解析程序中,原书是listFromLine=line.split('\t'),为什么我这里没用这个呢?
这个是因为我的数据原因(我的数据的格式有问题不符合\t的要求)。所以以后用的时候要注意这个!
最后还说一个,python语言格式很主要!本人在编程时,格式搞错了怎么都找不到错,搞了半天!香菇!最后发现是多大了一个空格符!