OpenCV入门(三十一)快速学会OpenCV 30 K近邻算法
嘿,大家好!今天让我们一起来聊聊机器学习中的“大拿”——K近邻算法(K-NN)。这可是机器学习界的一位“元老级”人物,简单到几乎可以说是“暴力美学”的存在!它的核心思想就像“找邻居”一样,谁离它最近,它就跟谁学。
比如说,你看到两个长得越来越像的人,你肯定会认为他们是父子,对吧?这就是K近邻算法的精髓:根据特征(如身高、体重等)的距离来分类。听起来很简单,但它的“威力”可不容小觑!
在代码实例中,作者用OpenCV的K近邻模块,把数据分成两组,左下方一组,右上方一组。然后随机生成一个点,判断它属于哪一组。这就像在玩“连连看”,看看哪个邻居更“亲近”!
那么,这个算法在实际生活中有哪些“用武之地”呢?比如,推荐电影时,K近邻会根据你的喜好找到最相似的用户,推荐他们喜欢的电影;在医疗诊断中,根据症状找到最相似的病例进行诊断。是不是很神奇?
不过,K近邻也不是“万能钥匙”。比如,它在处理大数据时可能会“力不从心”,因为计算距离会变得非常耗时。这也是为什么在实际应用中,我们常常会结合一些优化策略,比如降维或者空间划分,让它在大数据时代也能“游刃有余”。
下次当你在用推荐系统时,不妨想一想,这背后的“英雄”是不是K近邻呢?
OpenCV入门(三十一)快速学会OpenCV 30 K近邻算法
- 1.K近邻算法概述
- 2.代码实例
作者:Xiou
1.K近邻算法概述
机器学习算法是从数据中产生模型,也就是进行学习的算法(下文也简称为算法)。我们把经验提供给算法,它就能够根据经验数据产生模型。在面对新的情况时,模型就会为我们提供判断(预测)结果。例如,我们根据“个子高、腿长、体重轻”判断一个孩子是个运动员的好苗子。把这些数据量化后交给计算机,它就会据此产生模型,在面对新情况时(判断另一个孩子能不能成为运动员),模型就会给出相应的判断。
比如,要对一组孩子进行测试,首先就要获取这组孩子的基本数据。这组数据包含身高、腿长、体重等数据,这些反映对象(也可以是事件)在某个方面的表现或者性质的事项,被称为属性或特征。而具体的值,如反映身高的“188 cm”就是特征值或属性值。这组数据的集合“(身高=188 cm,腿长=56 cm,体重=46 kg), ……,(身高=189cm,腿长=55 cm,体重=48 kg)”,称为数据集,其中每个孩子的数据称为一个样本。
从数据中学得模型的过程称为学习(learning)或者训练(training)。在训练过程中所使用的数据称为训练数据,其中的每个样本称为训练样本,训练样本所组成的集合称为训练集。
当然,如果希望获取一个模型,除了有数据,还需要给样本贴上对应的标签(label)。例如,“((个子高、腿长、体重轻),好苗子)”。这里的“好苗子”就是标签,通常我们将拥有了标签的样本称为“样例”。
学得模型后,为了测试模型的效果,还要对其进行测试,被测试的样本称为测试样本。输入测试样本时,并不提供测试样本的标签(目标类别),而是由模型决定样本的标签(属于哪个类别)。比较测试样本预测的标签与实际样本标签之间的差别,就可以计算出模型的精确度。
大多数的机器学习算法都来源于日常生活实践。K近邻算法是最简单的机器学习算法之一,主要用于将对象划分到已知类中,在生活中被广泛使用。例如,教练要选拔一批长跑运动员,如何选拔呢?他使用的可能就是K近邻算法,会选择个子高、腿长、体重轻,膝、踝关节围度小,跟腱明显,足弓较大者作为候选人。他会觉得这样的孩子有运动员的潜质,或者说这些孩子的特征和运动员的特征很接近。
K近邻算法的本质是将指定对象根据已知特征值分类。例如,看到一对父子,一般情况下,通过判断他们的年龄,能够马上分辨出哪位是父亲,哪位是儿子。这是通过年龄属性的特征值来划分的。
K近邻算法在获取各个样本的特征值之后,计算待识别样本的特征值与各个已知分类的样本特征值之间的距离,然后找出k个最邻近的样本,根据k个最邻近样本中占比最高的样本所属的分类,来确定待识别样本的分类。
2.代码实例
在OpenCV中,不需要自己编写复杂的函数实现K近邻算法,直接调用其自带的模块函数即可。本节通过一个简单的例子介绍如何使用OpenCV自带的K近邻模块。
代码实例(1):演示OpenCV自带的K近邻模块的使用方法。
本例中有两组位于不同位置的用于训练的数据集,如图20-14所示。两组数据集中,一组位于左下角;另一组位于右上角。随机生成一个数值,用OpenCV中的K近邻模块判断该随机数属于哪一个分组。
上述两组数据中,位于左下角的一组数据,其x、y坐标值都在(0, 30)范围内。位于右上角的数据,其x、y坐标值都在(70, 100)范围内。根据上述分析,创建两组数据,每组包含20对随机数(20个随机数据点):
● 第1组随机数rand1中,其x、y坐标值均位于(0, 30)区间内。
● 第2组随机数rand2中,其x、y坐标值均位于(70, 100)区间内。接下来,为两组随机数分配标签:
● 将第1组随机数对划分为类型0,标签为0。
● 将第2组随机数对划分为类型1,标签为1。然后,生成一对值在(0, 100)内的随机数对:
test = np.random.randint(0, 100, (1, 2)).astype(np.float32)
最后,使用OpenCV自带的K近邻模块判断生成的随机数对test是属于rand1所在的类型0,还是属于rand2所在的类型1。
代码实例:
import cv2
import numpy as np
import matplotlib.pyplot as plt# 用于训练的数据
# rand1数据位于(0,30)
rand1 = np.random.randint(0, 30, (20, 2)).astype(np.float32)
# rand2数据位于(70,100)
rand2 = np.random.randint(70, 100, (20, 2)).astype(np.float32)
# 将rand1和rand2拼接为训练数据
trainData = np.vstack((rand1, rand2))
# 数据标签,共两类:0和1
# r1Label对应着rand1的标签,为类型0
r1Label = np.zeros((20, 1)).astype(np.float32)
# r2Label对应着rand2的标签,为类型1
r2Label = np.ones((20, 1)).astype(np