K邻近(KNN)算法

{% if theme.baidu_push %} {% endif %}

K邻近(KNN)算法

KNN分类模型

k 近邻(k-Nearest Neighbor,kNN)是机器学习中相对简单且容易理解的算法,是分类数据最简单有效的算法,它基于实例学习,我们必须用最真实的样本数据对模型进行训练,以便预测出的结果更具参考意义。
img
简单地说,k 近邻算法采用测量不同特征值之间的距离方法进行分类。这句话简单也不简单。更通俗易懂的理解,所谓“物以类聚,人以群分”,kNN 认为彼此相隔最近的点为一类。周围的对象是什么类别,我就是什么类别。如果你的朋友都开法拉利、保时捷等跑车,那么在 kNN 眼你,你也是有钱人,也开豪车。

工作原理

存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据 与所属分类的对应关系。输人没有标签的新数据后,将新数据的每个特征与样本集中数据对应的 特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。一般来说,我们 只选择样本数据集中前K个最相似的数据,这就是K-近邻算法中K的出处,通常K是不大于20的整数。 最后 ,选择K个最相似数据中出现次数最多的分类,作为新数据的分类。

  • 对未知类型的数据集中的每个点依次执行如下操作:
    • 计算已知类别数据集中的点与当前点之间的距离;
    • 按距离递增次序排序;
    • 选取与当前点距离最小的 k 个点;
    • 确认前 k 个点出现频率最高的类别作为当前点的预测分类;

接下来,举个栗子带大家更好的理解 kNN 算法。如图,有黄色的管理人才,深蓝色的架构师,以及未知的天蓝色。

img

当我们需要对员工进行技术和管理两个培养方向分类时,可能会考虑到他们的情商、沟通、技能、协作、远见、解决问题等能力。由于人类大脑的限制,我们只能处理三维以下的事务,这里只列举两个特征“情商”和“技能”评分,假设情商分高可作为管理人才来培养,技能分高作为架构师人才来培养。

我们拿到了七个样本数据,每一个样本带有情商和技能特征,以及对应的标签,他们分布在图中的数据如下:

技能 情商 培养方向
43 92 管理
60 88 管理
69 80 架构师
66 78 管理
88 50 架构师
80 91 管理
96 35 架构师
68 80

现在的需求是通过天蓝色的特征值预测他更适合的培养方向,按照 kNN 算法的实现步骤,计算出天蓝色特征与样本集的距离。计算二维平面上两点 a(x1,y1) 与 b(x2,y2) 间的欧氏距离

img
按距离升序排序之后结果如下:

技能 情商 欧式距离↑ 培养方向
69 80 1.0 架构师
66 78 2.83 管理
60 88 11.31 管理
80 91 16.27 管理
43 92 27.73 管理
88 50 36.06 架构师
96 35 53.0 架构师

我们得到了预测数据与各个样本间的距离,并按递增排好序。现假设 k = 3,对应的类别分别是“架构师”、“管理”、“管理”,按照算法实现的第 4 步,前 3 个点出现频率最高的类别是“管理”。那么,天蓝色的培养方向应该偏管理。

实例中 k 值取多少没有定论,如果实例中 k = 1 或 k = 2,那么结果未必是最准确的,这是一个经验值。通常 k 是 3 ≤ k < 20 的整数,并且是奇数,这样避免出现相同票数。

回过头来看数据分布图,以你为中心画圆,其中圆 c1 也就是 k = 1,距你最近的是“架构师”,圆 c2 则是当 k = 3 的时候,其中三个“管理”,少数服从多数,统计最多的类别依然是“管理”。

KNN优缺点

优点:精度高、对异常值不敏感、无数据输入假定。
缺点:kNN 必须保存全部数据集,会占用大量的存储空间,所以空间负责度高;kNN 必须对数据集中的每个数据计算距离值,实际使用时非常耗时,所以计算复杂度高。

1
2
#在scikit-learn库中使用k-近邻算法
from sklearn.neighbors import KNeighborsClassifier

交叉验证

  • 学习曲线&交叉验证选取K值
    • K值较小,则模型复杂度较高,容易发生过拟合,学习的估计误差会增大,预测结果对近邻的实例点非常敏感。
    • K值较大可以减少学习的估计误差,但是学习的近似误差会增大,与输入实例较远的训练实例也会对预测起作用,使预测发生错误,k值增大模型的复杂度会下降。
    • 在应用中,k值一般取一个比较小的值,通常采用交叉验证法来来选取最优的K值。
  • 适用场景
    • 小数据场景,样本为几千,几万的
  • 目的:
    • 选出最为适合的模型超参数的取值,然后将超参数的值作用到模型的创建中。
  • 思想:
    • 将样本的训练数据交叉的拆分出不同的训练集和验证集,使用交叉拆分出不同的训练集和验证集测分别试模型的精准度,然就求出的精准度的均值就是此次交叉验证的结果。将交叉验证作用到不同的超参数中,选取出精准度最高的超参数作为模型创建的超参数即可!
  • 实现思路:
    • 将训练数据平均分割成K个等份
    • 使用1份数据作为验证数据,其余作为训练数据
    • 计算验证准确率
    • 使用不同的测试集,重复2、3步骤
    • 对准确率做平均,作为对未知数据预测准确率的估计

img

  • API
    • from sklearn.model_selection import cross_val_score
    • cross_val_score(estimator,X,y,cv):
      • estimator:模型对象
      • X,y:训练集数据
      • cv:折数