机器学习 - K-最近邻算法(KNN)

KNN

KNN 是一种简单、有监督的机器学习(ML)算法,可用于分类或回归任务——并且也常用于缺失值插补。它基于这样一个思想:给定数据点最近的观测值是在数据集中最“相似”的观测值,因此我们可以根据最近现有点的值对不可预见的点进行分类。通过选择 K,用户可以选择在算法中使用的附近观测值的数量。

在这里,我们将向您展示如何实现用于分类的 KNN 算法,并展示不同的 K 值如何影响结果。

它是如何工作的?

K 是要使用的最近邻居的数量。对于分类,通过多数投票来确定新观测值应归入哪个类别。较大的 K 值通常对异常值更稳健,并产生比非常小的值更稳定的决策边界(K=3 比 K=1 更好,后者可能会产生不理想的结果)。

实例

首先,可视化一些数据点:

import matplotlib.pyplot as plt

x = [4, 5, 10, 4, 3, 11, 14 , 8, 10, 12]
y = [21, 19, 24, 17, 16, 25, 24, 22, 21, 21]
classes = [0, 0, 1, 0, 0, 1, 1, 0, 1, 1]

plt.scatter(x, y, c=classes)
plt.show()

亲自试一试

结果:

K-最近邻算法(KNN)

现在我们使用 K=1 来拟合 KNN 算法:

from sklearn.neighbors import KNeighborsClassifier

data = list(zip(x, y))
knn = KNeighborsClassifier(n_neighbors=1)

knn.fit(data, classes)

并使用它来分类一个新的数据点:

实例

new_x = 8
new_y = 21
new_point = [(new_x, new_y)]

prediction = knn.predict(new_point)

plt.scatter(x + [new_x], y + [new_y], c=classes + [prediction[0]])
plt.text(x=new_x-1.7, y=new_y-0.7, s=f"new point, class: {prediction[0]}")
plt.show()

亲自试一试

结果:

K-最近邻算法(KNN)

现在我们做同样的事情,但使用更高的 K 值来改变预测:

实例

knn = KNeighborsClassifier(n_neighbors=5)

knn.fit(data, classes)

prediction = knn.predict(new_point)

plt.scatter(x + [new_x], y + [new_y], c=classes + [prediction[0]])
plt.text(x=new_x-1.7, y=new_y-0.7, s=f"new point, class: {prediction[0]}")
plt.show()

亲自试一试

结果:

K-最近邻算法(KNN)

例子解释

导入您需要的模块。

您可以在我们的 Matplotlib 教程 中学习 Matplotlib 模块。

scikit-learn 是 Python 中一个流行的机器学习库。

import matplotlib.pyplot as plt
from sklearn.neighbors import KNeighborsClassifier

创建类似于数据集中变量的数组。我们有两个输入特征(x 和 y),然后是一个目标类别(class)。预先用目标类别标记的输入特征将用于预测新数据的类别。请注意,虽然我们这里只使用两个输入特征,但这种方法适用于任何数量的变量:

x = [4, 5, 10, 4, 3, 11, 14 , 8, 10, 12]
y = [21, 19, 24, 17, 16, 25, 24, 22, 21, 21]
classes = [0, 0, 1, 0, 0, 1, 1, 0, 1, 1]

将输入特征转换为一系列点:

data = list(zip(x, y))
print(data)

结果:

[(4, 21), (5, 19), (10, 24), (4, 17), (3, 16), (11, 25), (14, 24), (8, 22), (10, 21), (12, 21)]

使用输入特征和目标类别,我们在模型上拟合一个使用 1 个最近邻居的 KNN 模型:

knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(data, classes)

然后,我们可以使用相同的 KNN 对象来预测新的、不可预见的数据点的类别。首先,我们创建新的 x 和 y 特征,然后对新的数据点调用 knn.predict() 以获得类别 0 或 1:

new_x = 8
new_y = 21
new_point = [(new_x, new_y)]
prediction = knn.predict(new_point)
print(prediction)

结果:

[0]

当我们绘制所有数据以及新点和类别时,我们可以看到它被标记为蓝色,类别为 1。文本注释只是为了突出新点的位置:

plt.scatter(x + [new_x], y + [new_y], c=classes + [prediction[0]])
plt.text(x=new_x-1.7, y=new_y-0.7, s=f"new point, class: {prediction[0]}")
plt.show()

结果:

K-最近邻算法(KNN)

但是,当我们将邻居数量更改为 5 时,用于分类新点的点数就会改变。因此,新点的分类也会改变:

knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(data, classes)
prediction = knn.predict(new_point)
print(prediction)

结果:

[1]

当我们绘制新点的类别以及旧点时,我们注意到颜色已根据关联的类别标签更改:

plt.scatter(x + [new_x], y + [new_y], c=classes + [prediction[0]])
plt.text(x=new_x-1.7, y=new_y-0.7, s=f"new point, class: {prediction[0]}")
plt.show()

结果:

K-最近邻算法(KNN)