理解近邻法的基本原理,能实现K近邻(KNN)算法;
针对特定应用场景及数据,能用KNN进行分类;
熟悉不同近邻数对于算法的影响。
KNN算法是一种简单分类算法。它以所有已知类别的样本作为参照,计算未知样本与所有已知样本的距离,从中选取与未知样本距离最近的K个已知样本,根据少数服从多数的投票法则,将未知样本与K个最近邻样本中所属类别占比较多的归为一类。
1、导入实验要用到的相关库
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
2、加载并划分鸢尾花数据集(这里选择了所有的特征用于分类)
iris_data = load_iris()
X = iris_data["data"]
y = iris_data["target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=10)
3、使用默认的近邻数量和权重,查看预测精度
# 使用默认的近邻数量和权重,查看预测精度
knn = KNeighborsClassifier() # 默认 n_neighbors = 5, weight = 'uniform'
knn.fit(X_train, y_train) # 用训练数据拟合模型
print("模型精度:", knn.score(X_test, y_test))
K近邻分类模型 KNeighborsClassifier 默认 n_neighbors = 5,即使用与未知样本距离最近的 5 个训练样本对其进行分类;默认 weight = 'uniform',表示使用统一权重,即每个邻域中的所有点均被加权。如果设置 weight = 'distance',表示权重点与其距离的倒数,即查询点的近邻比远处的近邻具有更大的影响力。
输出:
模型精度: 0.9736842105263158
4、查看测试集第一个数据划分所用到的数据点
# 查看测试集第一个数据划分所用到的数据点
n = knn.kneighbors_graph(X_test)
print(n.toarray()[0])
kneighbors_gragp() 计算 X_test 中点的 k 临近点的(加权)图形 ,其输出为稀疏矩阵的格式,将其转换为数组的形式输出,第一个数据的结果如下所示。
输出:
[0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 1. 0. 0.
0. 1. 0. 0. 0. 0. 0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
5、增大近邻数,查看对算法的影响
# 增大近邻数,查看对算法的影响
knn = KNeighborsClassifier(n_neighbors=15)
knn.fit(X_train, y_train) # 用训练数据拟合模型
print("模型精度:", knn.score(X_test, y_test))
输出:
模型精度: 0.9736842105263158
6、改变权重设置,查看对算法的影响
# 改变权重设置,查看对算法的影响
knn = KNeighborsClassifier(weights='distance') # distence表示用距离的导数作为权重设置,即越近的点影响力越大
knn.fit(X_train, y_train)
print("模型精度:", knn.score(X_test, y_test))
输出:
模型精度: 0.9736842105263158
7、查看不同 n_neighbors 的设置在训练集和测试集上的精度
# 查看不同 n_neighbors 的设置在训练集和测试集上的精度
training_accuracy = []
test_accuracy = []
# n_neighbors取值从1到16
neighbors_settings = range(1, 16)
for n_neighbors in neighbors_settings:
# 构建模型
clf = KNeighborsClassifier(n_neighbors=n_neighbors)
clf.fit(X_train, y_train)
# 记录训练集精度
training_accuracy.append(clf.score(X_train, y_train))
# 记录泛化精度
test_accuracy.append(clf.score(X_test, y_test))
plt.plot(neighbors_settings, training_accuracy, label="training accuracy")
plt.plot(neighbors_settings, test_accuracy, label="test accuracy")
plt.ylabel("Accuracy")
plt.xlabel("n_neighbors")
plt.legend()
输出:
8、使用花萼长度和花萼宽度,设置近邻数量为5,绘制KNN分类器图
# 使用花萼长度和花萼宽度,设置近邻数量为5,绘制KNN分类器图
X = iris_data["data"][:,(0,1)]
y = iris_data["target"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=1)
from matplotlib.colors import ListedColormap
h = .02 # 设置网格中的步长
n_neighbors = 5
# 提取色谱
cmap_light = ListedColormap(['orange', 'cyan', 'cornflowerblue'])
cmap_bold = ListedColormap(['darkorange', 'c', 'darkblue'])
for weights in ['uniform', 'distance']:
# 我们创建最近邻分类器的实例并拟合数据。
clf = KNeighborsClassifier(n_neighbors, weights=weights)
clf.fit(X, y)
# 绘制决策边界。 为此,我们将为网格[x_min,x_max] x [y_min,y_max]中的每个点分配颜色。
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
# 将结果放入颜色图
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)
# 绘制训练数据
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold,
edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.xlabel('sepal length')
plt.ylabel('sepal width')
plt.title("3-Class classification (k = %i, weights = '%s')"
% (n_neighbors, weights))
plt.show()
输出:
KNN 不同近邻数对算法的影响:
随着近邻数越来越多,决策边界也越来越平滑。更平滑的边界对应更简单的模型。
使用更少的邻居对应更高的模型复杂度,而使用更多的邻居对应更低的模型复杂度。
KNN 不同权重对算法的影响:
KNN 默认使用统一权重,即每个邻域中的点的权重相同,如果使用距离作为权重,那么距离待分类点较近的近邻会被赋予更大的权重,在决策过程起到更重要的作用。