初探监督学习:使用OpenCV实现 k-NN 机器学习算法(分类模型)

其实NumPy部分还是有一定要求的,已经大致看完了。本来打算先把NumPy数据分析的坑填完的。。结果最近几天一直在看机器学习,过两天争取发几篇文章把NumPy那里补完!

问题背景(太长了。简要陈述):有两个队伍(蓝色正方形和红色三角形),他们都只喜欢和相同队伍的人做邻居,根据随机的数据集(一堆蓝色正方形和红色三角形的位置关系),预测在某一点如果有一个人住,这个人是蓝队还是红队

--> 就是要判断现在的图中绿点是蓝色正方形还是红色三角形

k-NN算法可以认为是最简单的机器学习算法之一,我们只需要存储训练数据集,接下来为了对新数据点进行预测,仅需要在训练数据集中找到最近相邻对点就可以了。k-NN算法认为一个数据点很可能和它近邻的点属于同一个类,结果和所定义的“近邻”的范围有关(k个最近邻)。

接下来就是分步骤实现的代码:

step1:生成训练数据

#coding=UTF-8
import numpy as np
import cv2
import matplotlib.pyplot as plt
plt.style.use('ggplot')

# step1:生成训练数据
np.random.seed(42)
def generate_data(num_samples, num_features=2):
	data_size = (num_samples, num_features)
	data = np.random.randint(0, 100, size=data_size)
	labels_size = (num_samples, 1)
	labels = np.random.randint(0, 2, size=labels_size)
	return data.astype(np.float32), labels

这里的生成函数就返回了一个N-2维的代表这num_samples个数的数据点(x,y坐标)的数组,以及按照顺序分别代表这些点的类别的labels列表(0是蓝色正方形,1是红色三角形)

step2:测试生成函数

我又不是大佬当然需要测试一下生成函数啦!使用print大法检查生成结果

step2:测试生成函数
train_data, labels = generate_data(11)
print(train_data)
print(train_data[0], labels[0])

step3:显示生成的数据集

确认生成的数据无误之后,就可以使用Matplotlib来得到一个类似于分布地图(data_map)的东西,就可以看出随机数据的分布情况

# all_blue 代表所有都是蓝色正方形的数据点列表
# all_red  代表所有都是红色三角形的数据点列表
def plot_data(all_blue, all_red):
	# 使用matplotlib中的scatter函数来批量生成蓝色正方形数据点
	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)')

# 测试显示函数
# 使用ravel平面化labels中所有等于0的元素 - 为蓝色正方形
blue = train_data[labels.ravel() == 0]
red  = train_data[labels.ravel() == 1]
plt.title('data_map')
plot_data(blue, red)
plt.show()

注:对于plt的使用在文章末尾给出了常见参数的代表意思,比如:b、r这种代表颜色蓝色和红色,s代表正方形,^代表正三角形

np数组中的ravel()函数的作用是扁平化,我的理解就是将现在的N-1维数组labels转换为1-N的数组,这样方便操作和选择

Numpy中扁平化函数ravel()和flatten()的区别

step4:训练分类器

接下来就是使用数据来训练分类器 - opencv的操作现在还不懂。需要慢慢研究

# step4:训练分类器
# 首先创建一个新的分类器
knn = cv2.ml.KNearest_create()
# 将训练数据传入到train方法中
msg = knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)
print('"knn.train"method returns : ' + str(msg))

这里添加一个msg是为了接收训练完成的确认信息 True

step5:预测新数据点的类别

分类器训练完成之后就可以来做些事情了 - 拿一个随机生成的范围内的点来判断类别

# step5:预测新数据点的类别
# 先使用数据生成函数生成一个随机点
# 下划线_表示让Python忽略这个label类别输出值,因为我们想要使用训练得到的模型来对类别进行预测
newdata, _ = generate_data(1)
print(newdata)
# 在预测之前可以尝试画出这个newdata在原来data_map上的位置,但是不能确定类型
plot_data(blue, red)
# 可以在plt.plot函数后面添加一个分号以抑制输出
plt.plot(newdata[0, 0], newdata[0, 1], 'go', markersize=14)
# 输出之后就可以看到有一个绿色的待确定的点新出现在了图上
plt.show()

# 进行预测,输出预测结果 = 1 代表对比的范围
ret, results, neighbor, dist = knn.findNearest(newdata, 6)
print('预测的类别结果为:(0:蓝色正方形 1:红色三角形)\t', results)
print('邻居的类别为:\t', neighbor)
print('和邻居的距离:\t', dist)
print(results[0, 0])
# 将最终预测的结果呈现在data_map上
if results[0, 0] is 0.0:
	plt.plot(newdata[0, 0], newdata[0, 1], c='b', marker='s', markersize=14)
elif results[0, 0] is 1.0:
	plt.plot(newdata[0, 0], newdata[0, 1], 'r^', markersize=14)
plot_data(blue, red)
plt.show()

整个过程中一共使用了三次matplotlib,可见掌握matplotlib的重要性!!!

三个图是呈连续的:

 

最后可以看到,当k=3时预测的结果是0,即为蓝色正方形

可以看到。。第三张图是错误的显示,但是判断条件什么的都没错吧,而且分类器产生的结果相对于条件来说也是正确的,因此我认为是我的matplotlib水平过低导致的bug。

学习一下matplotlib:
https://blog.csdn.net/mmc2015/article/details/47746195

https://blog.csdn.net/mmc2015/article/details/48222611

https://blog.csdn.net/qiu931110/article/details/68130199

猜你喜欢

转载自blog.csdn.net/weixin_43826242/article/details/88983620