支持向量机【OpenCV&Python】

0、引言

参考书籍 《OpenCV轻松入门》——面向Python李立宗著,电子工业出版社出版
支持向量机(Support Vector,SVM)是一种二分类模型,目标是寻找一个标准(称为超平面),从而对样本数据进行分割。支持向量机是最好的现成分类器之一,这里所谓的“现成”是指分类器不加修改即可使用。

分割的原则是确保分类最优化(类别之间的间隔最大)。
当数据集较小时,使用支持向量机分类非常有效。

在对原始数据进行分类的过程中,可能无法使用线性方法实现分割。支持向量机在分类时,把无法线性分割的数据映射到映射到高维空间,然后在高维空间找到分类最优的线性分类器

1、理论基础

1.1 分类

某IT企业在2017年通过笔试、面试的形式招聘了一些员工。2018年,企业针对这批员工在过去一年的实际表现进行了测评,将他们的实际表现分别确定为A级(优秀)和B级(良好)。
这批员工的笔试、面试、等级成绩如图1所示。横坐标为笔试成绩,纵坐标为面试成绩,位于右上角的圆点表示测评成绩是A级,位于左下角的小方块表示测评成绩是B级。
图1图1

如何根据笔试和面试成绩确定哪些员工可能是未来的优秀员工呢?偷懒的做法是将笔试和面试的标准都定的很高,但是这样会漏掉某些优秀的员工。所以,要合理地确定笔试和面试成绩标准,确保能够高效地找到A类员工。
2图2

1.2 分类器

在图2中用于划分不同类型的直线。就是分类器。重点在于,寻找最优分类器
这里,离分类器最近的点到分类器的距离称为间隔(margin)。我们要做的是使间隔尽可能地大,这样分类器在处理数据时就会更加准确。
如图3所示,左下角的间隔最大。

离分类器最近的点就叫做支持向量(support vector)。正是这些支持向量,决定了分类器所在的位置。
3图3

1.3 将不可分变为可分

上述的数据十分简单,我们可以使用一条直线(线性分类器)就可以对其划分。

然而,现实生活中的大部分问题都是十分复杂的,通常情况下,支持向量机会将不那么容易分类的数据通过函数映射变为可分类的

支持向量机在处理数据时,如果在低位空间内无法完成分类,就会自动将数据映射到高维空间,使其变成线性可分的。简单来说,就是对当前数据进行映射操作。并且,支持向量机能够通过核函数有效地降低计算复杂度

1.4 概念总结

支持向量机可以处理任何维度的数据。在不同的维度下,支持向量机都会尽可能寻找类似于二维空间中的直线的线性分类器

例如,在二维空间,支持向量机会寻找一条能够划分当前数据的直线;在三维空间,支持向量机会寻找一个能够划分当前数据的平面;在更高维的空间,支持向量机会寻找一个能够划分当前数据的超平面(hyperplane)

超平面属于线性分类器。

“支持向量机”是由**“支持向量”和“机器”构成的。
“支持向量”是离分类器最近的那些点,这些点位于
“最大间隔”**上。通常情况下,分类仅依靠这些点来完成,而与其他点无关。

“机器”是指分类器。

2、案例介绍

在使用支持向量机模块时,需要先使用函数cv2.ml.SVM-create()生成用于训练的空分类器模型。该函数的语法格式为:svm = cv2.ml.SVM-create()

获取了空分类器svm后,针对该模型使用svm.train()函数对训练数据进行分类,该函数的语法格式为:训练结果 = svm.train(训练数据,训练数据排列格式,训练数据的标签)
各参数含义如下
**训练数据:**表示原始数据,用来训练分类器;
**训练数据排列格式:**原始数据的排列格式有两种,一种是按行排列(cv2.ml.ROW-SAMPLE,每一条训练数据占一行),一种是按列排列(cv2.ml.COL-SAMPLE,每一条训练数据占一列);
****训练数据的标签:**原始数据的标签;
训练结果:**训练结果的返回值。

完成对分类器的训练后,使用 🎈svm.predict() 🎈函数即可使用训练好的分类器模型对测试数据进行分类,其语法格式为:(返回值,返回结果) = svm.predict(测试数据)

在实际使用中,可能会根据需要对其中的参数进行调整。例如:可以通过setType()函数设置类别,通过setKernel()函数设置核类型,通过set设置支持向量机的参数C(惩罚系数,挤兑误差的宽容度,默认值为0)

例1:已知老员工的笔试成=成绩、面试成绩及对应的等级表现,根据新入职员工的笔试成绩、面试成绩预测其可能的表现。

2.1 生成模拟数据

######### 生成模拟数据
# 构造20组笔试成绩和模拟成绩都在[95,100)之间的数据对,在一年后对应的工作表现为A级
a = np.random.randint(95,100,(20,2)).astype(np.float32)
# 构造20组笔试成绩和模拟成绩都在[95,100)之间的数据对,在一年后对应的工作表现为B级
a = np.random.randint(95,100,(20,2)).astype(np.float32)
# 最后,将两组数据合并,并使用numpy.array对其进行数据类型转换
data = np.vstack((a,b))
data = np.array(data,dtype= 'float32')

2.2 构造分组标签

######### 构造分组标签
# 首先,为对应表现为A级的分布在[95,100)区间的数据,构造标签0
aLabel = np.zeros((20,1))
# 接下来,为对应表现为B级的分布在[90,95)区间的数据,构造标签1
bLabel = np.ones((20,1))
# 最后,将两组标签合并,并使用numpy.array对其进行数据类型转换
label = np.vstack((aLabel,bLabel))
label = np.array(label,dtype='int32')

2.3 训练

####### 训练
# 用ml机器学习模块SVM_create()创建svm
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)

2.4 分类

####### 分类
# 生成两个随机的数据对(笔试成绩,面试成绩)用于测试。可以用随机数,也可以直接指定两个数字。
# 这里,我们生成两组笔试成绩和面试成绩差别较大的数据。
test = np.vstack([[98,90],[90,99]])
test = np.array(test,dtype='float32')

######## 使用函数svm.predict()对随机成绩进行分类
(p1,p2) = svm.predict(test)

2.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()

#### 将测试数据和预测分类显示出来
print (test)
print (p2)

2.6 完整程序

###################################################################33
import cv2
import numpy as np
import matplotlib.pyplot as plt

######### 第一步,准备数据
# 构造20组笔试成绩和模拟成绩都在[95,100)之间的数据对,在一年后对应的工作表现为A级
a = np.random.randint(95,100,(20,2)).astype(np.float32)
# 构造20组笔试成绩和模拟成绩都在[95,100)之间的数据对,在一年后对应的工作表现为B级
b = np.random.randint(95,100,(20,2)).astype(np.float32)
# 最后,合并数据,并使用numpy.array对其进行数据类型转换
data = np.vstack((a,b))
data = np.array(data,dtype= 'float32')

######### 第二步,构造分组标签,0代表A级,1代表B级
# 首先,为对应表现为A级的分布在[95,100)区间的数据,构造标签0
aLabel = np.zeros((20,1))
# 接下来,为对应表现为B级的分布在[90,95)区间的数据,构造标签1
bLabel = np.ones((20,1))
# 最后,合并标签,并使用numpy.array对其进行数据类型转换
label = np.vstack((aLabel,bLabel))
label = np.array(label,dtype='int32')

####### 第三步,训练
# 用ml机器学习模块SVM_create()创建svm
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)

####### 第四步,预测
# 生成两个随机的数据对(笔试成绩,面试成绩)用于测试。可以用随机数,也可以直接指定两个数字。
# 这里,我们生成两组笔试成绩和面试成绩差别较大的数据。
test = np.vstack([[98,90],[90,99]])
test = np.array(test,dtype='float32')

######## 使用函数svm.predict()对随机成绩进行预测
(p1,p2) = svm.predict(test)

###### 第五步,可视化
# 将训练数据、测试数据在图像上表示出来
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)

2.7 运行结果

运行结果1:
在这里插入图片描述在这里插入图片描述
运行结果2:
在这里插入图片描述在这里插入图片描述
因为我们采用随机方式生成数据,所以每次运行时所生成的数据会有所不同,运行结果也会有所差异。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值