《统计学习方法》 第三章 k近邻法

k近邻法(KNN)是一种基本分类和回归方法。k近邻法基本做法是:对给定的训练实例点和输入实例点,首先确定输入实例点的k个最近邻训练实例点,然后利用这k个训练实例点的类的多数来预测输入实例点的类。

k近邻算法

在这里插入图片描述
k近邻模型

k近邻法使用的模型实际上对应于对特征空间的划分。模型由三个基本要素——距离度量,k值的选择,分类决策规则决定。当这三个基本要素确定后,对于任何一个新的输入实例,它所属的类唯一地确定。这相当于根据基本要素将特征空间划分为一些子空间,确定子空间里的每个点所属的类。

在这里插入图片描述
距离度量

在这里插入图片描述
在这里插入图片描述
例题帮助理解:

在这里插入图片描述
k值的选择

k值的选择会对k近邻法的结果产生重大影响。

k值较小:

相当于用较小的邻域中的训练实例进行预测,“学习”的近似误差会减小,但估计误差会增大。
k值的减小就意味着整体模型变得复杂,容易发生过拟合。

k值较大:

相当于用较大的邻域中的训练实例进行预测。“学习”的估计误差会减少,但近似误差会增大。
k值得增大就意味着整体模型变得简单。

k值一般取一个比较小的数值。通常采用交叉验证法来选取最优的k值

分类决策规则

k近邻法中的分类决策规则往往是多数表决,即由输入实例的k个邻近的训练实例中的多数决定输入实例的类别。

在这里插入图片描述

k近邻法的实现:kd树

实现k近邻法时,主要考虑的问题时如何对训练数据进行快速k近邻搜索。

构造kd树

kd树是一种对k维空间中的实例点进行存储以便对其进行快速搜索的树形数据结构。kd树二叉树,表示对k维空间
的一个划分。

构造kd树的方法:

构造根结点,使根节点对应于k维空间中包含所有实例点的超矩形区域;通过下面的递归方法,不断地对k维空间、
进行切分,生成子结点。在超矩形区域(结点)上选择一个坐标轴和在此坐标轴上地一个切分点,确定一个超平
面,这个超平面通过选定地切分点并垂直于选定地坐标轴,将当前超矩形区域切分为左右两个子区域(子结点);
这时,实例被分到两个子区域。这个过程直到子区域内没有实例时终止(终止时地结点为叶结点)。在此过程中,
将实例保存在相应地结点上。
通常,依次选择坐标轴对空间切分,选择训练实例点在选定坐标轴上的中位数为切分点,这样得到的kd树时平衡的。

在这里插入图片描述
在这里插入图片描述
例题:
在这里插入图片描述
在这里插入图片描述

搜索kd树:

以最近邻为例,叙述搜索kd树的方法:

在这里插入图片描述
在这里插入图片描述
例题:

在这里插入图片描述
k近邻法的简单代码实现:

因为本人是刚接触skrlearn库,对于其中函数的许多用法都不熟悉,在网上查找knn代码时,也有很多不懂的地方,
下面的两个代码中有一些相关函数的介绍链接,大家如果对这些函数用法不熟悉,可以直接搜链接查看用法介绍。
简单的KNN代码,实现电影类型分类
import numpy as np
import operator
import collections

def createDataset():
    group=np.array([[1,101],[5,89],[108,5],[115,8]])#(动作镜头,接吻镜头)
    labels=['爱情片','爱情片','动作片','动作片']
    return group,labels

def classify(inx,dataset,labels,k):
    dist=np.sum((inx-dataset)**2,axis=1)**0.5 #如果axis=1,表示矩阵每一个行相加
    k_labels=[labels[index] for index in dist.argsort()[0:k]] 
    #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y
    #argsort()函数:https://www.cnblogs.com/yyxf1413/p/6253995.html
    #出现次数最多的标签即为最终类别
    label=collections.Counter(k_labels).most_common(1)[0][0]
    # most_common :https://blog.csdn.net/LiChuanxiu/article/details/103479656?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.not_use_machine_learn_pai&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.not_use_machine_learn_pai
    return label

if __name__ =='__main__':
    group ,labels = createDataset()
    test=[101,20]
    test_class=classify(test,group,labels,3)
    print(test_class) 
使用sklearn中提供的常用数据集——鸢尾花数据集
from sklearn import datasets,neighbors
from sklearn.model_selection import train_test_split
import  matplotlib.pyplot as plt
# iris:鸢尾花数据集:--> 用于分类
# 有150个数据集,共分为3类,每类50个样本。每个样本有4个特征。

# 加载iris数据集
iris=datasets.load_iris()

n_samples,n_features=iris.data.shape
""" print("共有",n_samples,"个样本,每个样本有",n_features,"个特征")#共有 150 个样本, 每个样本有 4 个特征
print("iris.data.shape : ",iris.data.shape)#样本  (150, 4)
print("iris.target.shape : ",iris.target.shape)#标签  (150,)
print("四个特征值 :",iris.feature_names)
print("花的类别 : ",iris.target_names)
print("iris.data :",iris.data)
print("iris.target : ",iris.target) """

#给数据集划分训练集和测试集
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.2,random_state=1)
clf=neighbors.KNeighborsClassifier()#使用默认参数 n_neighbors=5, weights=‘uniform’, algorithm=‘auto’
#k近邻分类器: https://www.cnblogs.com/qfwmy/p/12106725.html
clf.fit(x_train,y_train)
predict=clf.predict(x_test)
print(y_test==predict)

关于KNN算法,我还有许多没有实现的地方,还在持续学习中,如果大家有看到优秀的KNN算法实现的博客,希望可以私信我或在下方留言给我,帮助我继续学习!^ ^

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值