最小二乘多分类支持向量机(LST-KSVC)
本文是对论文《Least squares twin multi-class classification support vector machine》所提出的LST-KSVC算法的复现!基于此,本人对此算法也做了一定的改进,首先将其改进为分类精度更高的Advanced LST-KSVC算法,然后将其应用在迁移学习领域中,继续对其改进。
将分为三篇博客来详解以上所述的改进方法,请批评指正!
1. LST-KSVC算法
2. Advanced LST-KSVC算法
3. 基于 Advanced LST-KSVC的模型迁移学习算法
1. 术语
支持向量机(Support vector machine,SVM)
结构风险最小化(Structural risk minimization,SRM)
二次规划问题(Quadratic programming problem,QPP)
双支持向量机(Twin support vector machine,TWSVM)
有界双支持向量机(Twin bounded support vector machine,TBSVM)
最小二乘双支持向量机(Least squares twin support vector machine,LS-TWSVM)
2. 摘要
K类双支持向量分类(Twin-KSVC)是一种新的基于双支持向量机(TWSVM)的多分类方法。本文提出了一种称为LST-KSVC的最小二乘版本的Twin-KSVC算法,此算法求解简单且快速。与Twin-KSVC一样,LST-KSVC将所有训练数据转化为“1-versus-1-versus-rest”结构,获得三种值的输出{-1,0,1}。在UCI和人脸数据集上的实验表明,该方法在分类精度上与Twin-KSVC方法相当,但计算时间明显较短。另外,由于LST-KSVC的结构为“1-versus-1-versus-rest”,其分类精度高于其他基于支持向量机的典型多类分类方法。
3. TWSVM
基于“1-versus-1-versus-rest”结构的多分类算法。实际上,TWSVM是一种二分类器,但它使用两个非平行超平面执行分类,以此实现多分类,而支持向量机只使用单个超平面。
将训练数据集D分为三类,A表示“+1”类,B表示“-1”类,剩余的表示“0”类。目的就是寻求两个非平行超平面,使得每个超平面与一个类的训练数据最接近,并且离另一个类的训练数据最远。一个新的数据样本被分配给+1”类或“-1”类取决于两个平面中哪个离它最近。线性TWSVM利用对应于一类的目标函数和对应于另一类的约束函数来求解两个QPPs。第一个QPP让A类数据接近xw1+b=0的超平面,B类数据接近xw1+b=-1的超平面;第二个QPP让A类数据接近xw2+b=1的超平面,B类数据接近xw2+b=0的超平面;
其中,c1,c2是惩罚参数;e1,e2是合适维度的1向量;,是松弛变量项;
求解获得权重参数后,输入测试样本,根据两个超平面中更接近的是哪一个,将该样本点为哪一类,即
4. LST-KSVC
同样的,将训练数据集D分为三类,A表示“+1”类,B表示“-1类”,C表示“0”类。在最小二乘意义上修正线性Twin-KSVC的二次规划问题,即用等式约束代替不等式约束。让A类数据接近xw1+b=0的超平面,让B类和C类数据接近xw1+b=-1的超平面,公式如下:
其中,损失函数是松弛变量y和z的2范数的平方,而不是Twin-KSVC中使用的y和z的1范数;这种简单的修改使我们可以通过求解联立线性方程组来求解二次规划问题,通过将等式约束替换为QPPs的目标函数,得到:
接下来,因为使用了等式约束,所以可直接通过拉格朗日函数的形式,进行求解:
同理,可获得另一个二次规划问题的解:
LST-KSVC算法将所有训练样本表示为 “1-versus-1- versus-rest”结构, 对于一个新的测试点xi,具有三值输出的{1,0,1},通过以下决策函数来确定其类标签:
5. 实现代码
本文代码实验使用的数据集是TE过程的数据集,本人也在UCI数据集Iris数据集做了测试。
# -*-coding:utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
def load_TE_set(data_path,label_path):
X = pd.read_csv(data_path,header=None)
Y = pd.read_csv(label_path,header=None)
return np.array(X).T,np.array(Y).squeeze()
def split_set(X,Y,ratio = 0.8):
cls1 = np.argwhere(Y==1).squeeze()
cls2 = np.argwhere(Y==2).squeeze()
cls3 = np.argwhere(Y==3).squeeze()
idx1 = int(len(cls1)*ratio)
A_train = X[cls1[:idx1]]
A_test = X[cls1[idx1:len(cls1)]]
idx2 = int(len(cls2)*ratio)
B_train = X[cls2[:idx2]]
B_test = X[cls2[idx2:len(cls2)]]
idx3 = int(len(cls3)*ratio)
C_train = X[cls3[:idx3]]
C_test = X[cls3[idx3:len(cls3)]]
return A_train,A_test,B_train,B_test,C_train,C_test
def train_model(A,B,C,epso):
l1,m = A.shape
l2,_ = B.shape
l3,_ = C.shape
e1 = np.ones((l1,1))
e2 = np.ones((l2,1))
e3 = np.ones((l3,1))
E = np.hstack((A,e1))
F = np.hstack((B,e2))
G = np.hstack((C,e3))
c3 = c1 = pow(2,3)
c4 = c2 = pow(2,-5)
w1b1 = -1*np.dot(np.linalg.inv(c1*np.dot(F.T,F)+np.dot(E.T,E)+c2*np.dot(G.T,G)),\
(c1*np.dot(F.T,e2)+c2*np.dot(G.T,(1-epso)*e3)))
w2b2 = np.dot(np.linalg.inv(c3*np.dot(E.T,E)+np.dot(F.T,F)+c4*np.dot(G.T,G)),\
(c3*np.dot(E.T,e1)+c4*np.dot(G.T,(1-epso)*e3)))
return w1b1,w2b2
def cal_accuracy(label_test,result1,result2,epso):
num = result1.shape[0]
pre_test = np.ones(num)*3
for i,x in enumerate(result1):
if x>(epso-1):
pre_test[i]=1
for i,x in enumerate(result2):
if x<(1-epso):
pre_test[i]=2
count = 0
for x,y in zip(pre_test,label_test):
if x==y:
count+=1
return count/num
def test_model(data_test,label_test,w1b1,w2b2,epso):
w1 = w1b1[:-1]
b1 = w1b1[-1]
w2 = w2b2[:-1]
b2 = w2b2[-1]
e = np.ones((data_test.shape[0],1))
# 决策函数
num = data_test.shape[0]
result1 = (np.dot(data_test,w1)+b1*e).squeeze()
bound1 = np.ones(num)*(-1+epso)
result2 = (np.dot(data_test,w2)+b2*e).squeeze()
bound2 = np.ones(num)*(1-epso)
# 计算准确率
acc = cal_accuracy(label_test, result1, result2, epso)
print("the predict accuracy is :", acc)
# 绘图显示结果
x = np.arange(0,num)
plt.plot(x,result1,color='b')
plt.plot(x,result2,color='g')
plt.plot(x,bound1,color='r')
plt.plot(x,bound2,color='r')
plt.show()
if __name__=='__main__':
# 读入数据集
data_path = "TE_data.csv"
label_path = "TE_label.csv"
X,Y = load_TE_set(data_path, label_path)
# 切分数据集为训练集和测试集
A_train, A_test, B_train, B_test, C_train, C_test = split_set(X, Y)
print("train dataset shape is:",A_train.shape,B_train.shape,C_train.shape)
epso = 0.2
# 计算模型参数
w1b1, w2b2 = train_model(A_train, B_train, C_train, epso)
# 获得训练集和测试集
data_test = np.vstack((np.vstack((A_test,B_test)),C_test))
label_test = np.hstack((np.hstack((np.ones(A_test.shape[0]),\
np.ones(B_test.shape[0])*2)),np.ones(C_test.shape[0])*3))
data_train = np.vstack((np.vstack((A_train,B_train)),C_train))
label_train = np.hstack((np.hstack((np.ones(A_train.shape[0]),\
np.ones(B_train.shape[0])*2)),np.ones(C_train.shape[0])*3))
# 测试模型
test_model(data_train, label_train, w1b1, w2b2, epso)
test_model(data_test, label_test, w1b1, w2b2, epso)
6. 仿真结果