目录
这个想法是在特征空间中搜索测试数据的最近邻。我们将用下面的图片来研究它。
在图像中,有两个族,蓝色(正方形)和红色(三角形)。我们称每一种为 “ 类 ”。现在有一个新成员进入,显示为绿色(圆形)。他应该被添加到蓝色还是红色中,我们称该过程为 “ 分类 ” 。
我们需要做的就是通过kNN近邻算法进行分类操作,因此让我们应用此算法。
这种方法是检查谁是他的 最近邻(离的最近)。从图像中可以明显看出它是红色(三角形)类 。因此,他也被添加到了红色(三角形)类 中。此方法简称为 “ 最近邻 ”,因为分类仅取决于 “ 最近邻 ”。
但这是有问题的。红色(三角形)可能是最近的。但是,如果附近有很多蓝色(正方形)怎么办?然后,蓝色(正方形)在该地区的权重比红色(三角形)更大。因此,仅检查最接近的 1 个是不够的。相反,我们检查 k 个 “ 近邻 ”,那么,谁占的多,新样本就属于那个 “ 类 ” 。
假如在我们的图像中,让我们取 k = 3 ,即检查 3 个 “ 近邻 ”。他有 1 个蓝色(正方形)和 2 个红色(三角形)(有两个等距的蓝色(正方形),但是由于 k = 3 ,我们只取其中一个),所以他又应该加入红色(三角形)类 。但是,如果我们取 k = 7 怎么办?然后,他有 5 个蓝色(正方形)和 2 个红色(三角形),现在,他应该加入蓝色(正方形)类 。因此,所有这些都随 k 的值而变化。更有趣的是,如果 k = 4 怎么办?他有 2 个蓝色(正方形) 和2个红色(三角形),这是一个平滑!因此最好将 k 作为奇数。由于分类取决于 k 个最近的 “ 类 ”,因此该方法称为 “ k近邻 ” 。
同样,在kNN中,我们确实在考虑 k 个近邻(离的最近),但我们对所有人都给予同等的重视,对吧?这公平吗?例如,以 k = 4 的情况为例。我们说这是平局。但是请注意,这1个红色(三角形)比其他2个蓝色(正方形)离他更近。因此,他更应该被添加到红色(三角形)类 中。那么我们如何用数学解释呢?我们根据 “ 类 ” 到新成员的距离来给他们一些权重。对于那些靠近他的 “ 类 ” ,权重增加,而那些远离他的 “ 类 ” ,权重减轻。然后,我们分别添加每个 “ 类 ” 的总权重。谁得到的总权重最高,新成员归为那个 “ 类 ” 。
就像上面一样,我们将在这里做一个简单的例子,有两个 “ 类 ” 。在这里,我们将红色系列标记为 “ Class_0 ”(0表示),将蓝色系列标记为 “ Class_1 ”(1表示)。我们创建 25 个随机数(随机坐标),并将它们标记为 “ 0类 ” 或 “ 1类 ” 。我们借助Numpy中的Random Number Generator来完成所有这些工作。然后我们在Matplotlib的帮助下对其进行绘制。红色系列显示为三角形,蓝色系列显示为正方形。
- # 导入OpenCV库
- import cv2 as cv
-
- # 导入NumPy库,用于进行矩阵和数组的计算
- import numpy as np
-
- # 导入matplotlib的pyplot模块,用于数据的可视化
- import matplotlib.pyplot as plt
-
- # 使用NumPy的random.randint函数生成25个随机的二维向量,每个向量的元素值在0到100之间
- # 这些向量组成训练数据集,每个向量是一个样本,包含两个特征(x和y值)
- # astype(np.float32)将整数转换为浮点数,以便在计算时获得更高的精度
- trainData = np.random.randint(0,100,(25,2)).astype(np.float32)
-
- # 使用NumPy的random.randint函数生成25个随机的一维向量,每个向量的元素值在0到2之间,表示样本的标签(红色或蓝色)
- responses = np.random.randint(0,2,(25,1)).astype(np.float32)
-
- # 使用布尔索引从训练数据中选择标签为0(红色)的样本
- red = trainData[responses.ravel()==0]
-
- # 使用matplotlib的scatter函数绘制红色样本的散点图,参数80设定散点的大小,'r'设定散点的颜色,'^'设定散点的形状
- plt.scatter(red[:,0],red[:,1],80,'r','^')
-
- # 使用布尔索引从训练数据中选择标签为1(蓝色)的样本
- blue = trainData[responses.ravel()==1]
-
- # 使用matplotlib的scatter函数绘制蓝色样本的散点图,参数80设定散点的大小,'b'设定散点的颜色,'s'设定散点的形状
- plt.scatter(blue[:,0],blue[:,1],80,'b','s')
-
- # 使用matplotlib的show函数显示绘制的图像
- plt.show()
我们将在OpenCV中的kNN的帮助下,将一个新成员带入,并将其进行 “ 分类 ” 。
- # 导入OpenCV库,并重命名为cv。OpenCV是一个开源的计算机视觉和机器学习软件库。
- import cv2 as cv
-
- # 导入NumPy库,并重命名为np。NumPy是一个用于大型多维数组和矩阵的数学运算的库,提供了数学函数来操作这些数组。
- import numpy as np
-
- # 导入matplotlib的pyplot模块,并重命名为plt。matplotlib是一个用于创建静态、动态、交互式和实时图表的Python库。
- import matplotlib.pyplot as plt
-
- # 使用NumPy的random.randint函数生成25个随机的二维向量,每个向量的元素值在0到100之间。
- # 这些向量组成训练数据集,每个向量是一个样本,包含两个特征(x和y值)。
- # astype(np.float32)将整数转换为浮点数,以便在计算时获得更高的精度。
- # 包含(x,y)值的25个已知/训练数据的特征集
- trainData = np.random.randint(0,100,(25,2)).astype(np.float32)
-
- # 使用NumPy的random.randint函数生成25个随机的一维向量,每个向量的元素值在0到2之间,表示样本的标签(红色或蓝色)。
- # 用数字0和1分别标记红色或蓝色
- responses = np.random.randint(0,2,(25,1)).astype(np.float32)
-
- # 使用布尔索引从训练数据中选择标签为0(红色)的样本
- red = trainData[responses.ravel()==0]
-
- # 使用matplotlib的scatter函数绘制红色样本的散点图,参数30设定散点的大小,'r'设定散点的颜色,'^'设定散点的形状。
- plt.scatter(red[:,0],red[:,1],30,'r','^')
-
- # 使用布尔索引从训练数据中选择标签为1(蓝色)的样本
- blue = trainData[responses.ravel()==1]
-
- # 使用matplotlib的scatter函数绘制蓝色样本的散点图,参数80设定散点的大小,'b'设定散点的颜色,'s'设定散点的形状。
- plt.scatter(blue[:,0],blue[:,1],80,'b','s')
-
- # 使用NumPy的random.randint函数生成1个随机的二维向量,每个向量的元素值在0到100之间。这个向量代表新的样本点。
- newcomer = np.random.randint(0,100,(1,2)).astype(np.float32)
-
- # 使用matplotlib的scatter函数绘制新样本点的散点图,参数80设定散点的大小,'g'设定散点的颜色,'o'设定散点的形状。
- plt.scatter(newcomer[:,0],newcomer[:,1],80,'g','o')
-
- # 使用OpenCV的ml.KNearest_create函数创建一个KNN分类器对象。KNN是一种监督学习算法,可以用于分类和回归。
- knn = cv.ml.KNearest_create()
-
- # 使用KNN分类器的train函数训练模型,输入参数为训练数据、样本类型(cv.ml.ROW_SAMPLE表示每行是一个样本)和训练数据的标签。
- knn.train(trainData, cv.ml.ROW_SAMPLE, responses)
-
- # 使用KNN分类器的findNearest函数进行预测,输入参数为新数据和k值(这里设置为3)。返回值为四个值:ret(返回状态,如果返回值为1表示预测成功)、results(预测结果)、neighbours(最近邻样本的索引)和dist(最近邻样本的距离)。
- ret, results, neighbours ,dist = knn.findNearest(newcomer, 3)
-
- # 打印预测结果。这是一个新样本的标签。
- print( "result: {}\n".format(results) )
-
- # 打印最近邻样本的索引。这是一个新样本的三个最近邻样本在训练数据集中的索引。
- print( "neighbours: {}\n".format(neighbours) )
-
- # 打印最近邻样本的距离。这是一个新样本与它的三个最近邻样本的距离。
- print( "distance: {}\n".format(dist) )
-
- # 使用matplotlib的show函数显示绘制的图像。
- plt.show()
由上面的我们定义,将红色系列标记为 “ 0类 ” ,将蓝色系列标记为 “ 1类 ” 。从下面的图片我们可以看出,新成员绿色(圆形),他有 2 个蓝色(正方形)和 1 个红色(三角形),所以他又应该加入蓝色(正方形)类 ,也就是 “ 1类 ” 。