(二)k近邻学习
基本描述
描述: k近邻(kNN)学习是一种常见的监督学习算法
工作机制
给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个 “邻居” 的信息来进行预测
通常,在分类任务中,可以使用 “投票法” ,即选择k个样本的实值输出标记的平均值作为预测结果;
还可以基于距离的远近进行加权平均或加权投票,即距离越近的样本权重越大
惰性学习: 即此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理
优点: 天然的可以解决多分类问题,思想简单,但效果强大
缺点: 效率低下,高度数据相关,预测结果不具有可解释性,维数灾难
编程实现
最简单的思想
KNN的原理就是当预测一个新的值x的时候,根据它距离最近的K个点是什么类别来判断x属于哪个类别
例如图中原有多个训练点带有不同的标签,分别分为红、蓝、绿三种类型,我们引入一个新的X点,要如何判断这个点的归类呢?在二维坐标中,我们就可以通过计算X点与原坐标轴中所有点的距离,然后从小到大进行排列,选取前5(K)个数据,根据这5(K)个数据中,计算投票出最多的标记进行分类,可以看出,图中X点的前5个数据中有4个为红色,1个绿色,0个蓝色,所以根据kNN我们可以预测X点为红色类。
下面,我们根据这个思想,来一个简单的实现:
首先,我们先导入接下来所需要用到的包:
①sklearn中导入datasets,它可以为我们提供作为训练、测试用的数据集
②导入numpy包
③导入matplotlib.pyplot包,作为绘制接口
from sklearn import datasets
import numpy as np
import matplotlib.pyplot as plt
接下来,我们创建一个数据集:
raw_data_X = [[3.393, 2.331],
[3.110, 1.781],
[1.348, 1.368],
[2.312, 3.231],
[1.231, 3.124],
[4.345, 5.324],
[6.424, 3.423],
[7.291, 5.124],
[4.431, 7.924],
[3.931, 6.104]
]
raw_data_y = [0, 0, 0, 0, 0, 1, 1, 1, 1, 1]
让X_train,y_train分别等于上面我们创建的数据集:
X_train = np.array(raw_data_X)
y_train = np.array(raw_data_y)
可以看到:
利用绘制接口进行绘制:
plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1],color="g")
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1],color="r")
plt.show()
创建一个新的x点,来作为测试样本:
x = np.array([3.423, 6.241])
再次进行绘制:
plt.scatter(X_train[y_train==0,0], X_train[y_train==0,1],color="g")
plt.scatter(X_train[y_train==1,0], X_train[y_train==1,1],color="r")
plt.scatter(x[0], x[1] ,color="b")
plt.show()
可以看到,新引入的点更靠近红色部分
接下来我们实现一个简单的kNN进行分类:
from math import sqrt
distances = []
for x_train in X_train:
d = sqrt(np.sum(x_train - x) ** 2)
distances.append(d)
这里使用的是欧拉距离
排序:
nearest = np.argsort(distances)
设置k等于6:
k = 6
topK_y = [y_train[i] for i in nearest[:k]]
对计算出并排列好的距离进行投票:
from collections import Counter
Counter(topK_y)#将数组中存在的元素做一个统计(计数、投票)
找出票数最多的元素:
votes = Counter(topK_y)
votes.most_common(1)#找出票数最多的()个元素,返回一个数组
votes.most_common(1)[0][0]#取出我们感兴趣的数据
predict_y = votes.most_common(1)[0][0]#将结果存在