基于:ml in action
KNN算法原理:
训练样本集及其标签集
测试样本
计算与测试样本距离最近的K个训练样本
统计这K个训练样本的标签频率
选择频率最高的标签作为测试样本的标签
确定K的值:通过对样本的实验(多次和人工结合),取出误差最小的分类结果。一般小于20
距离:可以是欧氏距离,
归一化:
训练样本为向量,其每个属性的尺度差别很大时,比如X=[x1,x2..],x1属于[0,1],x2属于[1000,2000],
假定距离为欧式距离,样本为X1,X2,
则distance=sqrt((X11-X21)^2+(X12-X22)^2),显然属性x2的差最大值可取1000,其平方为1000*1000,而,x1属性的差最大值为1,其平方为1,则在distance中,x2属性所占比重就会很大,x1的影响可以忽略。
事实上,x1,x2属性的在distance中比重可能应当同样重要,这个时候,需要对x2属性进行放缩,使其尺度放缩到[0,1],一般对所有属性均放缩到[0,1]
公式:
newvalue=(oldvalue-minvalue)/(maxvalue-minvalue)
oldvalue:当前样本值(向量)
minvalue:训练集中对应属性的最小值向量
maxvalue:...最大值向量
优点:简单,
缺点:需要保存训练数据,每次都要计算N次距离,N为训练样本数。时间空间复杂度高
python代码
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
def generateDataset():
group=array([[1.0,1.1],[1.1,1.0],[0,0],[0,0.1]])
lables=['A','A','B','B']
return group,lables
def classify0(intX,dataSet,lables,k):
datasize=dataSet.shape[0]
diffMat=tile(intX,(datasize,1))-dataSet
distance=diffMat**2
sqrtdistance=distance.sum(1)
sqrtdistance=sqrtdistance**0.5
sortedDistanceIndex=sqrtdistance.argsort()
classsorted={}
for i in range(k):
votedlable=lables[sortedDistanceIndex[i]]
classsorted[votedlable]=classsorted.get(votedlable,0)+1
sortedclass=sorted(classsorted.items(),key=operator.itemgetter(1),reverse=True)
return sortedclass[0][0]
def file2matrix(filepath):
fr=open(filepath)
arrayOlines=fr.readlines()
numberoflines=len(arrayOlines)
returnMat=zeros((numberoflines,3))
vectorlables=[]
index=0
for line in arrayOlines:
line.strip()
listFromline=line.split('\t')
returnMat[index,:]=listFromline[0:3]
vectorlables.append(int(listFromline[-1]))
index+=1
return returnMat,vectorlables
def normMatrix(dataset):
rows=dataset.shape[0]
minval=dataset.min(0)
maxval=dataset.max(0)
maxsubmin=maxval-minval
dataset=(dataset-tile(minval,(rows,1)))/tile(maxsubmin,(rows,1))
return dataset,minval,maxsubmin
def plotdata(dataset,lables):
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(dataset[:,0],dataset[:,1],15.0*array(lables),15.0*array(lables))
fig.show()
(dataset,lables)=file2matrix("datingTestSet.txt")
dataset,minval,maxsubmin=normMatrix(dataset)
print (dataset)
#print (lables)
#print (minval)
#print (maxsubmin)
datasize=dataset.shape[0]
print(type(datasize))
print (datasize)
print (dataset[0,:])
traindata=dataset[0:datasize-10,:]
trainlable=lables[:datasize-10]
testdata=dataset[datasize-10:,:]
print (traindata.shape)
print (testdata.shape)
print (testdata)
testlable=lables[datasize-10:]
for i in range(9):
result=classify0(testdata[i],traindata,trainlable,3)
print ("result is ",result," real lable is ",testlable[i])