监督学习——使用OpenCV实现k-NN

监督学习——使用OpenCV实现k-NN

使用OpenCV,通过cv2.ml.KNearest_create函数创建k-NN模型,分以下步骤进行:

  1. 生成一些训练数据
  2. 指定k值,创建一个k-NN对象
  3. 找到想要分类的新数据点的k个最近邻的点
  4. 使用多数投票来分配新数据点的类标签
  5. 画出结果图

引入所须的模块:
使用k-NN算法的OpenCV、处理数据的NumPy、用于绘图的Matplotlib。
本次使用的Jupyter Notebook,需调用%matplotlib inline命令。

import numpy as np
import cv2
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use('ggplot')  #画图风格选择

若出现No module named 'cv2'错误,则说明未安装该模块,需在命令提示符终端输入下方代码

pip install opencv-python
pip install opencv-python -i https://pypi.tuna.tsinghua.edu.cn/simple

下载过程中若报错,则输入下方代码更新pip版本

python -m pip install --upgrade pip -i https://pypi.tuna.tsinghua.edu.cn/simple

生成训练数据

定义生成数据的函数,输入是要生成的数据点个数(num_samples)和每个数据点的特征数(num_features),所创建的数据矩阵有num_samples行、num_features列,其中每一个元素都为[0,100]范围内的一个随机整数,并创建一个所有样本在[0,2]单位内的随机整数标签值(0或1)。

def generate_data(num_samples, num_features=2):
    """Randomly generates a number of data points"""
    data_size = (num_samples, num_features)
    train_data = np.random.randint(0, 100, size=data_size)
    labels_size = (num_samples, 1)
    labels = np.random.randint(0, 2, size=labels_size)
    
    return train_data.astype(np.float32), labels

举例生成11个数据点,并随机选择它们的坐标

train_data, labels = generate_data(11)
train_data  #显示生成的数据

定义显示所有训练数据集的函数,输入为一个所有蓝色正方形的数据点列表(all_blue)和一个所有红色三角形的数据点列表(all_red):

def plot_data(all_blue, all_red):
    plt.figure(figsize=(10, 6))
    plt.scatter(all_blue[:, 0], all_blue[:, 1], c='b', marker='s', s=180)
    plt.scatter(all_red[:, 0], all_red[:, 1], c='r', marker='^', s=180)
    plt.xlabel('x coordinate (feature 1)')
    plt.ylabel('y coordinate (feature 2)')

将所有数据点分成红色数据集和蓝色数据集,使用下面命令可快速选择之前创建的labels数组中所有等于0的元素:

labels.ravel() == 0  #ravel平面化数组

将所创建train_data中对应标签为0的设置为所有蓝色数据点,标签为1的设为所有红色数据点,画出数据点:

blue = train_data[labels.ravel() == 0]
red = train_data[labels.ravel() == 1]
plot_data(blue, red)

在这里插入图片描述

训练分类器

k-NN分类器为OpenCV中ml模块的一部分,使用以下命令来创建一个新的分类器:

knn = cv2.ml.KNearest_create()

把训练数据传入到train方法中:

knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)

预测新数据点的类别

knn提供的findNearest方法很有用,可根据最近邻数据点的标签来预测新数据点的标签。
generate_data函数来生成一个新的数据点,其也会返回一个随机类别,可通过下划线 (_)让python忽略输出值。

newcomer, _ = generate_data(1)
newcomer #array([[20., 36.]], dtype=float32)

将新的数据点用绿色的圆圈表示(待确定标签),加入图中显示:

plot_data(blue, red)
plt.plot(newcomer[0, 0], newcomer[0, 1], 'go', markersize=14)

在这里插入图片描述

调用findNearest方法设置k=1,显示预测类别、最近邻点类别及距离:

ret, results, neighbor, dist = knn.findNearest(newcomer, 1)
print("Predicted label:\t", results)    #[[0.]]
print("Neighbor's label:\t", neighbor)  #[[0.]]
print("Distance to neighbor:\t", dist)  #[[290.]]

同理,设置k=6。而当k为偶数时,会有一定概率出现类别平局的现象,此时,OpenCV的k-NN将会选择数据点整体距离更近的邻居。

ret, results, neighbors, dist = knn.findNearest(newcomer, 6)
print("Predicted label:\t", results)      #[[1.]]
print("Neighbors' labels:\t", neighbors)  #[[0. 1. 1. 1. 0. 1.]]
print("Distance to neighbors:\t", dist)   #[[ 290. 1061. 1066. 2132. 2218. 2873.]]

扩大搜索范围,设置k=7,也可用以下代码预测类别:

knn.setDefaultK(7)
knn.predict(newcomer)  #(1.0, array([[1.]], dtype=float32))

而随着k值增大,其预测类别可能会发生变化。对此最简单的解决方法是尝试一组k值,并观察哪个的结果最好,具体问题具体分析。

参考书籍:《机器学习:使用OpenCV和Python进行智能图像处理》

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值