支持向量机是智能算法中的一个重要内容,在OpenCV中的使用是很简单的,直接调用cv2.ml系列函数即可。本文通过一个二维的数据来演示一下SVM的使用。
[TOC]
SVM基本使用流程
在使用支持向量机模块时,需要先使用函数cv2.ml.SVM_create()
生成用于后续训练的空分类器模型。
svm = cv2.ml.SVM_create()
获取空分类器之后,针对该模型使用svm.train()
函数对训练数据进行训练。语法格式:
训练结果 = svm.train(训练数据,训练数据排练格式,训练数据的标签)
- 训练数据:表示原始数据,用来训练分类器。例如前面说到的研究生录取,初试成绩、面试成绩都是原始的训练数据。
- 训练数据排练格式:原始数据的排列形式有
按行排列
(cv2.ml.ROW_SAMPLE,每一条训练数据占一行)和按列排列
(cv2.ml.COL_SAMPLE,每一条训练数据占一列),两种,根据数据的排列情况合理选择即可。 - 训练数据的标签:原始数据的标签
- 训练结果:训练结果的返回值
完成对分类器进行训练后,使用svm.predict()
函数即可使用训练好的分类器模型对测试数据进行分类。语法:
(返回值, 返回结果) = svm.predict(测试数据)
以上为基本使用方法,在实际使用中,会对参数进行适当调整。例如使用setType()
函数设置类别,用setKernel()
函数设置核类型,用setC()
函数设置支持向量机的参数C(惩罚系数,对错误的宽容度,默认为0)。
SVM案例演示
例如:已知老员工的笔试成绩、面试成绩以及对应的等级,现在根据新入职员工的笔试成绩和面试成绩来预测其可能的表现。
1、生成原始的训练数据
模拟生成数据,一年后表现为A级的员工入职时的笔试和面试成绩。构造20组笔试和面试成绩都分布在[95,100)区间的数据对:
a = np.random.randint(95,100,(200,2).astype(np.float32))
模拟生成数据,一年后表现为B级的员工入职时的笔试和面试成绩。构造20组笔试和面试成绩都分布在[90,95)区间的数据对:
b = np.random.randint(90,95,(200,2).astype(np.float32))
最后,将两组数据进行合并,并使用numpy.array对其进行类型转换:
data = np.vstack((a,b))
data = np.array(data,dtype='float32')
2、构造分组标签
首先,将分布在[95,100)区间的数据,构造标签“0”:
aLabel = np.zeros((20,1))
将分布在[90,95)区间的数据,构造标签“1”:
bLabel = np.ones((20,1))
最后,将两组数据进行合并,并使用numpy.array对其进行类型转换:
label = np.vstack((aLabel,bLabel))
label = np.array(label,dtype='int32')
3、训练
用支持向量机模块对已知的数据和其对应的标签进行训练。
result = svm.train(data,cv2.ml.ROW_SAMPLE,label)
4、分类
生成两个随机的数据对(笔试成绩、面试成绩)用于测试。
这里,尝试观察笔试和面试成绩差别比较大的数据如何分类。用如下语句生成成绩。
test = np.vstack([[98,90],[90,99]])
test = np.array(test,dtype='float32')
最后,对成绩进行分类:
(p1,p2) = svm.predict(test)
5、显示分类结果
#可视化
plt.scatter(a[:,0], a[:,1], 80, 'g', 'o')
plt.scatter(b[:,0], b[:,1], 80, 'b', 's')
plt.scatter(test[:,0], test[:,1], 80, 'r', '*')
plt.show()
完整代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
#第1步 准备数据
# A等级的笔试、面试分数
a = np.random.randint(95,100, (20, 2)).astype(np.float32)
# B等级的笔试、面试分数
b = np.random.randint(90,95, (20, 2)).astype(np.float32)
#合并数据
data = np.vstack((a,b))
data = np.array(data,dtype='float32')
#第2步 建立分组标签,0代表A等级,1代表B等级
#aLabel对应着a的标签,为类型0-等级A
aLabel=np.zeros((20,1))
#bLabel对应着b的标签,为类型1-等级B
bLabel=np.ones((20,1))
#合并标签
label = np.vstack((aLabel, bLabel))
label = np.array(label,dtype='int32')
#第3步 训练
# ml 机器学习模块 SVM_create() 创建
svm = cv2.ml.SVM_create()
# 属性设置,直接采用默认值即可。
#svm.setType(cv2.ml.SVM_C_SVC) # svm type
#svm.setKernel(cv2.ml.SVM_LINEAR) # line
#svm.setC(0.01)
# 训练
result = svm.train(data,cv2.ml.ROW_SAMPLE,label)
#第4步 预测
#生成两个随机的(笔试成绩、面试成绩),可以用随机数生成
test = np.vstack([[99,90],[90,99]]) #0-A级 1-B级
test = np.array(test,dtype='float32')
#预测
(p1,p2) = svm.predict(test)
#第5步 观察结果
#可视化
plt.scatter(a[:,0], a[:,1], 80, 'g', 'o')
plt.scatter(b[:,0], b[:,1], 80, 'b', 's')
plt.scatter(test[:,0], test[:,1], 80, 'r', '*')
plt.show()
#打印原始测试数据test,预测结果
print(test)
print(p2)
运行结果:
[[99. 90.]
[90. 99.]]
[[1.]
[1.]]
根据上面分类,可知:
笔试99,面试90为B类
笔试90,面试99为B类