K-Nearest Neighbour -- Explained

K-Nearest Neighbour -- Explained

K-Nearest Neighbour – Explained

K近邻: K-nearest neighbors(kNN)是一种受监督的机器学习算法,可用于解决分类和回归任务。我将kNN视为来自现实生活的算法。人们往往会受到周围人的影响。我们的行为受到我们成长的朋友的指导。我们的父母也以某种方式塑造我们的个性。如果您与热爱运动的人一起长大,那么很可能您最终会热爱运动。当然也有例外。 kNN的工作方式与此类似。

数据点的值由其周围的数据点确定。

  1. 如果您有一个非常亲密的朋友,并与他/她在一起度过了大部分时间,那么您最终会分享相似的兴趣并享受相同的事物。那就是k = 1的kNN。
  2. 如果您总是与5个人一起闲逛,则该群组中的每个人都会对您的行为产生影响,最终您将成为5的平均值。这就是kNN,其中k = 5

kNN分类器通过多数投票原则确定数据点的类别。如果k设置为5,则检查5个最接近点的类别。根据多数类别进行预测。同样,kNN回归采用5个最接近点的平均值。

我们观察到谁接近,但是如何确定数据点接近?测量数据点之间的距离。有许多测量距离的方法。欧几里得距离 Euclidean distance(p = 2的最小可夫斯基距离)是最常用的距离测量之一。下图显示了如何计算二维空间中两点之间的欧式距离。它是使用点的x和y坐标之差的平方来计算的。

K-Nearest Neighbour -- Explained
在上述情况下,欧几里德距离是(16 + 9)的平方根,它是5。二维欧几里德距离使我们想起了著名的毕达哥拉斯定理。

对于二维空间中的两个点,这似乎非常简单。 每个维度代表数据集中的特征。 通常,我们有许多具有许多功能的示例。 为了能够清楚地解释该概念,我将在二维空间(即2个要素)中介绍一个示例。

让我们从导入库开始:

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt #data visualization

from sklearn.datasets import make_blobs #synthetic dataset
from sklearn.neighbors import KNeighborsClassifier #kNN classifier
from sklearn.model_selection import train_test_split #train and test sets

Scikit-learn提供了许多有用的功能来创建综合数据集,这对实践机器学习算法非常有帮助。 我将使用make_blobs函数。

#create synthetic dataset
X, y = make_blobs(n_samples = 100, n_features = 2, centers = 4,
                       cluster_std = 1.5, random_state = 4)

此代码创建了一个数据集,其中包含100个样本,分为4类,特征数量为2。可以使用相关参数轻松调整样本,特征和类的数量。 我们还可以调整每个群集(或类)的传播数量。 让我们可视化此综合数据集:

#scatter plot of dataset
plt.figure(figsize = (10,6))
plt.scatter(X[:,0], X[:,1], c=y, marker= 'o', s=50)
plt.show()

K-Nearest Neighbour -- Explained

对于任何监督的机器学习算法,将数据集分为训练集和测试集非常重要。 我们首先训练模型并使用数据集的不同部分对其进行测试。 如果不进行这种分离,那么我们基本上将使用它已经知道的一些数据来测试模型。 我们可以使用train_test_split函数轻松地进行这种分离。

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 0)

我们可以分别使用train_size或test_size参数指定用于火车或测试集的原始数据量。 火车设置的默认间隔是75%,测试设置的默认间隔是25%。

然后,我们创建一个kNN分类器对象。 为了显示k值的重要性之间的差异,我创建了两个k值为1和5的分类器。然后使用训练集对这些模型进行训练。 n_neighbors参数用于选择k值。 默认值为5,因此不必显式编写。

knn5 = KNeighborsClassifier() #k=5
knn1 = KNeighborsClassifier(n_neighbors=1) #k=1

knn5.fit(X_train, y_train)
knn1.fit(X_train, y_train)

然后,我们预测测试集中的目标值并与实际值进行比较。

y_pred_5 = knn5.predict(X_test)
y_pred_1 = knn1.predict(X_test)

为了查看k值的影响,我们将k = 5和k = 1的测试集和预测值可视化。

K-Nearest Neighbour -- Explained
K-Nearest Neighbour -- Explained
K-Nearest Neighbour -- Explained

结果似乎非常相似,因为我们使用了一个非常小的数据集。 但是,即使在小型数据集上,不同的k值也会预测不同的点。
如何找到最佳的k值

k = 1:该模型过于具体,不能很好地概括。 它还倾向于对噪声敏感。 该模型在火车上实现了很高的准确性,但是对于新的,以前看不见的数据点来说,它的预测能力很差。 因此,我们可能最终会得出过度拟合模型。
k = 100:模型过于笼统,在训练集和测试集上都不是很好的预测指标。 这种情况称为欠拟合。

我们如何找到最佳的k值? Scikit-learn提供GridSearchCV函数,使我们能够轻松检查k的多个值。 我们来看一个使用scikit-learn数据集模块下可用数据集的示例。

from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import GridSearchCV

cancer = load_breast_cancer()
(X_cancer, y_cancer) = load_breast_cancer(return_X_y = True)

导入所需的库并加载数据集之后,我们可以创建GridSearchCV对象。

knn_grid = GridSearchCV(estimator = KNeighborsClassifier(), 
                        param_grid={'n_neighbors': np.arange(1,20)}, cv=5)

knn_grid.fit(X_cancer, y_cancer)

我们不需要拆分数据集,因为cv参数拆分了数据集。 cv参数的默认值为5,但我明确写了它,以强调为什么我们不需要使用train_test_split。

cv = 5基本上将数据集分为5个子集。 GridSearchCV进行5次迭代,每次使用4个子集进行训练,并使用1个子集进行测试。 这样,我们可以将所有数据点用于培训和测试。

我们可以使用best_params_方法检查哪些参数给我们带来最佳结果:

knn_grid.best_params_

在这种情况下,k的最佳值为12。

k-最近-Neigbors的优缺点

优点

  1. 简单易懂 不做任何假设,因此可以在非线性任务中实施。
  2. 在多个类别的分类上效果很好
  3. 适用于分类和回归任务

缺点

  1. 随着数据点数量的增加,它变得非常慢,因为模型需要存储所有数据点。
  2. 内存效率不高 对异常值敏感。 离群值也可以投票!

感谢您的阅读。 如果您有任何反馈意见,请告诉我。

上一篇:aliyun - Express Connect


下一篇:[LeetCode] 1602. Find Nearest Right Node in Binary Tree