1.KNN是一种基本分类与回归方法、K近邻法的输入为实例的特征向量,对应于特征空间的点;输出为实例的类别,可以取多类,K近邻法假设给定一个训练数据集,其中的实例类别已定。分类时根据其K个最近邻的训练实例的类别。通过多数表决等方式进行预测。
2.K近邻法三要素:K值的选择,距离度量,分类决策规则。
3.算法详述
3.1步骤:
为了判断未知实例的类别,以所有已知类别的实例作为参考。
选择参数K。
计算未知实例与所有已知实例的距离。
选择最近K个已知实例
根据少数服从多数的投票法则,让未知实例归类为k个最邻近样本中最多数的类别。
3.2细节
关于K
关于距离的衡量方法
3.2.1Euclidean Distance定义
其他距离衡量:余弦值,相关度,曼哈顿距离。
import math
def ComputerEuclideanDistance(x1,y1,x2,y2):
d=math.sqrt(math.pow((x1-x2),2)+math.pow((y1-y2),2))
return d
d_ag=ComputerEuclideanDistance(3,104,18,90)
print(d_ag)
4.算法优缺点
优点:
简单,易于理解,容易实现,通过对K的选择可具备丢噪音数据的健壮性。
缺点:
需要大量空间储存所有已知实例。
算法复杂度高(需要比较所有已知实例与要分类的实例)
当其样本分布不平衡时,比如其中一类样本过大(实例数量过多)占主导的时候,新的未知实例容易被归类为这个主导样本,因为这类样本实例的数量过大,但这个新的未知实例实际并不接近目标样本。
5.改进版本
考虑距离,根据距离加上权重
比如:1/d(d:距离)
6.python中用sklearn调用knn算法
# -*- coding: utf-8 -*-
from sklearn import neighbors
from sklearn import datasets
knn=neighbors.KNeighborsClassifier() #调用knn的分类器
iris=datasets.load_iris() #返回datasets里面的一个数据库
print iris
knn.fit(iris.data,iris.target) #建模,传入特征值矩阵,和类别矩阵
predictedLabel=knn.predict([[0.1,0.2,0.3,0.4]])
print predictedLabel
7.程序算法实现
# -*- coding: utf-8 -*-
import csv
import random
import math
import operator
from networkx.classes.function import neighbors
#装载数据集
def loadDataset(filename,split,trainingSet=[],testSet=[]): #数据里面分成训练集和测试集
with open(filename,'rb') as csvfile:
lines=csv.reader(csvfile) #按行内容读取
dataset=list(lines)
for x in range(len(dataset)-1):
for y in range(4):
dataset[x][y]=float(dataset[x][y])
if random.random()<split: #如果产生的随机值小于给定的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]) #取前k个距离
return neighbors
#根据少数服从多数原则预测实例属于哪一类
def getResponse(neighbors):
classVotes={}
for x in range(len(neighbors)):
response=neighbors[x][-1] #-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'irisdata.txt',split,trainingSet,testSet) #字符串r的意思是把传入的字符串当做原始字符串,忽略里面特殊符号。
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()