前言
试验环境:
1. python3.7 2. numpy >= '1.16.4' 3. sklearn >= '0.23.1'
一.KNN简介
1.1KNN建立过程
1.1.1:给定测试样本,计算它与训练集中的每一个样本的距离。
1.1.2:找出距离近期的K个训练样本。作为测试样本的近邻。
1.1.3:依据这K个近邻归属的类别来确定样本的类别。
1.2类别的判定
1.2.1:投票决定,少数服从多数。取类别最多的为测试样本类别。
1.2.2:加权投票法,依据计算得出距离的远近,对近邻的投票进行加权,距离越近则权重越大,设定权重为距离平方的倒数。
二.试验流程
2.1:库函数导入
2.2:数据导入
2.3:模型训练&可视化
三.KNN完成分类任务
3.1 KNN分类demo:
# 加载莺尾花数据集 from sklearn import datasets # 导入KNN分类器 from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import train_test_split # 导入莺尾花数据集 iris = datasets.load_iris() X = iris.data y = iris.target print("X展示:", X) print("y展示:", y) # 得到训练集合和验证集合, 8: 2 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 训练模型 clf = KNeighborsClassifier(n_neighbors=5, p=2, metric="minkowski") clf.fit(X_train, y_train) # 预测 X_pred = clf.predict(X_test) acc = sum(X_pred == y_test) / X_pred.shape[0] print("预测的准确率ACC: %.3f" % acc)
展示X:
[[5.1 3.5 1.4 0.2] [4.9 3. 1.4 0.2] [4.7 3.2 1.3 0.2] [4.6 3.1 1.5 0.2] [5. 3.6 1.4 0.2] [5.4 3.9 1.7 0.4] [4.6 3.4 1.4 0.3] [5. 3.4 1.5 0.2] [4.4 2.9 1.4 0.2] [4.9 3.1 1.5 0.1] [5.4 3.7 1.5 0.2] [4.8 3.4 1.6 0.2] [4.8 3. 1.4 0.1] [4.3 3. 1.1 0.1] [5.8 4. 1.2 0.2] [5.7 4.4 1.5 0.4] [5.4 3.9 1.3 0.4] [5.1 3.5 1.4 0.3] [5.7 3.8 1.7 0.3] [5.1 3.8 1.5 0.3] [5.4 3.4 1.7 0.2] [5.1 3.7 1.5 0.4] [4.6 3.6 1. 0.2] [5.1 3.3 1.7 0.5] [4.8 3.4 1.9 0.2] [5. 3. 1.6 0.2] [5. 3.4 1.6 0.4] [5.2 3.5 1.5 0.2] [5.2 3.4 1.4 0.2] [4.7 3.2 1.6 0.2] [4.8 3.1 1.6 0.2] [5.4 3.4 1.5 0.4] [5.2 4.1 1.5 0.1] [5.5 4.2 1.4 0.2] [4.9 3.1 1.5 0.2] [5. 3.2 1.2 0.2] [5.5 3.5 1.3 0.2] [4.9 3.6 1.4 0.1] [4.4 3. 1.3 0.2] [5.1 3.4 1.5 0.2] [5. 3.5 1.3 0.3] [4.5 2.3 1.3 0.3] [4.4 3.2 1.3 0.2] [5. 3.5 1.6 0.6] [5.1 3.8 1.9 0.4] [4.8 3. 1.4 0.3] [5.1 3.8 1.6 0.2] [4.6 3.2 1.4 0.2] [5.3 3.7 1.5 0.2] [5. 3.3 1.4 0.2] [7. 3.2 4.7 1.4] [6.4 3.2 4.5 1.5] [6.9 3.1 4.9 1.5] [5.5 2.3 4. 1.3] [6.5 2.8 4.6 1.5] [5.7 2.8 4.5 1.3] [6.3 3.3 4.7 1.6] [4.9 2.4 3.3 1. ] [6.6 2.9 4.6 1.3] [5.2 2.7 3.9 1.4] [5. 2. 3.5 1. ] [5.9 3. 4.2 1.5] [6. 2.2 4. 1. ] [6.1 2.9 4.7 1.4] [5.6 2.9 3.6 1.3] [6.7 3.1 4.4 1.4] [5.6 3. 4.5 1.5] [5.8 2.7 4.1 1. ] [6.2 2.2 4.5 1.5] [5.6 2.5 3.9 1.1] [5.9 3.2 4.8 1.8] [6.1 2.8 4. 1.3] [6.3 2.5 4.9 1.5] [6.1 2.8 4.7 1.2] [6.4 2.9 4.3 1.3] [6.6 3. 4.4 1.4] [6.8 2.8 4.8 1.4] [6.7 3. 5. 1.7] [6. 2.9 4.5 1.5] [5.7 2.6 3.5 1. ] [5.5 2.4 3.8 1.1] [5.5 2.4 3.7 1. ] [5.8 2.7 3.9 1.2] [6. 2.7 5.1 1.6] [5.4 3. 4.5 1.5] [6. 3.4 4.5 1.6] [6.7 3.1 4.7 1.5] [6.3 2.3 4.4 1.3] [5.6 3. 4.1 1.3] [5.5 2.5 4. 1.3] [5.5 2.6 4.4 1.2] [6.1 3. 4.6 1.4] [5.8 2.6 4. 1.2] [5. 2.3 3.3 1. ] [5.6 2.7 4.2 1.3] [5.7 3. 4.2 1.2] [5.7 2.9 4.2 1.3] [6.2 2.9 4.3 1.3] [5.1 2.5 3. 1.1] [5.7 2.8 4.1 1.3] [6.3 3.3 6. 2.5] [5.8 2.7 5.1 1.9] [7.1 3. 5.9 2.1] [6.3 2.9 5.6 1.8] [6.5 3. 5.8 2.2] [7.6 3. 6.6 2.1] [4.9 2.5 4.5 1.7] [7.3 2.9 6.3 1.8] [6.7 2.5 5.8 1.8] [7.2 3.6 6.1 2.5] [6.5 3.2 5.1 2. ] [6.4 2.7 5.3 1.9] [6.8 3. 5.5 2.1] [5.7 2.5 5. 2. ] [5.8 2.8 5.1 2.4] [6.4 3.2 5.3 2.3] [6.5 3. 5.5 1.8] [7.7 3.8 6.7 2.2] [7.7 2.6 6.9 2.3] [6. 2.2 5. 1.5] [6.9 3.2 5.7 2.3] [5.6 2.8 4.9 2. ] [7.7 2.8 6.7 2. ] [6.3 2.7 4.9 1.8] [6.7 3.3 5.7 2.1] [7.2 3.2 6. 1.8] [6.2 2.8 4.8 1.8] [6.1 3. 4.9 1.8] [6.4 2.8 5.6 2.1] [7.2 3. 5.8 1.6] [7.4 2.8 6.1 1.9] [7.9 3.8 6.4 2. ] [6.4 2.8 5.6 2.2] [6.3 2.8 5.1 1.5] [6.1 2.6 5.6 1.4] [7.7 3. 6.1 2.3] [6.3 3.4 5.6 2.4] [6.4 3.1 5.5 1.8] [6. 3. 4.8 1.8] [6.9 3.1 5.4 2.1] [6.7 3.1 5.6 2.4] [6.9 3.1 5.1 2.3] [5.8 2.7 5.1 1.9] [6.8 3.2 5.9 2.3] [6.7 3.3 5.7 2.5] [6.7 3. 5.2 2.3] [6.3 2.5 5. 1.9] [6.5 3. 5.2 2. ] [6.2 3.4 5.4 2.3] [5.9 3. 5.1 1.8]]
y展示:
[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 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]
3.2 分析KNN分类任务
X为输入,其形式为数组;y则为对应的标签,这是一个经典的三分类。
后续构建自己的数据,例如从表中读取数据(可参考:juejin.cn/post/707996…得到输入和输出,剩下的就是“搭积木”了。
四.KNN完成回归任务
4.1demo:
Demo来自sklearn官网
import numpy as np import matplotlib.pyplot as plt from sklearn.neighbors import KNeighborsRegressor np.random.seed(0) # 随机生成40个(0, 1)之前的数,乘以5,再进行升序 X = np.sort(5 * np.random.rand(40, 1), axis=0) # 创建[0, 5]之间的500个数的等差数列, 作为测试数据 T = np.linspace(0, 5, 500)[:, np.newaxis] # 使用sin函数得到y值,并拉伸到一维 y = np.sin(X).ravel() # Add noise to targets[y值增加噪声] y[::5] += 1 * (0.5 - np.random.rand(8)) # ############################################################################# # Fit regression model # 设置多个k近邻进行比较 n_neighbors = [1, 3, 5, 8, 10, 40] # 设置图片大小 plt.figure(figsize=(10,20)) for i, k in enumerate(n_neighbors): # 默认使用加权平均进行计算predictor clf = KNeighborsRegressor(n_neighbors=k, p=2, metric="minkowski") # 训练 clf.fit(X, y) # 预测 y_ = clf.predict(T) plt.subplot(6, 1, i + 1) plt.scatter(X, y, color='red', label='data') plt.plot(T, y_, color='navy', label='prediction') plt.axis('tight') plt.legend() plt.title("KNeighborsRegressor (k = %i)" % (k)) plt.tight_layout() plt.show()
分析KNN回归:
设置多个k近邻进行比较,从设置的这多个值结合图中可以得到:
当K=1:函数过拟合,对新数据的泛化性差
当K=40:函数欠拟合,无法适应数据
当K=3,5,8,10 时函数拟合拟合适中,在这四个拟合度中,结合图像看的话有泛化性有:(K=3)>(K=5)>(K=8)>(K=10)