20220315_K近邻

三 K近邻

1.1 基础

k近邻方法是一种惰性学习算法,可以用于回归和分类,它的主要思想是投票机制,对于一个测试实例x, 我们在有标签的训练数据集上找到和最相近的k个数据,用他们的label进行投票,分类问题则进行表决投票回归问题使用加权平均或者直接平均的方法。

K近邻算法,即是给定一个训练数据集,对新的输入实例,在训练数据集中找到与该实例最邻近的K个实例,这K个实例的多数属于某个类,就把该输入实例分类到这个类中。(这就类似于现实生活中少数服从多数的思想)

在这里插入图片描述
为了保证每个特征同等重要性,需对每个特征进行归一化

  • 算法关键: k值的选择距离的计算 >>>
  1. k∈[2,20],使用交叉验证得到一个很好的k值
    k值还可以表示我们的模型复杂度,当k值越小意味着模型复杂度变大,更容易过拟合,(用极少数的样例来绝对这个预测的结果,很容易产生偏见,这就是过拟合)。我们有这样一句话,k值越多学习的估计误差越小,但是学习的近似误差就会增大。
  2. 样本之间的距离的计算,我们一般使用对于一般使用Lp距离进行计算。当p=1时候,称为曼哈顿距离(Manhattan distance),当p=2时候,称为欧氏距离(Euclidean distance),当p=∞时候,称为极大距离(infty distance), 表示各个坐标的距离最大值,另外也包含夹角余弦等方法。
    一般采用欧式距离较多,但是文本分类则倾向于使用余弦来计算相似度。
  • KNN算法优点
  1. 简单易用,相比其他算法,KNN算是比较简洁明了的算法。即使没有很高的数学基础也能搞清楚它的原理。
  2. 模型训练时间快,上面说到KNN算法是惰性的,这里也就不再过多讲述。
  3. 预测效果好。
  4. 对异常值不敏感
  • KNN算法缺点
  1. 对内存要求较高,因为该算法存储了所有训练数据
  2. 预测阶段可能很慢
  3. 对不相关的功能和数据规模敏感

1.2 实例应用

1.2.1 KNN分类

  • 数据导入
iris = datasets.load_iris()
x = iris.data[:, :2] #只取前两维数据便于可视化
y = iris.target
  • 训练可视化
k_list = [1, 3, 5, 8, 10, 15]
h = 0.02
# 创建不同颜色的画布
cmap_light = ListedColormap(['orange', 'cyan', 'cornflowerblue'])
cmap_bold = ListedColormap(['darkorange', 'c', 'darkblue'])

plt.figure(figsize = (15, 14))
# 根据不同的k值进行可视化
for ind, k in enumerate(k_list):
    clf = KNeighborsClassifier(k)
    clf.fit(x, y)
    # 画出决策边界
    x_min, x_max = x[:, 0].min() - 1, x[:, 0].max() + 1
    y_min, y_max = x[:, 1].min() - 1, x[:, 1].max() + 1
    nx, ny = np.meshgrid(np.arange(x_min, x_max, h), 
                         np.arange(y_min, y_max, h))
    z = clf.predict(np.c_[nx.ravel(), ny.ravel()]).reshape(nx.shape)
    plt.subplot(321 + ind)
    #边界填充颜色
    plt.pcolormesh(nx, ny, z, cmap = cmap_light, shading='auto')
    #数据点可视化
    plt.scatter(x[:, 0], x[:, 1], c = y, cmap = cmap_bold, edgecolor = 'k', s = 20)
    plt.xlim(nx.min(), nx.max())
    plt.ylim(ny.min(), ny.max())
    plt.title("k = %i"%k)
plt.show()

在这里插入图片描述

1.2.3 莺尾花KNN分类

  • 导入数据
iris = datasets.load_iris()
x = iris.data
y = iris.target
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2)
#设置参数k(n_neighbors)=5, 使用欧式距离(metric=minkowski & p=2)
clf = KNeighborsClassifier(n_neighbors=2, p=2, metric='minkowski')
clf.fit(x_train, y_train)
  • 训练预测
x_predict = clf.predict(x_test)
acc = sum(x_predict == y_test) / x_predict.shape[0]
print("the accuracy of prediction: %.3f"%acc)
the accuracy of prediction: 0.967

1.2.4 KNN回归

  • 载入数据
np.random.seed(0)
# 对40个 (0, 1) * 5 数据进行升序训练   500个(0, 5)等差作为测试
x = np.sort(5 * np.random.rand(40, 1), axis = 0)
T = np.linspace(0, 5, 500)[:, np.newaxis]   #np.newaxis -> 一维变二维
#使用sin函数得到y值,并拉伸到一维
y = np.sin(x).ravel()
# Add noise to targets[y值增加噪声]
y[::5] += 1 * (0.5 - np.random.rand(8))

在这里插入图片描述

  • 预测&可视化
kn = [1, 3, 5, 8, 10, 40]
plt.figure(figsize = (10, 20))
for i, k in enumerate(kn):
     # 默认使用加权平均进行计算predictor
    clf = KNeighborsRegressor(n_neighbors=k, p = 2, metric = "minkowski")
    clf.fit(x, y)
    
    #预测
    y_pred = clf.predict(T)
    plt.subplot(6, 1, i + 1)
    plt.scatter(x, y, color ='red', label = 'data')
    plt.plot(T, y_pred, color = 'navy', label = 'prediction')
    plt.axis('tight')
    plt.legend()
    plt.title("KNeighborsRegressor (k = %i)"%(k))
plt.tight_layout()
plt.show() 

在这里插入图片描述

  • 结论: k= 1 >>> 过拟合
    当k=40时,预测的结果和最近的40个样本相关,因为我们只有40个样本,此时是所有样本的平均值,此时所有预测值都是均值,很容易发生欠拟合。
    一般情况下,使用knn的时候,根据数据规模我们会从[3, 20]之间进行尝试,选择最好的k,例如上图中的[3, 10]相对1和40都是还不错的选择。

1.2.5

参考资料

1.https://zhuanlan.zhihu.com/p/25994179 一文搞懂k近邻(k-NN)算法(一)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值