介绍
支持向量机(Support Vector Machine, SVM)是一种监督学习模型,广泛应用于分类和回归分析。SVM 的核心思想是通过找到一个最优的超平面来划分不同类别的数据点,并且尽可能地最大化离该超平面最近的数据点(支持向量)之间的间隔。这使得 SVM 具有良好的泛化能力,即能够很好地处理未见过的数据。
SVM 的工作原理
- 线性可分情况:
- 在最简单的情况下,如果数据集是线性可分的,SVM 试图找到一个最佳的直线(在二维空间中)或超平面(在多维空间中),它能将两个类别完全分开。
- 这个超平面的选择不仅取决于它可以正确分类训练数据,还在于它能够使两类样本到超平面的距离最大。这样的决策边界被称为最大间隔超平面。
- 非线性可分情况:
- 当数据不是线性可分时,可以通过核函数(Kernel Function)将原始特征映射到更高维度的空间,在这个新的空间中寻找线性分离的可能性。
- 常见的核函数包括多项式核、径向基函数(RBF Kernel)、Sigmoid 核等。选择合适的核函数对于提高 SVM 的性能至关重要。
- 软间隔与正则化:
- 现实世界的数据往往存在噪声或者异常值,严格的线性分割可能会导致过拟合问题。因此,引入了软间隔的概念,允许一些数据点位于错误的一侧。
- 正则化参数 C 控制着对误分类的惩罚程度;较小的 C 值意味着更宽的间隔但可能更多的容许误差,而较大的 C 则追求更高的准确率但可能导致过拟合。
- 支持向量:
- 决定最终超平面位置的关键数据点称为支持向量。这些点位于间隔边界上,或者是在软间隔设定下违反边界的点。
- 只有支持向量影响了模型的学习过程,其他不在间隔内的点对构建超平面没有贡献。
- 多分类问题:
- 对于多于两个类别的分类任务,可以采用一对多(One-vs-Rest, OvR)或一对一(One-vs-One, OvO)的方法构建多个二分类器,然后根据投票或其他策略确定最终类别标签。
SVM 的优点
- 高效率:在高维空间表现良好,即使当特征数量超过样本数量时也能有效工作。
- 强大的数学基础:基于凸优化理论,保证了全局最优解的存在性和唯一性。
- 适用于小规模数据集:不需要大量的训练数据即可获得较好的效果。
- 灵活性:通过不同的核函数可以适应各种类型的数据分布。
SVM 的局限性
- 计算复杂度:随着训练样本数目的增加,训练时间和内存消耗也会显著增长。
- 对参数敏感:如核函数的选择、正则化参数 C 和核参数(例如 RBF 的 gamma 参数),需要仔细调整以达到最佳性能。
- 解释性差:相比于决策树之类的算法,SVM 提供的模型通常难以直观理解。
5、软间隔及优化
5.1、软间隔问题
以上讨论问题都是基于样本点完全的线性可分,如果存在部分样本点不能完全线性可分,大部分样本点线性可分的情况,那么我们就需要用到软间隔,相比于硬间隔的苛刻条件,我们允许个别样本点出现在间隔带里面,即我们允许部分样本点不满足约束条件:
y ⋅ ( w T ⋅ x i + b ) ≥ 1 y\cdot (w^T\cdot x_i +b) \ge 1 y⋅(wT⋅xi+b)≥1
为了度量这个间隔软到何种程度,我们为每个样本引入一个" 松弛变量 " ξ i , ξ i ≥ 0 \xi_i,\xi_i \ge 0 ξi,ξi≥0,(中文:克西)加入松弛变量后,我们的约束条件变成 $ y\cdot (w^T\cdot x_i +b) \ge 1 -\xi_i$,这样不等式就不会那么严格,数据点在不同的约束条件下的情况如下:
内部点: y ⋅ ( w T ⋅ x i + b ) ≥ 1 y\cdot (w^T\cdot x_i +b) \ge 1 y⋅(wT⋅xi+b)≥1,即 ξ i = 0 \xi_i = 0 ξi=0
边界点: y ⋅ ( w T ⋅ x i + b ) = 1 y\cdot (w^T\cdot x_i +b) =1 y⋅(wT⋅xi+b)=1,即 ξ i = 0 \xi_i = 0 ξi=0
正确误差点: y ⋅ ( w T ⋅ x i + b ) = 1 − ξ i y\cdot (w^T\cdot x_i +b) = 1-\xi_i y⋅(wT⋅xi+b)=1−ξi,即$ 0 < \xi_i <1$
错误误差点: y ⋅ ( w T ⋅ x i + b ) = 1 − ξ i y\cdot (w^T\cdot x_i +b) = 1-\xi_i y⋅(wT⋅xi+b)=1−ξi,即 ξ i ≥ 1 \xi_i \ge 1 ξi≥1
5.2、优化SVM目标函数(了解)
加入软间隔后我们的目标函数变成了:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i s . t 1 − y ( w T ⋅ x i + b ) − ξ i ≤ 0 , ξ i ≥ 0 , i = 1 , 2 , ⋯ , n − − − 式 h min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i\quad s.t\quad 1-y(w^T\cdot x_i +b) - \xi_i \le 0,\xi_i\ge0,i = 1,2,\cdots,n\quad ---式h min21∣∣w∣∣2+Ci=1∑nξis.t1−y(wT⋅xi+b)−ξi≤0,ξi≥0,i=1,2,⋯,n−−−式h
其中C是一个大于0的常数,这里在原有的目标函数中加入 C ∑ i = 1 n ξ i C\sum\limits_{i=1}^n\xi_i Ci=1∑nξi可以理解为错误样本的惩罚程度,我们希望在对应条件下$ min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i 变小,对应的也是希望 变小,对应的也是希望 变小,对应的也是希望 C\sum\limits_{i=1}^n\xi_i 变小,当 C 为无穷大, 变小,当C为无穷大, 变小,当C为无穷大,\xi_i 必然无穷小,这样的话 S V M 就变成一个完全线性可分的 S V M 。如果 C 为有对应的值时, 必然无穷小,这样的话SVM就变成一个完全线性可分的SVM。如果C为有对应的值时, 必然无穷小,这样的话SVM就变成一个完全线性可分的SVM。如果C为有对应的值时,\xi_i$对应的会有一个大于0的值,这样的SVM就是允许部分样本不遵守约束条件。
接下来我们对新的目标函数h式求解最优化问题,步骤与 4、最小化SVM目标函数【硬间隔】完全线性可分步骤完全一样。
- 构造拉格朗日函数
将h式目标函数改写成如下:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i s . t 1 − y ( w T ⋅ x i + b ) − ξ i ≤ 0 , ξ i ≥ 0 , i = 1 , 2 , ⋯ , n − − − 式 h min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i\quad s.t\quad 1-y(w^T\cdot x_i +b) - \xi_i \le 0,\xi_i\ge0,i = 1,2,\cdots,n\quad ---式h min21∣∣w∣∣2+Ci=1∑nξis.t1−y(wT⋅xi+b)−ξi≤0,ξi≥0,i=1,2,⋯,n−−−式h
构造拉格朗日函数如下:
min w , b , ξ max λ , μ L ( w , b , ξ , λ , μ ) = m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i + ∑ i = 1 n λ i [ 1 − y i ( w T ⋅ x i + b ) − ξ i ] − ∑ i = 1 n μ i ξ i s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n − − − 式 i \begin{aligned}\min\limits_{w,b,\xi}\max\limits_{\lambda,\mu}L(w,b,\xi,\lambda,\mu) =&min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i+\sum\limits_{i=1}^n\lambda_i[1-y_i(w^T\cdot x_i +b)-\xi_i] - \sum\limits_{i=1}^n\mu_i\xi_i\\\\&s.t\quad \lambda_i \ge 0,\mu_i \ge 0\quad i=1,2,\cdots,n\quad ---式i \end{aligned} w,b,ξminλ,μmaxL(w,b,ξ,λ,μ)=min21∣∣w∣∣2+Ci=1∑nξi+i=1∑nλi[1−yi(wT⋅xi+b)−ξi]−i=1∑nμiξis.tλi≥0,μi≥0i=1,2,⋯,n−−−式i
上式中 λ i , μ i \lambda_i,\mu_i λi,μi是拉格朗日乘子, w , b , ξ w,b,\xi w,b,ξ是我们要计算的主问题参数。
- 对偶关系转换
目标函数是个下凸函数,对应的拉格朗日函数复合强对偶性,所以可以根据强对偶向,将对偶问题转换为:
min w , b , ξ max λ , μ L ( w , b , ξ , λ , μ ) = max λ , μ min w , b , ξ L ( w , b , ξ , λ , μ ) \min\limits_{w,b,\xi}\max\limits_{\lambda,\mu}L(w,b,\xi,\lambda,\mu) = \max\limits_{\lambda,\mu}\min\limits_{w,b,\xi}L(w,b,\xi,\lambda,\mu) w,b,ξminλ,μmaxL(w,b,ξ,λ,μ)=λ,μmaxw,b,ξminL(w,b,ξ,λ,μ)
即:
max λ , μ min w , b , ξ L ( w , b , ξ , λ , μ ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i + ∑ i = 1 n λ i [ 1 − y i ( w T ⋅ x i + b ) − ξ i ] − ∑ i = 1 n μ i ξ i s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n − − − 式 j \begin{aligned}\max\limits_{\lambda,\mu}\min\limits_{w,b,\xi}L(w,b,\xi,\lambda,\mu) =&\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i+\sum\limits_{i=1}^n\lambda_i[1-y_i(w^T\cdot x_i +b)-\xi_i] - \sum\limits_{i=1}^n\mu_i\xi_i\\\\&s.t\quad \lambda_i \ge 0,\mu_i \ge 0\quad i=1,2,\cdots,n\quad ---式j \end{aligned} λ,μmaxw,b,ξminL(w,b,ξ,λ,μ)=21∣∣w∣∣2+Ci=1∑nξi+i=1∑nλi[1−yi(wT⋅xi+b)−ξi]−i=1∑nμiξis.tλi≥0,μi≥0i=1,2,⋯,n−−−式j
使用j式对 w , b , ξ w,b,\xi w,b,ξ求导,并令导数为零,得到如下关系:
{ ∂ L ∂ w = w − ∑ i = 1 n λ i ⋅ x i ⋅ y i = 0 ∂ L ∂ b = ∑ i = 1 n λ i ⋅ y i = 0 ∂ L ∂ ξ = C ∑ i = 1 n 1 − ∑ i = 1 n λ i − ∑ i = 1 n μ i = 0 \left\{\begin{aligned}&\frac{\partial L}{\partial w}=w - \sum\limits_{i=1}^n\lambda_i\cdot x_i\cdot y_i = 0\\\\&\frac{\partial L}{\partial b}=\sum\limits_{i=1}^n\lambda_i\cdot y_i = 0\\\\&\frac{\partial L}{\partial \xi} = C\sum\limits_{i=1}^n1 - \sum\limits_{i=1}^n\lambda_i-\sum\limits_{i=1}^n\mu_i = 0\end{aligned}\right. ⎩ ⎨ ⎧∂w∂L=w−i=1∑nλi⋅xi⋅yi=0∂b∂L=i=1∑nλi⋅yi=0∂ξ∂L=Ci=1∑n1−i=1∑nλi−i=1∑nμi=0
整理之后得到:
{ w = ∑ i = 1 n λ i ⋅ x i ⋅ y i 0 = ∑ i = 1 n λ i ⋅ y i C = λ i + μ i \left\{\begin{aligned}&w = \sum\limits_{i=1}^n\lambda_i\cdot x_i\cdot y_i\\\\&0=\sum\limits_{i=1}^n\lambda_i\cdot y_i \\\\&C = \lambda_i+\mu_i\end{aligned}\right. ⎩ ⎨ ⎧w=i=1∑nλi⋅xi⋅yi0=i=1∑nλi⋅yiC=λi+μi
将以上关系代入到 j 式:
max λ , μ L ( w , b , ξ , λ , μ ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i + ∑ i = 1 n λ i [ 1 − y i ( w T ⋅ x i + b ) − ξ i ] − ∑ i = 1 n μ i ξ i = 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( x i ⋅ x j ) + ∑ i = 1 n λ i ξ i + ∑ i = 1 n μ i ξ i + ∑ i = 1 n λ i − ∑ i = 1 n λ i y i ( ∑ j = 1 n λ j x j y j ⋅ x i + b ) − ∑ i = 1 n λ i ξ i − ∑ i = 1 n μ i ξ i = 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( x i ⋅ x j ) + ∑ i = 1 n λ i − ∑ i = 1 n ∑ j = 1 n λ i y i λ j y j ( x i ⋅ x j ) = ∑ i = 1 n λ i − 1 2 ∑ i = 1 n ∑ j = 1 n λ i y i λ j y j ( x i ⋅ x j ) s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n C − λ i − μ i = 0 − − − 式 k \begin{aligned}&\max\limits_{\lambda,\mu}L(w,b,\xi,\lambda,\mu) =\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i+\sum\limits_{i=1}^n\lambda_i[1-y_i(w^T\cdot x_i +b)-\xi_i] - \sum\limits_{i=1}^n\mu_i\xi_i\\\\&=\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_j y_i y_j(x_i\cdot x_j) +\sum\limits_{i=1}^n\lambda_i\xi_i +\sum\limits_{i=1}^n\mu_i\xi_i +\sum\limits_{i=1}^n\lambda_i-\sum\limits_{i=1}^n\lambda_iy_i(\sum\limits_{j=1}^n\lambda_jx_jy_j\cdot x_i +b)-\sum\limits_{i=1}^n\lambda_i\xi_i-\sum\limits_{i=1}^n\mu_i\xi_i\\\\&=\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_j y_i y_j(x_i\cdot x_j) +\sum\limits_{i=1}^n\lambda_i -\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_iy_i\lambda_jy_j(x_i\cdot x_j)\\\\&=\sum\limits_{i=1}^n\lambda_i -\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_iy_i\lambda_jy_j(x_i\cdot x_j)\\\\&\quad \quad s.t\quad \lambda_i\ge0,\mu_i \ge 0\quad i = 1,2,\cdots,n\quad C - \lambda_i-\mu_i =0 \quad ---式\ k\end{aligned} λ,μmaxL(w,b,ξ,λ,μ)=21∣∣w∣∣2+Ci=1∑nξi+i=1∑nλi[1−yi(wT⋅xi+b)−ξi]−i=1∑nμiξi=21i=1∑nj=1∑nλiλjyiyj(xi⋅xj)+i=1∑nλiξi+i=1∑nμiξi+i=1∑nλi−i=1∑nλiyi(j=1∑nλjxjyj⋅xi+b)−i=1∑nλiξi−i=1∑nμiξi=21i=1∑nj=1∑nλiλjyiyj(xi⋅xj)+i=1∑nλi−i=1∑nj=1∑nλiyiλjyj(xi⋅xj)=i=1∑nλi−21i=1∑nj=1∑nλiyiλjyj(xi⋅xj)s.tλi≥0,μi≥0i=1,2,⋯,nC−λi−μi=0−−−式 k
我们发现上式中求 max λ , μ L ( w , b , ξ , λ , μ ) \max\limits_{\lambda,\mu}L(w,b,\xi,\lambda,\mu) λ,μmaxL(w,b,ξ,λ,μ)与 μ \mu μ没有关系,但是为什么可以消掉是因为 C = λ i + μ i C = \lambda_i + \mu_i C=λi+μi,所以在约束条件中一定有此条件,所以我们得到最终的目标函数可以写成如下:
max λ L ( w , b , ξ , λ , μ ) = max λ [ ∑ i = 1 n λ i − 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( x i ⋅ x j ) ] s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n C − λ i − μ i = 0 − − − 式 L \begin{aligned}\max\limits_{\lambda}&L(w,b,\xi,\lambda,\mu) = \max\limits_\lambda[\sum\limits_{i=1}^n\lambda_i -\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_jy_iy_j(x_i\cdot x_j)]\\\\&s.t\quad \lambda_i\ge0,\mu_i \ge 0\quad i = 1,2,\cdots,n\quad C - \lambda_i-\mu_i =0 \quad ---式\ L\end{aligned} λmaxL(w,b,ξ,λ,μ)=λmax[i=1∑nλi−21i=1∑nj=1∑nλiλjyiyj(xi⋅xj)]s.tλi≥0,μi≥0i=1,2,⋯,nC−λi−μi=0−−−式 L
推导到以上之后,我们发现结果和硬间隔结果一样,参照4.3 d式,只是结果中多了约束条件 C = λ i + μ i C = \lambda_i + \mu_i C=λi+μi。
3.求解结果
同样我们也可以利用SMO算法对式L 求解得到一组合适的 λ \lambda λ值和 μ \mu μ值,由于综上所述,我们可以的到最终的w和b的值如下:
{ w = ∑ i = 1 n λ i ⋅ x i ⋅ y i b = 1 S ∑ i ∈ S ( y i − w T ⋅ x i ) \left\{\begin{aligned}&w = \sum\limits_{i=1}^n\lambda_i\cdot x_i\cdot y_i \\\\&b = \frac{1}{S}\sum\limits_{i \in S}(y_i - w^T \cdot x_i)\end{aligned}\right. ⎩ ⎨ ⎧w=i=1∑nλi⋅xi⋅yib=S1i∈S∑(yi−wT⋅xi)
这里得到的w和b虽然和硬分割结果一样,但是这是加入松弛变量之后得到的w和b的值,根据L 式的条件 C = λ i + μ i C = \lambda_i + \mu_i C=λi+μi和 λ i ≥ 0 , μ i ≥ 0 \lambda_i \ge 0,\mu_i \ge 0 λi≥0,μi≥0,结合h式,C越大,必然导致松弛越小,如果C无穷大,那么就意味着模型过拟合,在训练SVM时,C是我们需要调节的参数。
那么确定w和b之后,我们就能构造出最大分割超平面: w T ⋅ x + b = 0 w^T\cdot x +b = 0 wT⋅x+b=0,新来样本对应的特征代入后得到的结果如果是大于0那么属于一类,小于0属于另一类。
5.3、SVM代码演练
以乳腺癌为例,使用SVM进行建模训练
python
from sklearn.svm import SVC
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
X,y = datasets.load_breast_cancer(return_X_y=True)
score = 0
for i in range(100):
X_train,X_test,y_train,y_test = train_test_split(X,y)
model = SVC(C = 1.0)
model.fit(X_train,y_train)
score += model.score(X_test,y_test)
print('模型平均得分是:',score)
5.4、网格搜索最佳参数
网格搜索就是手动给定模型中想要改动的所有参数,程序自动使用穷举法来将所有的参数或者参数组合都运行一遍,将对应得到的模型做K折交叉验证,将得分最高的参数或参数组合当做最佳结果,并得到模型。
也就是说网格搜索用来获取最合适的一组参数,不需要我们手动一个个尝试。使用网格搜索由于针对每个参数下的模型需要做K折交叉验证最终导致加大了模型训练时间,所以一般我们可以在小的训练集中使用网格搜索找到对应合适的参数值,再将合适的参数使用到大量数据集中训练模型。例如:逻辑回归中使用正则项时,我们可以先用一小部分训练集确定合适的惩罚系数,然后将惩罚系数应用到大量训练集中训练模型。
python
from sklearn.svm import SVC
import numpy as np
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.model_selection import GridSearchCV
import pandas as pd
X,y = datasets.load_breast_cancer(return_X_y=True)
score = 0
search_space = {'C': np.logspace(-3, 3, 7)}
best_params = []
for i in range(100):
X_train,X_test,y_train,y_test = train_test_split(X,y)
model = SVC()
gc = GridSearchCV(model, param_grid=search_space,cv=5)
gc.fit(X_train,y_train)
best_params.append(gc.best_params_['C'])
best_model = gc.best_estimator_
best_model.fit(X_train,y_train)
score += best_model.score(X_test,y_test)
print('模型平均得分是:',score)
# 查看最佳参数
pd.value_counts(best_params)
6、SVM Hinge Loss(了解)
软间隔情况下,SVM的目标函数如下:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i s . t 1 − y ( w T ⋅ x i + b ) − ξ i ≤ 0 , ξ i ≥ 0 , i = 1 , 2 , ⋯ , n − − − 式 h min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^n\xi_i\quad s.t\quad 1-y(w^T\cdot x_i +b) - \xi_i \le 0,\xi_i\ge0,i = 1,2,\cdots,n\quad ---式h min21∣∣w∣∣2+Ci=1∑nξis.t1−y(wT⋅xi+b)−ξi≤0,ξi≥0,i=1,2,⋯,n−−−式h
其实这里我们说SVM的损失主要说的就是上式中的松弛变量 ξ i \xi_i ξi损失,当所有样本总的 ξ i \xi_i ξi为0时那么就是一个完全线性可分的SVM;如果SVM不是线性可分,那么我们希望总体样本的松弛变量 ∑ i = 1 n ξ i \sum\limits_{i=1}^n\xi_i i=1∑nξi越小越好。
根据h式的条件$ 1-y(w^T\cdot x_i +b) - \xi_i \le 0,\xi_i \ge 0$我们可以改写成如下:
ξ i ≥ 1 − y ( w T ⋅ x i + b ) , ξ i ≥ 0 \xi_i \ge 1-y(w^T\cdot x_i +b) ,\xi_i\ge 0 ξi≥1−y(wT⋅xi+b),ξi≥0
根据下图结合以上两个条件我们可以继续改写成如下:
[外链图片转存中...(img-SyxmjmiJ-1734921194630)]
ξ i = m a x ( 0 , 1 − y ( w T ⋅ x i + b ) ) − − − 式 m \xi_i = max(0,\ 1-y(w^T\cdot x_i +b)) \quad --- 式m ξi=max(0, 1−y(wT⋅xi+b))−−−式m
上式等价于:
ξ i = { 0 y ( w T ⋅ x i + b ) ≥ 1 1 − y ( w T ⋅ x i + b ) y ( w T ⋅ x i + b ) < 1 \xi_i = \left\{\begin{aligned}&0\quad y (w^T\cdot x_i +b ) \ge 1 \\\\& 1-y (w^T\cdot x_i +b )\quad y (w^T\cdot x_i +b ) < 1\end{aligned}\right. ξi=⎩ ⎨ ⎧0y(wT⋅xi+b)≥11−y(wT⋅xi+b)y(wT⋅xi+b)<1
以上公式就是SVM的损失函数,称为"Hinge Loss",也被叫做"合页损失函数"。其图像如下:
[外链图片转存中...(img-qEmZKJab-1734921194630)]
特点是当 y ( w T ⋅ x i + b ) ≥ 1 y(w^T\cdot x_i +b) \ge 1 y(wT⋅xi+b)≥1时损失为0。
我们可以将m式代入到h式得到新的目标函数,暂时先不关注约束条件,新的目标函数如下:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n m a x ( 0 , 1 − y ( w T ⋅ x i + b ) ) min\frac{1}{2}||w||^2 + C\sum\limits_{i=1}^nmax(0,\ 1-y(w^T\cdot x_i +b)) min21∣∣w∣∣2+Ci=1∑nmax(0, 1−y(wT⋅xi+b))
针对新的目标函数我们同样也是最小化整体目标函数。我们发现以上目标函数与逻辑回归L2正则化的损失函数在形式上非常类似,将上式可以改写成如下:
m i n 1 2 ∣ ∣ w ∣ ∣ 2 + L O S S min\frac{1}{2}||w||^2 + LOSS min21∣∣w∣∣2+LOSS
逻辑回归L2正则化损失函数如下:
J ( θ ) = − ∑ i = 1 n [ y ( i ) ln ( h θ ( x ( i ) ) ) + ( 1 − y ( i ) ) ln ( 1 − h θ ( x ( i ) ) ) ] + λ ∑ i = 1 n w i 2 J(\theta) = -\sum\limits_{i = 1}^n[y^{(i)}\ln(h_{\theta}(x^{(i)})) + (1-y^{(i)})\ln(1-h_{\theta}(x^{(i)}))] + \lambda \sum\limits_{i=1}^nw_i^2 J(θ)=−i=1∑n[y(i)ln(hθ(x(i)))+(1−y(i))ln(1−hθ(x(i)))]+λi=1∑nwi2
也可以改写成如下:
J ( θ ) = L O S S + λ ∑ i = 1 n w i 2 J(\theta) = LOSS + \lambda \sum\limits_{i=1}^nw_i^2 J(θ)=LOSS+λi=1∑nwi2
如果将逻辑损失函数图像与"Hinge Loss"图像放在一起图像如下:
[外链图片转存中...(img-ui50iyDc-1734921194630)]
通过上图我们可以看出,在训练逻辑回归时,损失永远不会为0,因此即使分类正确,逻辑回归仍然会不停的训练,以求得更小的损失和更大的概率,但是极有可能出现过拟合,这就是为什么我们需要在梯度下降中提前终止的原因。但是在SVM中,如果分类正确可以直接达到 ∑ i = 1 n ξ i = 0 \sum\limits_{i=1}^n\xi_i =0 i=1∑nξi=0,不再进行对分类无益的训练,即学习到一定程度就不再学习。
7、核函数
7.1、非线性核函数
在前面SVM讨论的硬间隔和软间隔都是指的样本完全可分或者大部分样本点线性可分的情况。我们可以使用升维方式来解决这种线性不可分的问题,例如目前只有两个维度 x 1 , x 2 x_1,x_2 x1,x2,我们可以基于已有的维度进行升维得到更多维度,例如: x 1 , x 2 , x 1 x 2 x_1,x_2,x_1x_2 x1,x2,x1x2,这样我们可以将以上问题可以转换成高维可分问题。SVM中线性不可分问题就是非线性SVM问题,对这种问题我们可以将样本映射到高维空间,再通过间隔最大化的方式学习得到支持向量机。
7.2、核函数(kernel function)
假设原有特征有如下三个 x 1 , x 2 , x 3 x_1,x_2,x_3 x1,x2,x3,那么基于三个已有特征进行两两组合(二阶交叉)我们可以得到如下更多特征:
[ x 1 2 、 x 1 x 2 、 x 1 x 3 、 x 2 2 、 x 2 x 1 、 x 2 x 3 、 x 3 2 、 x 3 x 1 、 x 3 x 2 ] [x_1^2、x_1x_2、x_1x_3、x_2^2、x_2x_1、x_2x_3、x_3^2、x_3x_1、x_3x_2] [x12、x1x2、x1x3、x22、x2x1、x2x3、x32、x3x1、x3x2]
我们在训练模型时将以上组合特征可以参与到模型的训练中,其代价是运算量过大,比如原始特征有m个,那么二阶交叉的维度为 C m 2 C_m^2 Cm2个,这种量级在实际应用中很难实现,那么有没有一种方式可以在升维的同时可以有效的降低运算量,在非线性SVM中,核函数就可以实现在升维的同时可以有效降低运算量,那么核函数是什么?
有两个向量 m = [ m 1 , m 2 , m 3 ] T , n = [ n 1 , n 2 , n 3 ] T m = [m_1,m_2,m_3]^T,n = [n_1,n_2,n_3]^T m=[m1,m2,m3]T,n=[n1,n2,n3]T,我们分别对两个向量进行相同升维分别记为 ϕ m , ϕ n \phi m,\phi n ϕm,ϕn:
ϕ m = [ m 1 2 、 m 1 m 2 、 m 1 m 3 、 m 2 2 、 m 2 m 1 、 m 2 m 3 、 m 3 2 、 m 3 m 1 、 m 3 m 2 ] T ϕ n = [ n 1 2 、 n 1 n 2 、 n 1 n 3 、 n 2 2 、 n 2 n 1 、 n 2 n 3 、 n 3 2 、 n 3 n 1 、 n 3 n 2 ] T \begin{aligned}&\phi m = [m_1^2、m_1m_2、m_1m_3、m_2^2、m_2m_1、m_2m_3、m_3^2、m_3m_1、m_3m_2]^T\\\\&\phi n = [n_1^2、n_1n_2、n_1n_3、n_2^2、n_2n_1、n_2n_3、n_3^2、n_3n_1、n_3n_2]^T\end{aligned} ϕm=[m12、m1m2、m1m3、m22、m2m1、m2m3、m32、m3m1、m3m2]Tϕn=[n12、n1n2、n1n3、n22、n2n1、n2n3、n32、n3n1、n3n2]T
之后计算两者内积如下:
ϕ m ⋅ ϕ n = m 1 2 n 1 2 + m 1 m 2 n 1 n 2 + m 1 m 3 n 1 n 3 + m 2 2 n 2 2 + m 2 m 1 n 2 n 1 + m 2 m 3 n 2 n 3 + m 3 2 n 3 2 + m 3 m 1 n 3 n 1 + m 3 m 2 n 3 n 2 = m 1 2 n 1 2 + m 2 2 n 2 2 + m 3 2 n 3 2 + 2 m 1 m 2 n 1 n 2 + 2 m 1 m 3 n 1 n 3 + 2 m 2 m 3 n 2 n 3 − − − 式 o \begin{aligned}\phi m\cdot \phi n &= m_1^2n_1^2+m_1m_2n_1n_2+m_1m_3n_1n_3+m_2^2n_2^2+m_2m_1n_2n_1\\\\&+m_2m_3n_2n_3+m_3^2n_3^2+m_3m_1n_3n_1+m_3m_2n_3n_2\\\\&=m_1^2n_1^2 + m_2^2n_2^2+m_3^2n_3^2 + 2m_1m_2n_1n_2 + 2m_1m_3n_1n_3 + 2m_2m_3n_2n_3\quad ---式o\end{aligned} ϕm⋅ϕn=m12n12+m1m2n1n2+m1m3n1n3+m22n22+m2m1n2n1+m2m3n2n3+m32n32+m3m1n3n1+m3m2n3n2=m12n12+m22n22+m32n32+2m1m2n1n2+2m1m3n1n3+2m2m3n2n3−−−式o
另外我们计算m和n的内积如下:
m ⋅ n = m 1 n 1 + m 2 n 2 + m 3 n 3 m\cdot n = m_1n_1 + m_2n_2 + m_3n_3 m⋅n=m1n1+m2n2+m3n3
对结果进行平方得到:
( m ⋅ n ) 2 = ( m 1 n 1 + m 2 n 2 + m 3 n 3 ) 2 = m 1 2 n 1 2 + m 2 2 n 2 2 + m 3 2 n 3 2 + 2 m 1 m 2 n 1 n 2 + 2 m 1 m 3 n 1 n 3 + 2 m 2 m 3 n 2 n 3 − − − 式 p \begin{aligned}(m\cdot n)^2 &= (m_1n_1 + m_2n_2 + m_3n_3)^2\\\\&=m_1^2n_1^2 + m_2^2n_2^2+m_3^2n_3^2 + 2m_1m_2n_1n_2 + 2m_1m_3n_1n_3 + 2m_2m_3n_2n_3\quad ---式p\end{aligned} (m⋅n)2=(m1n1+m2n2+m3n3)2=m12n12+m22n22+m32n32+2m1m2n1n2+2m1m3n1n3+2m2m3n2n3−−−式p
【备注】: ( a + b + c ) 2 = a 2 + b 2 + c 2 + 2 a b + 2 a c + 2 b c (a + b + c)^2 = a^2 + b^2 + c^2 + 2ab + 2ac + 2bc (a+b+c)2=a2+b2+c2+2ab+2ac+2bc
我们发现o式和p式结果一样,也就是
ϕ m ⋅ ϕ n = ( m ⋅ n ) 2 − − − 式 q \phi m\cdot \phi n = (m\cdot n)^2 \quad ---式q ϕm⋅ϕn=(m⋅n)2−−−式q
以上在m和n向量中只有3个元素时推导成立,那么在m和n中如果有多个元素时也一样成立。
我们发现,如果最终目标只是计算向量升维后的内积 ϕ m ⋅ ϕ n \phi m\cdot \phi n ϕm⋅ϕn,根据q式可知,我们可以先计算原始向量的内积 m ⋅ n m\cdot n m⋅n,再进行平方运算,而不需要真正的进行高运算量的升维操作。这种通过两个低维向量进行数学运算得到它们投影至高维空间时向量的内积方法叫做核方法,相应的算法叫做核函数,上面案例核函数记为:
K ( m ⋅ n ) = ϕ m ⋅ ϕ n = ( m ⋅ n ) 2 K(m\cdot n) = \phi m\cdot \phi n = (m\cdot n)^2 K(m⋅n)=ϕm⋅ϕn=(m⋅n)2
以上核函数叫做多项式核函数,常用的核函数有如下几种,不同的核函数的区别是将向量映射到高维空间时采用的升维方法不同,不过高维向量都是不需要计算出来的。
- 线性核函数:
K ( x i ⋅ x j ) = x i T ⋅ x j K(x_i\cdot x_j) = x_i^T\cdot x_j K(xi⋅xj)=xiT⋅xj
- 多项式核函数:
K ( x i ⋅ x j ) = ( α ( x i T ⋅ x j ) + c ) d α , c , d 都是参数 K(x_i\cdot x_j) = (\alpha(x_i^T\cdot x_j) + c) ^d\quad \alpha,c,d都是参数 K(xi⋅xj)=(α(xiT⋅xj)+c)dα,c,d都是参数
- 高斯核函数:
K ( x i ⋅ x j ) = e − ∣ ∣ x i − x j ∣ ∣ 2 2 δ 2 K(x_i\cdot x_j) = e^{-\frac{||x_i - x_j||^2}{2\delta^2}} K(xi⋅xj)=e−2δ2∣∣xi−xj∣∣2
7.3、核函数在SVM中应用
在非线性SVM中,我们可以对原始特征进行升维,原有的超平面 w T ⋅ x + b = 0 w^T\cdot x +b = 0 wT⋅x+b=0变成了 w T ⋅ ϕ x + b = 0 w^T \cdot \phi x + b = 0 wT⋅ϕx+b=0,根据 L 式SVM目标函数:
max λ L ( w , b , ξ , λ , μ ) = max λ [ ∑ i = 1 n λ i − 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( x i ⋅ x j ) ] s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n C − λ i − μ i = 0 − − − 式 L \begin{aligned}\max\limits_{\lambda}&L(w,b,\xi,\lambda,\mu) = \max\limits_\lambda[\sum\limits_{i=1}^n\lambda_i -\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_jy_iy_j(x_i\cdot x_j)]\\\\&s.t\quad \lambda_i\ge0,\mu_i \ge 0\quad i = 1,2,\cdots,n\quad C - \lambda_i-\mu_i =0 \quad ---式\ L\end{aligned} λmaxL(w,b,ξ,λ,μ)=λmax[i=1∑nλi−21i=1∑nj=1∑nλiλjyiyj(xi⋅xj)]s.tλi≥0,μi≥0i=1,2,⋯,nC−λi−μi=0−−−式 L
可知最终经过对偶处理后的目标函数如下:
max λ L ( w , b , ξ , λ , μ ) = max λ [ ∑ i = 1 n λ i − 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( ϕ x i ⋅ ϕ x j ) ] s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n C − λ i − μ i = 0 \begin{aligned}\max\limits_{\lambda}&L(w,b,\xi,\lambda,\mu) = \max\limits_\lambda[\sum\limits_{i=1}^n\lambda_i -\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_jy_iy_j(\phi x_i\cdot \phi x_j)]\\\\&s.t\quad \lambda_i\ge0,\mu_i \ge 0\quad i = 1,2,\cdots,n\quad C - \lambda_i-\mu_i =0 \end{aligned} λmaxL(w,b,ξ,λ,μ)=λmax[i=1∑nλi−21i=1∑nj=1∑nλiλjyiyj(ϕxi⋅ϕxj)]s.tλi≥0,μi≥0i=1,2,⋯,nC−λi−μi=0
以上公式与l式不同的是只是将 x i ⋅ x j x_i\cdot x_j xi⋅xj转换成了 ϕ x i ⋅ ϕ x j \phi x_i \cdot \phi x_j ϕxi⋅ϕxj,这样我们可以将上式进而转换成下式:
max λ L ( w , b , ξ , λ , μ ) = max λ [ ∑ i = 1 n λ i − 1 2 ∑ i = 1 n ∑ j = 1 n λ i λ j y i y j ( x i ⋅ x j ) 2 ] s . t λ i ≥ 0 , μ i ≥ 0 i = 1 , 2 , ⋯ , n C − λ i − μ i = 0 − − − 式 r \begin{aligned}\max\limits_{\lambda}&L(w,b,\xi,\lambda,\mu) = \max\limits_\lambda[\sum\limits_{i=1}^n\lambda_i -\frac{1}{2}\sum\limits_{i=1}^n\sum\limits_{j=1}^n\lambda_i\lambda_jy_iy_j(x_i\cdot x_j)^2]\\\\&s.t\quad \lambda_i\ge0,\mu_i \ge 0\quad i = 1,2,\cdots,n\quad C - \lambda_i-\mu_i =0 \quad ---式r\end{aligned} λmaxL(w,b,ξ,λ,μ)=λmax[i=1∑nλi−21i=1∑nj=1∑nλiλjyiyj(xi⋅xj)2]s.tλi≥0,μi≥0i=1,2,⋯,nC−λi−μi=0−−−式r
这样我们可以通过核函数将数据映射到高维空间,但是核函数是在低维上进行计算,而将实质上的分类效果表现在了高维空间上,来解决在原始空间中线性不可分的问题。
在SVM中我们可以使用常用的核函数:线性核函数、多项式核函数、高斯核函数来进行升维解决线性不可分问题,应用最广泛的就是高斯核函数,无论是小样本还是大样本、高维或者低维,高斯核函数均适用,它相比于线性核函数来说,线性核函数只是高斯核函数的一个特例,线性核函数适用于数据本身线性可分,通过线性核函数来达到更理想情况。高斯核函数相比于多项式核函数,多项式核函数阶数比较高时,内部计算时会导致一些元素值无穷大或者无穷小,而在高斯核函数会减少数值的计算困难。
综上,我们在非线性SVM中使用核函数时,先使用线性核函数,如果不行尝试换不同的特征,如果还不行那么可以直接使用高斯核函数。
非线性SVM使用核函数代码如下:
python
from sklearn import svm
from sklearn import datasets
from sklearn.model_selection import train_test_split as ts
X,y = datasets.load_wine(return_X_y=True)
#split the data to 7:3
X_train,X_test,y_train,y_test = ts(X,y,test_size=0.3)
print(y_test)
# select different type of kernel function and compare the score
# kernel = 'rbf'
clf_rbf = svm.SVC(kernel='rbf')
clf_rbf.fit(X_train,y_train)
score_rbf = clf_rbf.score(X_test,y_test)
print("The score of rbf is : %f"%score_rbf)
# kernel = 'linear'
clf_linear = svm.SVC(kernel='linear')
clf_linear.fit(X_train,y_train)
score_linear = clf_linear.score(X_test,y_test)
print("The score of linear is : %f"%score_linear)
# kernel = 'poly'
clf_poly = svm.SVC(kernel='poly')
clf_poly.fit(X_train,y_train)
score_poly = clf_poly.score(X_test,y_test)
print("The score of poly is : %f"%score_poly)
7.4、核函数代码
SVM核函数
导包
python
import numpy as np
from sklearn import datasets
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
加载数据
python
X,y = datasets.load_wine(return_X_y=True)
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2)
display(X_train.shape)
(142, 13)
线性核函数
python
y
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2])
python
X_train.shape
(142, 13)
python
svc = SVC(kernel='linear') # 线性方程
svc.fit(X_train,y_train)
svc.score(X_test,y_test)
# coeficient系数,方程系数【斜率】,截距
display(svc.coef_,svc.intercept_,svc.coef0)
array([[ 0.87461679, 0.58503034, 1.30901877, -0.2053376 , 0.00791142,
-0.02648789, 0.28527406, 0.25120048, -0.14808948, 0.4932904 ,
-0.16508327, 0.55177431, 0.00439756],
[ 0.00751869, 0.06280402, 0.13381895, -0.03612393, 0.01335316,
0.27556403, 0.44767092, -0.0124128 , 0.16396695, -0.06890565,
0.0985208 , 0.40013235, 0.00186776],
[-0.30289155, -0.28857803, -0.57307745, 0.07076996, -0.038963 ,
0.14831149, 1.34058488, 0.10782495, 0.2291751 , -1.00113637,
0.4848562 , 0.42472284, -0.00238992]])
array([-19.84003733, -5.08521134, 11.08381003])
0.0
高斯核函数
python
svc = SVC(kernel='rbf')
svc.fit(X_train,y_train)
svc.score(X_test,y_test)
# svc.coef_
0.6666666666666666
多项式核函数
python
svc = SVC(kernel='poly',degree=2,coef0=0)
svc.fit(X_train,y_train)
svc.score(X_test,y_test)
0.7222222222222222
sigmoid
python
svc = SVC(kernel='sigmoid')
svc.fit(X_train,y_train)
svc.score(X_test,y_test)
0.2222222222222222
python
# 机器学习:
# 理论基础判断,第六感觉
# 实际基础判断
非线性核函数
python
import matplotlib.pyplot as plt
python
from matplotlib.colors import ListedColormap# 指定颜色
造数据
python
# 没有拆分,也可以,练习
X,y = datasets.make_circles(n_samples=100,factor=0.7)# 两个特征
X += np.random.randn(100,2) * 0.03 # 逼真
plt.figure(figsize=(6,6))
c = ListedColormap(colors=['blue','#FF0000'])
plt.scatter(X[:,0],X[:,1],c = y,cmap = c)
<matplotlib.collections.PathCollection at 0x1e857fd4940>
线性核函数
python
svc = SVC(kernel='linear')
svc.fit(X,y)
svc.score(X,y)
0.51
poly【升维】
python
svc = SVC(kernel='poly',degree=2)
svc.fit(X,y)
svc.score(X,y)
1.0
rbf【高斯】
python
svc = SVC(kernel='rbf')
svc.fit(X,y)
svc.score(X,y)
1.0
sigmoid
python
svc = SVC(kernel='sigmoid')
svc.fit(X,y)
svc.score(X,y)
0.55
python
8、支持向量机SVM特点
8.1、抗干扰能力强
根据一些样本点,我们可以通过拉格朗日乘数法、KKT条件、对偶问题、SMO算法计算出支持向量机SVM的分类线 w T ⋅ x + b = 0 w^T\cdot x + b = 0 wT⋅x+b=0,其中
{ w = ∑ i = 1 n λ i ⋅ x i ⋅ y i b = 1 S ∑ i ∈ S ( y i − w T ⋅ x i ) \left\{\begin{aligned}&w = \sum\limits_{i=1}^n\lambda_i\cdot x_i\cdot y_i \\\\&b = \frac{1}{S}\sum\limits_{i \in S}(y_i - w^T \cdot x_i)\end{aligned}\right. ⎩ ⎨ ⎧w=i=1∑nλi⋅xi⋅yib=S1i∈S∑(yi−wT⋅xi)
S代表的是边界上的样本点。
我们可以看出SVM在训练过程中找到的是两类点的分割线,计算样本中有少量异常点,在训练模型时依然能很正确的找到中间分割线,因为训练SVM时考虑了全量数据,确定这条线的b时只与支持向量点(边界上的点)有关。同样在测试集中就算有一些样本点是异常点也不会影响其正常分类,SVM具有抗干扰能力强的特点。
此外,由于训练SVM需要所有样本点参与模型训练,不然不能缺点这条线,所以当数据量大时,SVM训练占用内存非常大。这是SVM模型的缺点。
8.2、二分类及多分类
SVM同样支持多分类,我们可以将一个多分类问题拆分成多个二分类问题,例如有A,B,C三类,我们使用SVM训练时可以训练3个模型,第一个模型针对是A类和不是A类进行训练。第二个模型针对是B类和不是B类进行训练。第三个模型针对是C类和不是C类进行训练。这样可以解决多分类问题。