本文已参与「新人创作礼」活动,一起开启掘金创作之路
K近邻分析与应用
K近邻分类方法的基本思路是:不对预先的训练数据集进行任何处理,当测试一个新来的数据属于哪个类时,计算下它与训练集中所有实例的距离,从中选出K个距离最小(近)的实例,统计下这K个实例属于哪个类的最多,就将新来的数据归为哪一类。 谚语:“走路像鸭子,叫起来像鸭子,看起来像鸭子,那它很可能就是鸭子”。 举例来说,如果我们有下面的训练集,其中每个实例有5个属性,最后一列标出了它们属于哪一类?
编号 属性1 属性2 属性3 属性4 属性5 所属类 1 1.1 1.2 1.3 1.4 1.5 A 2 2.1 2.2 2.3 2.4 2.5 B 3 3.1 3.2 3.3 3.4 3.5 A 4 4.1 4.2 4.3 4.4 4.5 A 5 5.1 5.2 5.3 5.4 5.5 B
假设现在有一个新数据(2.11,2.21,2.22,2.23,2.24,2.25),我们取K = 3,在训练集中与它距离最近的三个实例肯定是实例1,2,3,其中两个属于A类,一个属于B类,那我们就将新数据归为A类。
Code
# -*- coding: utf-8 -*-
import csv
import random
import math
import operator
import numpy as np
def loadDataset(filename,split,trainingSet=[],testSet=[]):
with open(filename,'r') as csvfile:
lines = csv.reader(csvfile)
dataset = list(lines)
for x in range(len(dataset)-1):
for y in range(np.array(dataset).shape[1]):
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 distance
def getNeighbors(trainingSet,testInstance,k):
distance=[]
length = len(testInstance)-1
for i in range(len(trainingSet)):
dist = euclideanDistance(testInstance, trainingSet[i], length)#求每个训练样本的距离
distance.append((trainingSet[i],dist))#将元组(每个训练数据,与测试数据的欧几里德距离)添加到距离集合
distance.sort(key=operator.itemgetter(1))#进行升序排序
neighbors=[]
for i in range(k):
neighbors.append(distance[i][0])#取k个与测试样本的最短距离
return neighbors
def getResponse(neighbors):
classVotes = {}
for i in range(len(neighbors)):#分别统计k个最短距离的类别,取类别出现次数最多的
response=neighbors[i][-1]
if response in classVotes:
classVotes[response]+=1
else:
classVotes[response]=1
sortedVotes=sorted(classVotes.items(),key=operator.itemgetter(1),reverse=True)#进行降序排序
return sortedVotes[0][0]
def getAccuracy(testSet,predictions):#求准确率
correct = 0 #由于每次测试集的样本是随机划分的,每次准确率也不是固定的
for i in range(len(testSet)):
if testSet[i][-1] == predictions[i]:
correct +=1
return (correct/float(len(testSet)))*100.0
def main():
trainingSet=[]
testSet=[]
split=0.85
loadDataset(r'C:\Users\lndx\Desktop\knn_data.csv', split,trainingSet,testSet)
print('Train set:'+repr(len(trainingSet)))
print('Test set:'+repr(len(testSet)))
predictions=[]
k=5
for i in range(len(testSet)):
neighbors = getNeighbors(trainingSet, testSet[i], k)
result = getResponse(neighbors)
predictions.append(result)
print('prediction='+repr(result)+',actual='+repr(testSet[i][-1]))
accuracy = getAccuracy(testSet, predictions)
print('Accuracy:'+repr(accuracy)+'%')
if __name__ =='__main__':
main()
结果