只使用numpy不调用skit-learn完整实现线性不可分支持向量机六分类,对手动输入的单条18维数据循环训练、保存模型、加载模型、预测
时间: 2023-06-15 07:03:18 浏览: 196
好的,我可以为您提供一个基于numpy实现的线性不可分支持向量机的六分类器。这里使用的是一对多(One-vs-All)的方法进行多分类。
代码实现如下:
```python
import numpy as np
class SVM:
def __init__(self, C=1, learning_rate=0.01, max_iters=1000, kernel_type='linear', degree=3, gamma=1.0):
self.C = C
self.learning_rate = learning_rate
self.max_iters = max_iters
self.kernel_type = kernel_type
self.degree = degree
self.gamma = gamma
self.kernel = self._get_kernel_func(kernel_type, degree, gamma)
def _get_kernel_func(self, kernel_type, degree, gamma):
if kernel_type == 'linear':
return lambda x, y: np.dot(x, y)
elif kernel_type == 'poly':
return lambda x, y: (gamma * np.dot(x, y) + 1) ** degree
elif kernel_type == 'rbf':
return lambda x, y: np.exp(-gamma * np.sum((x - y) ** 2))
else:
raise ValueError('Invalid kernel type.')
def _init_params(self, X, y):
self.X = X
self.y = y
self.m, self.n = X.shape
self.alpha = np.zeros(self.m)
self.b = 0
self.E = np.zeros(self.m)
def _predict(self, X):
pred = np.zeros(X.shape[0])
for i in range(X.shape[0]):
pred[i] = np.sign(np.sum(self.alpha * self.y * self.kernel(X[i], self.X)) + self.b)
return pred
def _train(self):
for t in range(self.max_iters):
for i in range(self.m):
Ei = self.E[i]
xi = self.X[i]
yi = self.y[i]
if (yi * Ei < -0.001 and self.alpha[i] < self.C) or (yi * Ei > 0.001 and self.alpha[i] > 0):
j = np.random.choice(list(range(i)) + list(range(i+1, self.m)))
xj = self.X[j]
yj = self.y[j]
Ej = self.E[j]
alpha_i_old = self.alpha[i]
alpha_j_old = self.alpha[j]
if yi != yj:
L = max(0, alpha_j_old - alpha_i_old)
H = min(self.C, self.C + alpha_j_old - alpha_i_old)
else:
L = max(0, alpha_i_old + alpha_j_old - self.C)
H = min(self.C, alpha_i_old + alpha_j_old)
if L == H:
continue
eta = self.kernel(xi, xi) + self.kernel(xj, xj) - 2 * self.kernel(xi, xj)
if eta == 0:
continue
alpha_j_new_unc = alpha_j_old + yj * (Ei - Ej) / eta
alpha_j_new = min(max(alpha_j_new_unc, L), H)
alpha_i_new = alpha_i_old + yi * yj * (alpha_j_old - alpha_j_new)
b1 = self.b - Ei - yi * (alpha_i_new - alpha_i_old) * self.kernel(xi, xi) - yj * (alpha_j_new - alpha_j_old) * self.kernel(xi, xj)
b2 = self.b - Ej - yi * (alpha_i_new - alpha_i_old) * self.kernel(xi, xj) - yj * (alpha_j_new - alpha_j_old) * self.kernel(xj, xj)
if 0 < alpha_i_new < self.C:
self.b = b1
elif 0 < alpha_j_new < self.C:
self.b = b2
else:
self.b = (b1 + b2) / 2
self.alpha[i] = alpha_i_new
self.alpha[j] = alpha_j_new
self.E[i] = np.sum(self.alpha * self.y * self.kernel(xi, self.X)) + self.b - yi
self.E[j] = np.sum(self.alpha * self.y * self.kernel(xj, self.X)) + self.b - yj
def fit(self, X, y):
self._init_params(X, y)
for i in range(6):
binary_y = np.where(y == i, 1, -1)
self.E = np.zeros(self.m)
self.alpha = np.zeros(self.m)
self.b = 0
self._train()
setattr(self, f'alpha_{i}', self.alpha)
setattr(self, f'b_{i}', self.b)
def predict(self, X):
predictions = np.zeros((X.shape[0], 6))
for i in range(6):
alpha = getattr(self, f'alpha_{i}')
b = getattr(self, f'b_{i}')
predictions[:, i] = self._predict(X) * alpha * self.y + b
return np.argmax(predictions, axis=1)
def save(self, filename):
with open(filename, 'wb') as f:
np.savez(f, C=self.C, learning_rate=self.learning_rate, max_iters=self.max_iters, kernel_type=self.kernel_type,
degree=self.degree, gamma=self.gamma, alpha=self.alpha, b=self.b)
def load(self, filename):
with open(filename, 'rb') as f:
model = np.load(f)
self.C = model['C']
self.learning_rate = model['learning_rate']
self.max_iters = model['max_iters']
self.kernel_type = model['kernel_type']
self.degree = model['degree']
self.gamma = model['gamma']
self.alpha = model['alpha']
self.b = model['b']
```
接下来,您可以使用以下代码进行训练、保存模型、加载模型和预测:
```python
# 训练模型
svm = SVM(C=1, learning_rate=0.01, max_iters=1000, kernel_type='rbf', gamma=0.1)
svm.fit(X_train, y_train)
# 保存模型
svm.save('svm_model.npz')
# 加载模型
svm = SVM()
svm.load('svm_model.npz')
# 预测
X_test = np.array([[-0.5, 0.5, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5]])
y_pred = svm.predict(X_test)
print(y_pred)
```
这里假设您已经有了训练数据 `X_train` 和标签 `y_train`。在上述代码中,我们使用了高斯核函数(RBF核函数)进行分类。您可以根据需要修改 `SVM` 类的参数,例如正则化参数 `C`、学习率 `learning_rate`、最大迭代次数 `max_iters`、核函数类型 `kernel_type`、多项式核函数的次数 `degree` 和高斯核函数的参数 `gamma`。
在 `predict` 方法中,我们使用了一对多的方法进行多分类。首先为每个类别训练一个二分类器,然后将测试样本输入这些二分类器进行预测,最后选择预测得分最高的类别作为最终预测结果。预测结果是一个长度为测试样本数的一维数组,每个元素表示该样本的预测类别。
在上述代码中,我们手动输入了一条测试数据 `X_test`,您可以根据需要修改为其他数据。
阅读全文