import numpy as np
import scipy.optimize as optimize
import cvxopt
class tw_svm():
def __init__(self, X_train, y_train, X_test, c1=1, c2=1, kernel_type='rbf', b=1, c=1, d=2, sigma=3):
self.X_train = X_train
self.y_train = y_train
self.X_test = X_test
# Kernel 设置
self.kernel_type = kernel_type
self.b = b # 双曲正切的常数乘子
self.c = c # 多项式,切线和线性样条的常数和
self.d = d # 多项式的权重
self.sigma = sigma # RBF 和 ERBF 的 sigma
# Twin SVM settings
self.c1 = c1 # TW-SVM 软间隔 1
self.c2 = c2 # TW-SVM 软间隔 2
# SVM settings
self.C = 10 # soft margin
self.solver = 'optimize' # Quadratic problem solver. 'cvxopt' or 'optimize'
# #
# self.alpha = None # 拉格朗如乘子 (SVM and LSSVM)
# self.SV = None # 支持向量
# self.bias = 1 # 偏置
# 计算核函数 k(x1, x2)
def kernel(self, x1, x2):
if x1.ndim == 1:
x1 = np.array([x1]).T
if x2.ndim == 1:
x2 = np.array([x2]).T
m1 = x1.shape[0]
m2 = x2.shape[0]
k = np.zeros((m1, m2))
t = self.kernel_type # 选择使用的核函数
b = self.b
c = self.c
d = self.d
sigma = self.sigma
for i in range(m1):
for j in range(m2):
# 线性核函数
if t == 'linear':
k[i, j] = x1[i] @ x2[j]
# 多项式核函数
elif t == 'poly':
k[i, j] = (x1[i] @ x2[j] + c) ** d
# 高斯核函数
elif t == 'rbf':
k[i, j] = np.exp(-(x1[i] - x2[j]) @ (x1[i] - x2[j]) / (2 * sigma ** 2))
# 指数径向基函数
elif t == 'erbf':
k[i, j] = np.exp(-np.abs(x1[i] - x2[j]) / (2 * sigma ** 2))
# H双曲正切核函数
elif t == 'tanh':
k[i, j] = np.tanh(b * (x1[i] @ x2[j]) + c)
# 线性样条核函数
elif t == 'lspline':
k[i, j] = c + x1[i] * x2[j] + x1[i] * x2[j] * min(x1[i], x2[j]) + 1 / 2 * (x1[i] + x2[j]) * min(
x1[i], x2[j]) ** d
return k
# TWSVM: Solve quadratic problem
def solveQP(p, q, x0, C=None):
# "Quadratic Programming with Python and CVXOPT"
# Solve SVM QP optimization problem:
# min(x) 1/2 * x.T P x + q.T x
# s.t. Gx<=h
# Ax=b
# Input parameters of CVXOPT library
N = q.shape[0]
# construct P, q, G, h matrices for CVXOPT
p = cvxopt.matrix(p, tc='d')
q = cvxopt.matrix(q, tc='d')
if C is None or C == 0: # hard-margin SVM
g = cvxopt.matrix(np.diag(np.ones(N) * -1), tc='d')
h = cvxopt.matrix(np.zeros((N, 1)), tc='d')
else: # soft-margin SVM
g = cvxopt.matrix(np.vstack((np.diag(np.ones(N) * -1), np.eye(N))), tc='d')
h = cvxopt.matrix(np.hstack((np.zeros(N), np.ones(N) * C)), tc='d')
# solve QP problem
x = cvxopt.solvers.qp(p, q, g, h)
return x
# TWSVM: Solve quadratic problem using SciPy optimize
def minimize(self, alpha, M):
g = -np.sum(alpha) + 0.5 * alpha.T @ M @ alpha
return g
def train(self):
X_train = self.X_train
y_train = self.y_train
if y_train.ndim == 1:
y_train = np.array([y_train]).T
A = X_train[y_train[:, 0] == 1] # 取得正样本数据
B = X_train[y_train[:, 0] == -1] # 取得负样本数据
self.Ct = np.vstack((A, B)) # 将样本拼接,用来计算核函数
m1 = A.shape[0]
m2 = B.shape[0]
e1 = np.ones((m1, 1))
e2 = np.ones((m2, 1))
K_ACt = self.kernel(A, self.Ct)
K_BCt = self.kernel(B, self.Ct)
# TWSVM 1
S = np.hstack((K_ACt, e1))
R = np.hstack((K_BCt, e2))
P1 = R @ np.linalg.pinv(S.T @ S) @ R.T
# TWSVM 2
L = np.hstack((K_ACt, e1))
J = np.hstack((K_BCt, e2))
P2 = L @ np.linalg.pinv(J.T @ J) @ L.T
# 初始化 alpha 和 gamma
alpha0 = np.zeros((np.size(R, 0), 1))
gamma0 = np.zeros((np.size(L, 0), 1))
# 拉格朗日乘数
if self.solver == 'cvxopt':
# CVXOPT algorithm:
alpha = self.solveQP(P1, -e2, C=self.c1)
gamma = self.solveQP(P2, -e1, C=self.c2)
alpha = np.ravel(alpha['x'])
gamma = np.ravel(gamma['x'])
elif self.solver == 'optimize':
# Scipy optimize
b1 = optimize.Bounds(0, self.c1)
b2 = optimize.Bounds(0, self.c2)
alpha = optimize.minimize(self.minimize, x0=alpha0, args=P1, method='L-BFGS-B', bounds=b1).x
gamma = optimize.minimize(self.minimize, x0=gamma0, args=P2, method='L-BFGS-B', bounds=b2).x
if alpha.ndim == 1:
alpha = np.array([alpha]).T
if gamma.ndim == 1:
gamma = np.array([gamma]).T
# 解出参数
epsilon = 1e-16
I = np.eye(len(S.T @ S))
self.z1 = -np.linalg.pinv(S.T @ S + epsilon * I) @ R.T @ alpha
I = np.eye(len(J.T @ J))
self.z2 = np.linalg.pinv(J.T @ J + epsilon * I) @ L.T @ gamma
return
def predict(self, X_test):
# 输入参数:
# z1, z2
# Ct
u1 = self.z1[:-1] # TWSVM 1 的权重
b1 = self.z1[-1:] # TWSVM 1 的偏置
u2 = self.z2[:-1] # TWSVM 2 的权重
b2 = self.z2[-1:] # TWSVM 2 的偏置
K_XCt = self.kernel(X_test, self.Ct)
# 得到两个非平行的超平面
surface1 = K_XCt @ u1 + b1
surface2 = K_XCt @ u2 + b2
# 计算点到两个超平面的距离
dist1 = abs(surface1) # class 1
dist2 = abs(surface2) # class -1
# 根据数据点距离两个超平面的远近来判断所属的类别
y_hat = np.argmax(np.hstack((dist1, dist2)), axis=1)
if y_hat.ndim == 1:
y_hat = np.array([y_hat]).T
y_hat = np.where(y_hat == 0, -1, y_hat)
return y_hat
def loadDataSet(fileName):
dataMat = []
labelMat = []
testarr = []
testarr1 = []
fr = open(fileName)
for line in fr.readlines(): # 逐行读取,滤除空格等
lineArr = line.strip().split('\t')
dataMat.append([float(lineArr[0]), float(lineArr[1]), float(lineArr[2]), float(lineArr[3]), float(lineArr[4]), float(lineArr[5]), float(lineArr[6]), float(lineArr[7]), float(lineArr[8]), float(lineArr[9]), float(lineArr[10]), float(lineArr[11])]) # 添加数据
labelMat.append(float(lineArr[12])) # 添加标签
X=np.array(dataMat)
Y=np.array(labelMat)
X_train = np.array(X[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199]])
y_train = np.array(Y[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199]])
X_test = np.array(X[[200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285]])
y_test = np.array(Y[[200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285]])
return X_train, y_train, X_test, y_test
if __name__ == '__main__':
X_train, y_train, X_test, y_test = loadDataSet('新建 Microsoft Excel 工作表.txt')
tw_svm = tw_svm(X_train, y_train, X_test)
tw_svm.train()
y_hat = tw_svm.predict(X_test)
error = 0
for i in range(len(y_test)):
if y_test[i] != y_hat[i]:
error += 1
print(1-(error/len(y_test)))
##报错的内容如下:
Traceback (most recent call last):
File "D:\python pro\web_crawler\novel\TWSVM.py", line 208, in <module>
tw_svm.train()
File "D:\python pro\web_crawler\novel\TWSVM.py", line 140, in train
alpha = optimize.minimize(self.minimize, x0=alpha0, args=P1, method='L-BFGS-B', bounds=b1).x
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "D:\python pro\web_crawler\.venv\Lib\site-packages\scipy\optimize\_minimize.py", line 535, in minimize
raise ValueError("'x0' must only have one dimension.")
ValueError: 'x0' must only have one dimension.
这个是什么问题呀?具体该怎么改呢?