在opencv中支持SVM分类器,过程就是:先训练再预测(python实现)
# svm 对于数据的要求: 所有的数据都要有label # [155,48] -- 0 女生 [152,53] ---1 男生 # 监督学习 0 负样本 1 正样本
步骤一:获取训练样本
#1.获取训练样本,2类
row = 30
data1 = np.ones((row,2))+np.random.rand(row,2) #[1,2) 1.5为中心
data2 = np.ones((row,2))*(-2)+np.random.rand(row,2) #[-2,-1) -1.5为中心
plt.figure(1)
plt.plot(data1[:,0],data1[:,1],'o')
plt.plot(data2[:,0],data2[:,1],'o')
#data = np.vstack(data1, data2) #报错
data = np.vstack((data1,data2)) #将两种训练样本合并,这里无法转float32格式,所以才有下一行代码
data = np.array(data,dtype='float32') #将训练样本转换成要求的float32格式才可以
步骤二:获取训练标签
#2.获取标签
label_data1 = np.zeros((row,1),dtype='int32') #将训练标签转换成要求的int32格式才可以
label_data2 = np.ones((row,1),dtype='int32')
label = np.vstack((label_data1,label_data2)) #行堆积,另起一行,得到一个60x2的数组
label = np.array(label,dtype='int32') #这句话可有可无,因为label_data1和label_data2已声明int32类型
步骤三:创建分类器
#3.创建分类器
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(cv2.ml.SVM_C_SVC)
步骤四:进行训练
#4.进行训练
res = svm.train(data,cv2.ml.ROW_SAMPLE,label)
print("训练成功与否res的值",res) #输出:True
步骤五:进行预测
#5.进行预测
pre = np.random.rand(20,2)*4-2 #测试样本:20个点[-2,2)
pre = np.array(pre,dtype='float32') #将测试样本转换成要求的float32格式才可以
(par1,res) = svm.predict(pre) #返回值两个参数
print("预测后结果res的值\n",res) #得到一个20x1的数组
输出:
预测后结果res的值
[[1.]
[0.]
[0.]
[1.]
[1.]
[1.]
[1.]
[1.]
[0.]
[1.]
[0.]
[1.]
[0.]
[1.]
[1.]
[0.]
[0.]
[1.]
[1.]
[1.]]
步骤六:结果绘图
predict通过res返回得到一个20x1的数组。每一行相应一个输入点,计算得到的值就是分类的序号,在这里是0和1我们取0.5为阈值进行分类并显示结果。
因为测试样本是20个[-2,2)范围的点,即20*2的数组为了方便比较,先将结果预测后结果res进行列堆积,由20*1转换成20*2的数组同型数组就可以进行比较输出。
#6.结果绘图
res = np.hstack((res,res)) #列堆积,另起一列,得到一个20x2的数组
pre0 = pre[res<0.5] #后续详细解释
pre1 = pre[res>=0.5]
print("pre0\n",pre0)
print("pre1\n",pre1)
print("pre0.shape:",pre0.shape) #此时两者均为一列
print("pre1.shape:",pre1.shape)
pre0 = np.reshape(pre0,(int(pre0.shape[0]/2),2)) #为了显示绘图,将一列变二列
pre1 = np.reshape(pre1,(int(pre1.shape[0]/2),2))
plt.figure(2)
plt.plot(pre0[:,0],pre0[:,1],'o') #画图plt.plot(x坐标,y坐标,'线型')
plt.plot(pre1[:, 0], pre1[:, 1], 'o')
plt.show()
输出:
pre0.shape: (24,)
pre1.shape: (16,)
pre0
[-0.33559075 1.3618486 1.7029347 0.04593408 0.3551418 1.3985409
0.75370246 -0.13495038 0.18302129 0.46836114 0.42994153 0.3347996
-0.05576663 1.3062311 1.9422737 1.8106563 0.5062942 0.6137762
1.9550579 -0.65718 0.8673214 1.4073303 1.3502296 0.88142025]
pre1
[-0.3959848 -0.9314422 0.12321403 -0.8255872 -1.9429276 -0.49432907
-1.5003582 -0.20095745 -1.786253 1.0939165 -0.68006885 -0.40214399
-1.3144214 -1.7472401 -0.6790464 -0.4059371 ]
完整代码
def svm_point():
"""
以下出现的np.array(pre,dtype='float32')作用:
指定数组或者矩阵内部数据的数据类型
"""
row = 30
#1.获取样本,2类
data1 = np.ones((row,2))+np.random.rand(row,2) #[1,2) 1.5为中心
data2 = np.ones((row,2))*(-2)+np.random.rand(row,2) #[-2,-1) -1.5为中心
plt.figure(1)
plt.plot(data1[:,0],data1[:,1],'o')
plt.plot(data2[:,0],data2[:,1],'o')
# data = np.vstack(data1, data2) #报错
data = np.vstack((data1,data2)) #将两种训练样本合并,这里无法转float32格式,所以才有下一行代码
data = np.array(data,dtype='float32') #将训练样本转换成要求的float32格式才可以
#2.获取标签
label_data1 = np.zeros((row,1),dtype='int32') #将训练标签转换成要求的int32格式才可以
label_data2 = np.ones((row,1),dtype='int32')
label = np.vstack((label_data1,label_data2)) #行堆积,另起一行,得到一个60x2的数组
label = np.array(label,dtype='int32') #这句话可有可无,因为label_data1和label_data2已声明int32类型
#3.创建分类器
svm = cv2.ml.SVM_create()
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(cv2.ml.SVM_C_SVC)
#4.训练样本
res = svm.train(data,cv2.ml.ROW_SAMPLE,label)
print("训练成功与否res的值",res) #输出:True
#5.进行预测
pre = np.random.rand(20,2)*4-2 #测试样本:20个点[-2,2)
pre = np.array(pre,dtype='float32') #将测试样本转换成要求的float32格式才可以
(par1,res) = svm.predict(pre) #返回值两个参数
print("预测后结果res的值\n",res) #得到一个20x1的数组
"""
predict通过res返回得到一个20x1的数组。
每一行相应一个输入点,计算得到的值就是分类的序号,在这里是0和1
我们取0.5为阈值进行分类并显示结果
"""
"""
因为测试样本是20个[-2,2)范围的点,即20*2的数组
为了方便比较,先将结果预测后结果res进行列堆积,由20*1转换成20*2的数组
同型数组就可以进行比较输出
"""
#6.结果绘图
res = np.hstack((res,res)) #列堆积,另起一列,得到一个20x2的数组
pre0 = pre[res<0.5] #后续详细解释
pre1 = pre[res>=0.5]
print("pre0.shape:",pre0.shape) #此时两者均为一列
print("pre1.shape:",pre1.shape)
pre0 = np.reshape(pre0,(int(pre0.shape[0]/2),2)) #为了显示绘图,将一列变二列
pre1 = np.reshape(pre1,(int(pre1.shape[0]/2),2))
plt.figure(2)
plt.plot(pre0[:,0],pre0[:,1],'o') #画图plt.plot(x坐标,y坐标,'线型')
plt.plot(pre1[:, 0], pre1[:, 1], 'o')
plt.show()
# usePlot()
# reshape()
svm_point()
补充:解释pre0 = pre[res<0.5]
前提:要由两个维度一样的才可以进行比赋值
def true_false():
a = np.array([[1],[2],[3],[4],[5]])
b = np.array([[1],[1],[1],[0],[0]])
res1 = a[b==1]
print(res1)
res2 = a[b<0.5]
print(res2)
true_false()
输出:
[1 2 3]
[4 5]