数学推导
代码实现
class SVMClassifier:
def __init__(self, C=1., kernel=rbf_kernel, power=4, gamma=None, coef=4):
"""
:param C: 惩罚参数
:param kernel: 核函数
:param power: 多项式核函数最高次项
:param gamma: 核函数参数
:param coef: 多项式核函数参数
"""
self.C = C
self.kernel = kernel
self.power = power
self.gamma = gamma
self.coef = coef
self.lagr_multipliers = None
self.support_vectors = None
self.support_vectors_labels = None
self.intercept = None
def fit(self, X, y):
"""
:param X: 连续数据
:param y: 二分类 传入只有1和0的
:return:
"""
y[y == 0] = -1
m, n = np.shape(X)
if not self.gamma:
self.gamma = 1 / n # 若为空,设默认值
self.kernel = self.kernel( # 初始化核函数
power=self.power,
gamma=self.gamma,
coef=self.coef
)
kernel_matrix = np.zeros((m, m)) # 计算样本点之间结果,结果存在矩阵中
for i in range(m):
for j in range(m):
kernel_matrix[i, j] = self.kernel(X[i], X[j])
# 处理凸优化问题
P = cvxopt.matrix(np.outer(y, y) * kernel_matrix, tc='d')
q = cvxopt.matrix(np.ones(m) * -1)
A = cvxopt.matrix(y, (1, m), tc='d')
b = cvxopt.matrix(0, tc='d')
if not self.C:
G = cvxopt.matrix(np.identity(m) * -1)
h = cvxopt.matrix(np.zeros(m))
else:
G_max = np.identity(m) * -1
G_min = np.identity(m)
G = cvxopt.matrix(np.vstack((G_max, G_min)))
h_max = cvxopt.matrix(np.zeros(m))
h_min = cvxopt.matrix(np.ones(m) * self.C)
h = cvxopt.matrix(np.vstack((h_max, h_min)))
# 使用cvxopt库解决凸优化问题
minimization = cvxopt.solvers.qp(P, q, G, h, A, b)
lagr_mult = np.ravel(minimization['x']) # 拉格朗日乘子
idx = lagr_mult > 1e-7 # 获取非0拉格朗日乘子的索引
self.lagr_multipliers = lagr_mult[idx] # 获取符合的拉格朗日乘子
self.support_vectors = X[idx] # 获取支持向量
self.support_vectors_labels = y[idx] # 获取对应标签
self.intercept = self.support_vectors_labels[0] # 计算wx+b中的b
for i in range(len(self.lagr_multipliers)):
self.intercept -= self.lagr_multipliers[i] * self.support_vectors_labels[i] *\
self.kernel(self.support_vectors[i], self.support_vectors[0])
y[y == -1] = 0
def predict(self, X_text):
y_predict = []
for sample in X_text:
prediction = 0
for i in range(len(self.lagr_multipliers)):
prediction += self.lagr_multipliers[i] * self.support_vectors_labels[i] * \
self.kernel(self.support_vectors[i], sample)
prediction += self.intercept
y_predict.append(np.sign(prediction)) # 大于0返回1,小于0返回-1
y_predict = np.array(y_predict, dtype=np.int8)
y_predict[y_predict == -1] = 0
return y_predict