k近邻法(KNN)是一种基本分类和回归方法。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树的方法:
因为本人是刚接触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算法实现的博客,希望可以私信我或在下方留言给我,帮助我继续学习!^ ^