《opencv》在第一章主要是介绍了环境相关的知识,如:anaconda、jupyter、python等,以及github上关于本书的代码和一个anaconda环境。这个环境是作者专门为本书所构建的,里面包含了所必须的一些包及其版本信息。遗憾的是对于现在2019.11.2已经过时了,里面所有包的版本都落后当前最新版本太多了。而anaconda中默认安装的都是比较新的版本。尝试了下创建提供的环境没有成功,所以放弃了。
第二章主要简单介绍了一些基本的工具,如NumPy,在Python中载入外部数据、Matplotlib进行数据可视化。都是介绍一点点东西。
第三章第一节主要介绍的是模型性能评估的一些指标和方法。但是本书的学习思路是用到什么再去学,所以模型都还没有,评估模型性能的知识就往后稍稍,大概看了下,敲了一下指令就过去了。
3.2节使用k-nn分类模型预测类别。书中给的例子很有意思。一个小镇上两只球队:红队和蓝队。各自再小镇上有自己的球迷,两队的球迷彼此是互相看不顺眼的。他们不愿做邻居,久而久之,两队的球迷逐渐各自的聚居区。一个外地的推销员来到小镇推销体育用品。他知道如果他给红队球迷推销蓝队的商品,那么他可能会有麻烦,反之亦然。于是他掌握了小镇所有居民的位置。但是某一天小镇出现了新居民,推销员需要知道他的成分。于是他使用了一个分类模型:k-nn分类模块。他将所有居民的坐标以及成分输入到模型中进行训练,然后再将新居民的坐标输入给模型,他期望这个模型能给他一个正确的结果。
首先需要准备当前居民的位置坐标以及成分信息,即这个居民是红色的还是蓝色的。坐标包括横、纵两个feature值,而其成分只有两种,用0表示蓝、1表示红。通过numpy的random方法生成:
def generate_data(num_samples, num_features, seed):
np.random.seed(seed)
data_size = (num_samples, num_features)
data = np.random.randint(0, 100, data_size)
label_size = (num_samples, 1)
label = np.random.randint(0,2,label_size)
return data.astype(np.float32), label
num_samples表示居民的数量,num_features值固定为2。seed为随机数种子,指定一个随机数种子,这样可以使每次生成的随机数都一样。坐标的范围为0-100。
将上面生成的数据通过下面的方法,就可以看到小镇居民的居住位置了。
def plot_data(blue, red):
plt.style.use('ggplot')
plt.scatter(blue[:,0], blue[:,1],c = 'b', marker = 's', s = 180)
plt.scatter(red[:,0], red[:,1],c = 'r', marker = '^', s = 180)
plt.xlabel('x coordinate')
plt.ylabel('y coordinate')
blue为蓝色成分的居民数组,red为红色成分的居民
通过generate_data生成一个测试居民,如下:
绿色圆圈就是测试居民。
为了使用knn模型,首先需要通过训练数据来训练模型:
knn = cv2.ml.KNearest_create()
res = knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)
opencv已经给我们提供了knn分类器,并提供了训练的接口,我们只需要输入训练数据就可以了
模型训练成功后,就可以拿来进行预测了:
ret, results, neighbor, dist = knn.findNearest(newcomer, 1)
print(results)
print(neighbor)
print(dist)
输出结果为:
[[1.]]
[[1.]]
[[113.]]
knn算法的本质就是寻找最近的k个邻居,分析这k个邻居的类型,找出居民最多的类型,那么新居民为归类为这种类型。上面findNearest()方法中的第二个参数就是k值。设为1表示寻找离新居民最近的居民,将新居民的类型划分为该居民的类型。上述输出结果的含义分别为:新居民的类型(0为蓝色、1为红色)、最近的k个邻居的类型、新居民与k个邻居的距离。
将k值设为3,结果为:
[[1.]]
[[1. 0. 1.]]
[[113. 145. 260.]]
分类的结果为1,即红色
将k值设为6,结果为:
[[1.]]
[[1. 0. 1. 1. 1. 0.]]
[[ 113. 145. 260. 612. 712. 1009.]]
6个邻居中有4个位红色,所以新居民也为红色
如果k个邻居中红色和蓝色的数量一样,则需要比较距离,即第三个输出结果。
结论:knn是通过计算测试数据与训练数据的距离(一般多用欧式距离)得到K个邻居,再根据这些邻居的类型进行计数,计数结果最多的类型为测试数据的预测类型。原理非常简单,实现方式也很简单。无愧为最容易描述和理解的机器学习算法之一。