kNN算法的指导思想是“近朱者赤,近墨者黑”,由你的邻居来推断出你的类别。
1、指导思想
kNN算法的指导思想是“近朱者赤,近墨者黑”,由你的邻居来推断出你的类别。
计算步骤如下:
1)算距离:给定测试对象,计算它与训练集中的每个对象的距离(一般采用欧几里得距离)
2)找邻居:圈定距离最近的k个训练对象,作为测试对象的近邻
3)做分类:根据这k个近邻归属的主要类别,来对测试对象分类
2、距离或相似度的衡量
什么是合适的距离衡量?距离越近应该意味着这两个点属于一个分类的可能性越大。
觉的距离衡量包括欧式距离、夹角余弦等。
对于文本分类来说,使用余弦(cosine)来计算相似度就比欧式(Euclidean)距离更合适。
3、类别的判定
投票决定:少数服从多数,近邻中哪个类别的点最多就分为该类。
加权投票法:根据距离的远近,对近邻的投票进行加权,距离越近则权重越大(权重为距离平方的倒数)
优缺点
1、优点
简单,易于理解,易于实现,无需估计参数,无需训练
适合对稀有事件进行分类(例如当流失率很低时,比如低于0.5%,构造流失预测模型)
特别适合于多分类问题(multi-modal,对象具有多个类别标签),例如根据基因特征来判断其功能分类,kNN比SVM的表现要好
2、缺点
懒惰算法,对测试样本分类时的计算量大,内存开销大,评分慢
可解释性较差,无法给出决策树那样的规则。
注意:k值的选择一般小于样本的开放
简单,易于理解,易于实现,无需估计参数,无需训练
适合对稀有事件进行分类(例如当流失率很低时,比如低于0.5%,构造流失预测模型)
特别适合于多分类问题(multi-modal,对象具有多个类别标签),例如根据基因特征来判断其功能分类,kNN比SVM的表现要好
2、缺点
懒惰算法,对测试样本分类时的计算量大,内存开销大,评分慢
可解释性较差,无法给出决策树那样的规则。
注意:k值的选择一般小于样本的开放
example
下面模仿一下算法的过程
如上图所示 k=5
选取靠谱x的5个点,其中有4个点属于类别w1,1个属于类别w3,根据少数服从多数的原则,判断x的类型是w1
代码如下(python实现)
import csv
import random
import math
import operator
#导入数据集
def loadDataset(filename,split,trainingSet=[],testSet=[]):
with open(filename,'rb') as csvfile:
lines=csv.reader(csvfile)
dataset=list(lines)
print len(dataset)
for x in range(len(dataset)-1):
for y in range(4):
dataset[x][y]=float(dataset[x][y])
if random.random()<split:
trainingSet.append(dataset[x])
else:
testSet.append(dataset[x])
#计算欧几里得距离
def euclideanDistance(instance1,instance2,length):
distance=0
for x in range(length):
distance+=pow((instance1[x]-instance2[x]),2)
return math.sqrt(distance)
#拿到要判断实例的k个最近的邻居
def getNeighbors(trainingSet,testInstance,k):
distances=[]
length=len(testInstance)-1
for x in range(len(trainingSet)):
dist=euclideanDistance(testInstance,trainingSet[x],length)
distances.append((trainingSet[x],dist))
distances.sort(key=operator.itemgetter(1))
neighbors=[]
for x in range(k):
neighbors.append(distances[x][0])
return neighbors
#根据拿到的k个邻居中根据少数服从多数的原则,判定这个实例的类型
def getResponse(neighbors):
classVotes={}
for x in range(len(neighbors)):
response=neighbors[x][-1]
if response in classVotes:
classVotes[response]+=1
else:
classVotes[response]=1
sortedVotes=sorted(classVotes.iteritems(),key=operator.itemgetter(1),reverse=True)
return sortedVotes[0][0]
def getAccuracy(testSet,predictions):
correct=0
for x in range(len(testSet)):
if testSet[x][-1]==predictions[x]:
correct+=1
return (correct/float(len(testSet)))*100.0
def main():
trainingSet=[]
testSet=[]
split=0.67
loadDataset(r'F:\pythontest\KNN\iris.data.set.txt',split,trainingSet,testSet)
print 'Train set:'+repr(len(trainingSet))
print 'Test set:'+repr(len(testSet))
predictions=[]
k=3
for x in range(len(testSet)):
neighbors=getNeighbors(trainingSet,testSet[x],k)
result=getResponse(neighbors)
predictions.append(result)
print('> predicted='+repr(result)+', actual='+repr(testSet[x][-1]))
accuracy=getAccuracy(testSet,predictions)
print('Accuracy:'+repr(accuracy)+'%')
main()