实验目的及内容
理解和掌握支持向量机基本原理和方法,理解数据线性可分性,理解支持向量机对偶问题,理解支持向量机核函数等概念,掌握间隔、支持向量、对偶、核函数等概念及计算方法。
实验要求
基于给定数据集,编程实现软间隔线性支持向量机模型,采用随机梯度下降方法对模型进行训练。初始参数w1=0,w2=0,b=0,参数C=100,学习率α=0.001。绘制训练集精度迭代曲线,绘制分类超平面,给出最终支持向量机表达式和模型在测试集上的精度。
实验环境
python、numpy、matplotlib
实验代码
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use('TKAgg')
# 导入训练数据
train_dataset = np.genfromtxt("experiment_06_training_set.csv", delimiter=",", skip_header=1)
# 获取训练数据的条数以及列数
rowOfTrainDataset = train_dataset.shape[0]
columnOfTrainDataset = train_dataset.shape[1]
# 从训练数据中分离属性和标签
yOfTrainDataset = train_dataset[:, 2:3]
xOfTrainDataset = train_dataset[:, 0:2]
# 导入测试数据
test_dataset = np.genfromtxt("experiment_06_testing_set.csv", delimiter=",", skip_header=1)
# 获取测试数据的条数
rowOfTestDataset = test_dataset.shape[0]
# 从测试数据中分离属性和标签
yOfTestDataset = test_dataset[:, 2:3]
xOfTestDataset = test_dataset[:, 0:2]
# 超参数设置
C = 100
lr = 0.001
# 初始化W和b
W = np.zeros((2, 1))
b = 0
# 初始化画精度曲线的x轴和y轴
x_line = np.arange(1, rowOfTrainDataset+1).reshape(rowOfTrainDataset, 1)
y_line = np.zeros((rowOfTrainDataset, 1))
# 随机梯度下降
for i in range(rowOfTrainDataset):
# 获取样本的x和y并调整规模
x = xOfTrainDataset[i, :].reshape(2, 1)
y = yOfTrainDataset[i, 0]
# 如果违反间隔
if y * (W.T @ x + b) < 1:
dw = W - C * y * x
db = -C * y
# 不违反间隔
else:
dw = W
db = 0
# 更新参数
W -= lr * dw
b -= lr * db
# 计算精度并打印结果
accuracyOfTrainDataset = np.sum(np.sign(W.T @ xOfTrainDataset.T + b).T == yOfTrainDataset) / rowOfTrainDataset
y_line[i, 0] = accuracyOfTrainDataset
print(f"index: {i} | accuracy: {accuracyOfTrainDataset: .4f}")
# 画精度曲线
plt.figure(1)
plt.plot(x_line, y_line, color='b', linewidth=1.5, label='Accuracy line')
plt.xlabel("index", fontsize=12)
plt.ylabel("Accuracy", fontsize=12)
plt.title("Accuracy line", fontsize=14)
plt.legend(loc='upper right', frameon=True)
plt.grid(alpha=0.3, linestyle=':')
plt.ylim(0, 1.1)
plt.tight_layout()
# 准备两类点以及分割超平面的数据
train_label_1 = xOfTrainDataset[yOfTrainDataset.flatten() == 1]
train_label_0 = xOfTrainDataset[yOfTrainDataset.flatten() == -1]
line_x = np.arange(-1, 5).reshape(6, 1)
line_y = (W[0, 0] * line_x + b) / (-W[1, 0])
# 画分割超平面
plt.figure(2)
plt.scatter(train_label_1[:, 0], train_label_1[:, 1], color='r', alpha=0.7, edgecolors='white', s=10, label='Label 1')
plt.scatter(train_label_0[:, 0], train_label_0[:, 1], color='b', alpha=0.7, edgecolors='white', s=10, label='Label -1')
plt.plot(line_x, line_y, color='g', linewidth=1.5, label='separating hyperplane')
plt.title("separating hyperplane", fontsize=14)
plt.xlabel("X-axis", fontsize=12)
plt.ylabel("Y-axis", fontsize=12)
plt.legend(loc='upper right', frameon=True)
plt.grid(alpha=0.3, linestyle=':')
plt.tight_layout()
plt.show()
# 打印SVM表达式
print(f"支持向量机表达式: {W[0, 0]: .4f} * x1 + {W[1, 0]: .4f} * x2 + {b: .4f} = 0")
# 计算并打印测试集精度
accuracyOfTestDataset = np.sum(np.sign(W.T @ xOfTestDataset.T + b).T == yOfTestDataset) / rowOfTestDataset
print(f"测试集精度: {accuracyOfTestDataset * 100: .4f}%")
结果分析
训练集精度迭代曲线
分类超平面图
支持向量机表达式
y = sgn(1.3027 * x1 – 1.2594 * x2 + 1.2000)
测试集上精度:
测试集精度:100.0000%