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

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

原理:


k近邻模型

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

模型

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


距离度量

扫描二维码关注公众号,回复: 1506624 查看本文章

对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-8
import 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 KDTree
x =[[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)  #生成KDtree
dist, 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的博客)



猜你喜欢

转载自blog.csdn.net/qq_36603091/article/details/78283375
今日推荐