kNN算法,又名k邻近算法,简单的来说,就是通过测量不同特征值之间距离的方法进行分类。
算法的原理十分简单,举个例子,假设我们要通过”打斗镜头数“和接吻镜头数”这两个特征把电影分为爱情片和动作片,我们可以用一下步骤。
- 建立坐标系,其中x轴为打斗镜头数,y轴为接吻镜头数。
- 将训练集中所有的电影以点的形式画在坐标系中。
- 将新电影画在坐标系中。
- 测量新电影与其他电影之间的距离,并找出距离最近的k个点。
- 在这k个点中,若爱情片数量多,则新电影为爱情片,反之则为动作片
为使代码重复使用方便,我们将运算过程写在函数中,再将函数放置于python模块内。而非写在脚本中。
代码如下。主要是根据书改的,修改了变量的名称使可读性增加。
from numpy import *
import operator
def classify(inx,data,labels,k):
datasize = data.shape[0]
diffmat = tile(inx,(datasize,1))-data
sqdiff=diffmat ** 2
sqdist=sqdiff.sum(axis=1)
dists = sqdist**0.5
sorteddist = argsort(dists)
classcount={}
for i in range(k):
votelabel=labels[sorteddist[i]]
classcount[votelabel]=classcount.get(votelabel,0)+1
sortedcount=sorted(classcount.items(),key=operator.itemgetter(1),reverse=True)
return sortedcount[0][0]
def filetomat(filename):
fr=open(filename)
lines = fr.readlines()
linescount=len(lines)
res=zeros((linescount,3))
labels=[]
index = 0
for line in lines:
line = line.strip()
listfromline = line.split('\t')
res[index,:] = listfromline[0:3]
labels.append(int(listfromline[-1]))
index += 1
return res,labels
def norm(data):
mins = data.min(0)
maxs = data.max(0)
ranges = maxs-mins
res = zeros(shape(data))
m=data.shape[0]
res=data-tile(mins,(m,1))
res=res/tile(ranges,(m,1))
return res,ranges,mins
def test():
horatio = 0.1
data,labels = filetomat('datingTestSet2.txt')
normmat,ranges,mins = norm(data)
m = normmat.shape[0]
numtests = int(m*horatio)
errorcount = 0.0
for i in range(numtests):
classifyres = classify(normmat[i,:],normmat[numtests:m,:],labels[numtests:m],3)
print("分类结果:",classifyres,"正确答案:",labels[i])
if (classifyres != labels[i]):
errorcount+=1.0
print("平均出错率:",errorcount/float(numtests))
之后,在命令行中输入
import kNN
kNN.test()
即可对代码进行测试。