前言
k近邻(k-Nearest Neighbors,简称kNN)算法是一种简单且常用的分类算法。k近邻的输入是实例的特征向量,对应于特征空间的点,输出为实例的类别。
一、k近邻算法
我们用人话来讲,就是现在,二维平面上有一堆点,已经分好类别了,看图看图,现在图上的点是不是被分成A,B两类。
那现在橙色的点我们应该分在哪类呢,当然是它离哪类近就归类为哪类。那我们现在要做的就是确定选择几个参考点(k近邻中k值的选取),然后用什么算法计算点之间的距离(距离度量),最后采取什么分类策略(服从多数,即分类决策规则)
这其实就包含了k近邻法的三要素,距离度量,k值选择,分类度量规则。
二、k近邻算法实现
1.自然想法
这里关键是计算样本点的邻域,不妨设这个样本点为x,现在就是要确定,和x离得最近的k个点,还记得k吗?k就是上面k值。我可以计算x与特征空间(理解为平面)中,所有点的距离,储存在一个数组里面,然后对数组进行排序,然后选择前k个元素,即是我们要求的参考点,但是这个方法要计算x与所有参考点的距离,还要进行数组排序,但这个方法的时间复杂度很高,所以不是很理想。
2.kd树
kd树是一种对k维空间中的实例点进行存储以便对其进行快速检索的树形数据结构。kd 树是二叉树,表示对k维空间的一个划分。构造 kd 树相当于不断地用垂直于坐标轴的超平面将k维空间切分,构成一系列的k维超矩形区域。kd树的每个结点对应于一个k维超矩形区域。
我这里给一个简单的例子:
首先,我们将以x轴为标准,找到x坐标的中位数,即479,于是以点4为划分,将空间划分为两部分。同样的,先看左边,以y轴坐标为标准,找到y坐标的中位数,即721,于是以点1划分,将左边空间划分为两部分,同理,右边以点6划分,将右边空间划分为两部分。
构建出的kd树如下图:
现在来看如何使用kd树,现在有一个点x(471,449),先从根节点,由于471小于479,所以遍历到节点1,又449小于721,所以遍历到节点2上,故以x到节点2的距离为半径的邻域里,有最近的节点。
3.代码简单演示
这里哥们直接调库了嗷,从 scikit-learn
库中导入 k近邻分类器的语句。有兴趣的宝子可以自己用二叉树实现一下,哥们也不太会哈哈哈。
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
# 样本数据和对应的类别标签
X_train = np.array([
[70, 721],
[207, 313],
[343, 858],
[479, 449],
[615, 40],
[751, 177],
[888, 585]
])
y_train = np.array([0, 1, 0, 1, 1, 0, 0])
# 初始化k近邻分类器,选择k值为3
k = 3
knn = KNeighborsClassifier(n_neighbors=k)
# 训练模型
knn.fit(X_train, y_train)
# 预测新样本点的类别
X_new = np.array([[471, 449]])
y_pred = knn.predict(X_new)
print("预测类别:", y_pred)
代码运行结果:
其实是很直观的,我标注的数据,你可以很清楚得看出x离类别1比较近,有兴趣的可以自己计算一下()想起之前打数模计算欧式距离的噩梦了。。
总结
1.通俗介绍了一下什么是k近邻算法
2.讲解了k近邻算法的底层实现逻辑
3.用scikit-learn
库简单演示了一下例子