统计学习方法--K近邻法 python实现

来源:互联网 发布:透明头像生成软件 编辑:程序博客网 时间:2024/05/20 18:46

k近邻是一种常用的分类与回归算法,简单直观。

原理:


k近邻模型

模型有3个要素——距离度量方法、k值的选择和分类决策规则。

模型

当3要素确定的时候,对任何实例(训练或输入),它所属的类都是确定的,相当于将特征空间分为一些子空间。


距离度量

对n维实数向量空间Rn,经常用Lp距离或曼哈顿Minkowski距离。距离的度量详见博客http://blog.csdn.net/qq_36603091/article/details/78216124

k值的选择

k较小,容易被噪声影响,发生过拟合。

k较大,较远的训练实例也会对预测起作用,容易发生错误。

分类决策规则

使用0-1损失函数衡量,那么误分类率是:

Nk是近邻集合,要使左边最小,右边的必须最大,

所以多数表决=经验最小化。

 k近邻法的实现:

kd树

算法核心在于怎么快速搜索k个近邻出来,朴素做法是线性扫描,不可取,这里介绍的方法是kd树。

构造kd树 

对数据集T中的子集S初始化S=T,取当前节点node=root取维数的序数i=0,对S递归执行: 

找出S的第i维的中位数对应的点,通过该点,且垂直于第i维坐标轴做一个超平面。该点加入node的子节点。

该超平面将空间分为两个部分,对这两个部分分别重复此操作(S=S',++i,node=current),直到不可再分。

搜索效率

kd树搜索的平均时间复杂度为logN.。所以,当样本较小时,kd树搜索与暴力搜索接近;但当数据量很大,kd树搜索能节省很多搜索时间。一般来说,k维的数据,数据集超过2k时,kd树能表现的比较好。

python实现

# -*- coding: utf-8 -*-"""Created on Thu Oct 19 13:17:31 2017@author: lizheng"""#encoding:utf-8import csv     #用于处理csv文件  import random    #用于随机数  import math           import operator  #  函数操作  #加载数据集  def loadDataset(filename,split,trainingSet=[],testSet = []):      with open(filename,"r") as csvfile:         #这里如果是open("D:\Iris.txt","rb")会提示有错误        #错误为“Error: iterator should return strings, not bytes (did you open the file in text mode?)”        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:                  trainingSet.append(dataset[x])              else:                  testSet.append(dataset[y])    #计算距离-欧氏距离  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 = []      #返回k个最近邻      for x in range(k):          neighbors.append(distances[x][0])      return neighbors    #对k个近邻进行合并,返回value最大的key  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.items(),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"D:\Iris.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) + "%")    if __name__ =="__main__":      main()







from sklearn.neighbors import KDTreex =[[2, 3],             [5, 4],             [9, 6],             [4, 7],             [8, 1],             [7, 2]]s=[[5,3]]x.extend(s)tree = KDTree(x, leaf_size=2, metric='euclidean')tree.query(x, k=3)  #生成KDtreedist, ind = tree.query(s, k=7) i = ind[0][1]print("s-k-Nearest :",x[i],"didistance: ",dist[0][i])#返回S的最近邻和欧氏距离#print(tree.query(x, k=2, return_distance=False) )


使用scikit-learn的KNN算法进行分类的一个实例

from sklearn import neighbors  import numpy as np  #数据集  group =np.array([[1.0,1.1],[2.0,2.1],[1.0,1.0],[0,0],[0,0.1],[0.5,0.9]])labels = ['A','A','A','B','B','B'] knn = neighbors.KNeighborsClassifier()  #训练数据集  knn.fit(group,labels)  #预测  predict = knn.predict([[1,2],[3,3]])  print(predict)  
使用iris鸢尾花数据集 的一个实例

from sklearn.datasets import load_iris  from sklearn import neighbors    #查看iris数据集  iris = load_iris()  print(iris)    knn = neighbors.KNeighborsClassifier()  #训练数据集  knn.fit(iris.data, iris.target)  #预测  predict = knn.predict([[1,2,2,5]])  print (predict)  print (iris.target_names[predict])



Python中常用包——sklearn主要模块和基本使用方法(Jorocco的博客)