一、SVM算法简介
支持向量机(support vector machine,SVM)是一种二分类模型,它的基本模型是定义
在特征空间上的间隔最大的线性分类器。SVM还包括核技巧,这使它成为实质上的非线性
分类器。支持向量机的学习算法是求解凸二次规划的最优化算法。
支持向量(Support Vector):把划分数据的决策边界就叫做超平面,点到超平面的距离叫做间隔。在支持向量机中,距离超平面最近的且满足一定条件的几个训练样本点被称为支持向量(Support Vector)。机(Machine):表示的是一种算法。支持向量机的意思就是使超平面和支持向量之间的间隔尽可能的大,这样才可以使两类样本准确地分开。
例如,我们用函数来表示超平面,如下图所示的黑实线就是超平面,红色圈圈内的点则代表支持向量。
二、线性支持向量机
如何使用一条之间分割下面的红蓝数据集?
直线被用来将数据分割到不同类别中,而实际上我们可以多条直线将数据分来。SVM的核心思路是找到一个直线,使离直线比较近的点,尽可能 远离这条直线,这可以使模型具有很强的泛化能力。而这些点就被称为 支持向量(Support Vector)。在二维空间中,我们用直线来分割,如果是高维空间,我们使用 超平面来分割。
三、非线性支持向量机
如何分类一种非线性可分的数据集?
我们可以使用使用核函数来构建非线性支持向量机。核函数允许算法在变换后的高维特征空间中拟合最大的超平面。
核函数是支持向量机(SVM)中一个核心的概念,它使得SVM能够有效地处理非线性可分的数据。以下是核函数的具体内容:
- 核函数的基本定义:核函数可以定义为一个函数,它接受两个低维空间中的向量作为输入,并返回它们在高维特征空间中的内积。这种方法避免了直接在高维空间中操作,因为那会涉及到复杂的运算和高计算成本。通过这种方式,数据可以在高维空间中变得线性可分,从而使用线性算法进行处理。
- 核函数的工作原理:通过将原始数据映射到更高维的空间中,数据点在这个新的空间中可以被线性超平面分隔。这种映射使得原本在低维空间中线性不可分的问题,在高维空间中变得线性可分。核函数通过计算数据的点积来实现这一点,而无需显式地构造高维空间中的数据表示,这称为“核技巧”。
- 常用的核函数类型:线性核函数主要用于原始特征空间本身即是线性可分的场景。多项式核函数可以将数据映射到一个更高阶的多项式空间,使数据在新的空间中线性可分。高斯核函数,也称为径向基函数(RBF),其特点是可以将数据映射到无限维的空间,提供强大的灵活性和泛化能力。此外,还有其他如Sigmoid核、拉普拉斯核等,每种核函数都有其特定的应用场景和优势。
四、实验及实验结果分析
实验代码如下:
import numpy as np # 导入numpy库,用于进行数值计算
import matplotlib.pyplot as plt # 导入matplotlib库的pyplot模块,用于绘制图形
from sklearn import datasets # 从sklearn库中导入datasets模块,用于生成数据集
class LinearSVM: # 定义线性支持向量机类
def __init__(self, learning_rate=0.0001, lambda_param=0.1, n_iters=1000): # 初始化方法,设置学习率、正则化参数和迭代次数
self.learning_rate = learning_rate # 设置学习率
self.lambda_param = lambda_param # 设置正则化参数
self.n_iters = n_iters # 设置迭代次数
self.w = None # 初始化权重为None
self.b = None # 初始化偏置为None
def fit(self, X, y): # 拟合方法,输入特征矩阵X和目标向量y
n_samples, n_features = X.shape # 获取样本数量和特征数量
y_ = np.where(y <= 0, -1, 1) # 将目标向量y中的负值转换为-1,正值转换为1
self.w = np.zeros(n_features) # 初始化权重为零向量
self.b = 0 # 初始化偏置为0
for _ in range(self.n_iters): # 进行指定次数的迭代
for idx, x_i in enumerate(X): # 遍历特征矩阵X
condition = y_[idx] * (np.dot(x_i, self.w) - self.b) >= 1 # 判断是否满足约束条件
if condition: # 如果满足约束条件
self.w -= self.learning_rate * (2 * self.lambda_param * self.w) # 更新权重
else: # 如果不满足约束条件
self.w -= self.learning_rate * (2 * self.lambda_param * self.w - np.dot(x_i, y_[idx])) # 更新权重
self.b -= self.learning_rate * y_[idx] # 更新偏置
def predict(self, X): # 预测方法,输入特征矩阵X
linear_output = np.dot(X, self.w) - self.b # 计算线性输出
return np.sign(linear_output) # 返回预测结果的符号
X, y = datasets.make_blobs(n_samples=500, centers=2, random_state=8) # 生成数据集
y = np.where(y == 0, -1, 1) # 将目标向量y中的负值转换为-1,正值转换为1
svm = LinearSVM() # 创建线性支持向量机实例
svm.fit(X, y) # 使用数据集训练模型
def plot_hyperplane(X, y, w, b): # 定义绘制超平面的函数,输入特征矩阵X、目标向量y、权重w和偏置b
plt.scatter(X[:, 0], X[:, 1], marker='o', c=y, s=100, edgecolors='k', cmap='winter') # 绘制散点图
ax = plt.gca() # 获取当前坐标轴
xlim = ax.get_xlim() # 获取x轴的范围
ylim = ax.get_ylim() # 获取y轴的范围
xx = np.linspace(xlim[0], xlim[1], 30) # 在x轴范围内生成30个等间距的点
yy = np.linspace(ylim[0], ylim[1], 30) # 在y轴范围内生成30个等间距的点
YY, XX = np.meshgrid(yy, xx) # 生成网格点坐标矩阵
xy = np.vstack([XX.ravel(), YY.ravel()]).T # 将网格点坐标矩阵展平并转置
Z = (np.dot(xy, w) - b).reshape(XX.shape) # 计算每个网格点的输出值
ax.contour(XX, YY, Z, color='k', levels=[-1, 0, 1], alpha=0.5, linestyles=['--', '-', '--']) # 绘制超平面
plt.show() # 显示图形
plot_hyperplane(X, y, svm.w, svm.b) # 调用绘制超平面的函数,传入特征矩阵X、目标向量y、权重w和偏置b
实验结果为:
实验结果分析:由上图可知,分类结果较好。
五、总结
SVM的优点:
(1)解决了小样本情况下的机器学习。
(2)由于使用核函数方法克服了维数灾难和非线性可分的问题,所以向高维空间映射时没有增加计算的复杂度。(由于支持向量机算法的最终决策函数只由少数的支持向量所确定,所以计算的复杂性取决于支持向量的数目,而不是整个样本空间的维数)。
SVM的缺点:
(1)支持向量机算法对大规模训练样本难以实施,这是因为支持向量算法借助二次规划求解支持向量,这其中会设计m阶矩阵的计算,所以矩阵阶数很大时将耗费大量的机器内存和运算时间。
(2)经典的SVM只给出二分类的算法,而在数据挖掘中,一般要解决多分类的分类问题,而支持向量机对于多分类问题解决效果并不理想。
(3)现在常用的SVM理论都是使用固定惩罚系数C,但是正负样本的两种错误造成的损失是不一样的。