目录
一、概念
1.定义:
支持向量机(support vector machines,SVM)是一种分类模型,其基本定义为特征空间上的间隔最大化的线性分类器,本质上是一个求解凸二次规划的问题。
支持向量机是求解特征空间上的最大间隔(软间隔、硬间隔),是一个线性分类器,为了支持非线性的分类,引入了核技巧,用于将输入从输入空间映射到特征空间。相比较而言,核变换方法算是比支持向量机用得更广泛的一种机器学习方法。
2.主要分类
- 线性可分支持向量机
- 线性支持向量机
- 非线性支持向量机
先认识两个概念之间的关系,分别是输入空间、特征空间。假设一个分类问题的输入空间于特征空间不同,则线性可分向量机和线性支持向量机假设这两个空间的元素可以一一对应,非线性支持向量机则利用一个非线性核技巧完成映射。支持向量机的学习都是基于特征空间进行的。
3.线性可分支持向量机
1.线性可分支持向量机
假设特征空间中的训练数据集为
学习的目标就是找到一个超平面,能将实例分到不同类中,分离超平面方程可以写为:
其中 w 是法向量, 法向量指向的一侧是正类,另一侧是负类。
一般情况下,当训练数据集线性可分时,存在无穷多个分离超平面。如果使用感知机算法(误分类最小的策略),此时的解会有无穷多个;线性可分支持向量机利用间隔最大化求解超平面,此时的解是唯一解。
2.函数间隔与几何间隔
一个点距离分类超平面的远近可以表示分类预测的准确程度,那么在 w⋅x+b=0 时, |w⋅x+b| 就能表示 x 距离超平面的远近,而此时y 的符号是否一致可以表示分类是否正确。于是函数间隔就可以写成。
超平面与所有数据集的间隔就是所有样本点的函数间隔的最小值( ,在这个间隔内,任意一个超平面都可以把数据集正确分类)。
不过只有函数间隔存在一个问题,只要成比例的改变 w 和 b (比如变成 2w 和 2b ),超平面不会改变,但是函数间隔却变成了原来的2倍。即有必要对 w 加一些约束,如规范化:
||w||=1
如此可以使得函数间隔是确定的,此时函数间隔就变成了几何间隔。
同样,超平面与所有数据集的间隔就是所有样本点的函数间隔的最小值( )
3.间隔最大化
可分离超平面有无穷多个,但是几何间隔最大的分离超平面是唯一的,在线性可分的情况下,这种间隔称为硬间隔(近似线性可分的情况下为软间隔)。
求解间隔最大的超平面可以表示为如下约束问题:
基于几何间隔和函数间隔的关系,上式可以改写为
因为函数间隔的倍数不会改变超平面,所以我们可以取,同时最大化 1/||w|| 和最小化 ( 1/2 和平方均码是为了求导方便)等价。 所以上式还可以进一步改写:
目标函数式二次函数,约束条件是仿射函数,上述的凸优化问题就成了凸二次规划问题,可求解得最优解 w∗ , b∗ ,由此得最优分离超平面
4.间隔边界
训练数据集中与分离超平面距离最近的样本点的实例即为支持向量,那么在约束条件下,支持向量就是:
对于 的点,支持向量超平面为
对于 的点,支持向量超平面为
所以间隔依赖法向量 w ,为 2/||w|| , H1 和 H2 为间隔边界。
5.线性可分支持向量机对偶算法
求解最优化问题可以应用拉格朗日对偶性,求解对偶问题得到原始问题的解,求解对偶问题至少有两个好处:
- 对偶问题更容易求解
- 可以自然的引入核函数,推广到非线性分类问题
基本步骤
第一步:引入拉格朗日乘子≥ 0得到拉格朗日函数
第二步:令对w和b的偏导为零
第三步:w, b回代到第一步:
4.线性支持向量机
1.线性支持向量机
线性可分支持向量机中有较强的不等式约束,在更一般的情况下,这些不等式约束并非全部成立,因此需要从上面的硬间隔改为软间隔。
线性不可分意味着函数间隔不能满足大于等于1的约束条件,为了解决这个问题,引入一个松弛变量 ,使得函数间隔加上这个松弛变量后满足大于等于1的条件。于是,约束条件就变成了
同时,每一个松弛变量 会有一个代价,于是原目标函数就变成了
其中 C≥0 为惩罚函数,C 值越大时对误分类的惩罚越大,反之越小。上式表示让间隔仅可能大,同时使误分类尽可能小,而 C 就是二者的调和系数。
注意:
- C参数控制了错误分类训练示例的惩罚。C参数越大,则告诉SVM要对所有的例子进行正确的分类。
- 当C比较小时,模型对错误分类的惩罚较小,比较松弛,之间的间隔就比较大,可能会产生欠拟合的情况;
- 当C比较大时,模型对错误分类的惩罚就大,因此两组数据之间的间隔就小,容易产生过拟合的情况。
- C值越大,越不愿放弃那些离群点;c值越小,越不重视那些离群点。 根据上图结果看出,当C=100时,发现SVM现在对每个示例都进行了正确的分类,但是它绘制的决策边界并不适合数据。
于是线性不可能分的支持向量机就变成了如下的凸二次规划问题。
2.线性支持向量机对偶算法
首先还是构造拉格朗日函数( ,)
求 L(w,b,,,) 对 w,b, 的极小
带入拉格朗日函数中有
再对 求 的极大,得对偶问题
对约束条件进行变换可以得到
反解原始最优化问题就有,若存在一个 的一个分量 ,0≤≤C 有
3.合页损失函数
线性支持向量机还可以写成如下的最小化目标函数
其中下标 + 表示取正值的函数,令
则需要最小化的目标函数可以可以写成
取 则
与原目标函数等价。
5.非线性支持向量机
1.核支持向量机
对于一个给定的训练数据集,有时候一个实数空间上的线性平面不可分,需要一个超曲面才能分开,这样的问题就是非线性可分问题。
变换:x →
设样本x映射后的向量为ϕ(x), 划分超平面为f(x)=w^T*ϕ(x)+b
2. 核函数
1.基本想法
不显式地构造核映射, 而是设计核函数.
2.Mercer定理(充分非必要)
只要对称函数值所对应的核矩阵半正定, 则该函数可作为核函数.
3.常用的核函数
二、代码示例——垃圾邮件分类
基本思路:
-
数据准备:准备带有标记的垃圾邮件和非垃圾邮件数据集。这些数据集包括已经标记好的邮件内容以及相应的分类(垃圾或非垃圾)。
-
特征提取:针对每封邮件,需要将文本内容转换成特征向量。常见的方法包括词袋模型(Bag of Words)等。这些特征向量可以描述邮件中词汇的出现频率或重要程度。
-
数据预处理:对特征向量进行预处理,包括去除停用词、词干提取、标点符号处理等,以便提高分类器的性能。
-
分割数据集:将数据集分为训练集和测试集,通常按照一定比例划分,例如 70% 的数据用于训练,30% 的数据用于测试。
-
训练模型:使用 SVM 算法构建分类模型。可以选择不同的核函数(如线性核、多项式核或高斯核)来构建模型。
-
模型评估:使用测试集对训练好的模型进行评估,计算分类准确率、精确率、召回率等指标,以验证模型的性能。
-
预测和部署:当模型的性能达到满意的水平后,可以将其用于预测新的未知邮件的分类,并将模型部署到实际应用中。
加载数据:
import numpy as np
import matplotlib.pyplot as plt
from scipy.io import loadmat
from sklearn import svm
# 加载数据
train_data = loadmat('svm_data/data/spamTrain.mat')
test_data = loadmat('svm_data/data/spamTest.mat')
X_train = train_data['X']
y_train = train_data['y'].ravel()
X_test = test_data['Xtest']
y_test = test_data['ytest'].ravel()
print(X_test.shape)
print(X_train.shape)
训练模型
# 训练 SVM 模型
C = 0.1
clf = svm.SVC(C=C, kernel='linear')
clf.fit(X_train, y_train)
# 计算在训练集和测试集上的准确率
train_acc = clf.score(X_train, y_train)
test_acc = clf.score(X_test, y_test)
print(f'Training accuracy: {train_acc:.2f}')
print(f'Testing accuracy: {test_acc:.2f}')
结果:
绘制图形
# 绘制决策边界
x_min, x_max = X_train[:, 0].min(), X_train[:, 0].max()
y_min, y_max = X_train[:, 1].min(), X_train[:, 1].max()
xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500), np.linspace(y_min, y_max, 500))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Paired, alpha=0.8)
plt.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=plt.cm.Paired)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title(f'SVM Decision Boundary with C = {C}')
plt.show()
总是出现报错
修改了好几次也总不行,不知道到底是哪里错了,求解答!!!
三、总结
其实本文很多内容都是基于别人发出来的内容做的小记录,其实对这一章节还是有很多不理解的地方,特别是对于数学公式之间的转换还是有不明白的地方。但是在写博客的时候也复习了一下内容和加深印象,对于不理解的地方,还是会在接下去的时间里慢慢突破,解决问题。