赞
踩
对两类样本点进行分类,如下图,有a线、b线、c线三条线都可以将两类样本点很好的分开类,我们可以观察到b线将两类样本点分类最好,原因是我们训练出来的分类模型主要应用到未知样本中,虽然a、b、c三条线将训练集都很好的分开类,但是当三个模型应用到新样本中时,b线抗干扰能力最强,也就是泛化能力最好,样本变化一些关系不大,一样能被正确的分类。那么如何确定b线的位置呢?我们可以使用支持向量机SVM来确定b线的位置。

支持向量机(support vector machines,SVM)是一种二分类算法,它的目的是寻找一个超平面来对样本进行分割,分割的原则是间隔最大化,如果对应的样本特征少,一个普通的SVM就是一条线将样本分隔开,但是要求线到两个类别最近样本点的距离要最大。

如上图所示,b线就是我们根据支持向量机要找到的分割线,这条线需要到两个类别最近的样本点最远,图上的距离就是d,由于这条线处于两个类别的中间,所以到两个类别的距离都是d。
支持向量机SVM算法就是在寻找一个最优的决策边界(上图中的两条虚线)来确定分类线b,所说的支持向量(support vector)就是距离决策边界最近的点(上图中p1、p2、p3点,只不过边界穿过了这些点)。如果没有这些支持向量点,b线的位置就要改变,所以SVM就是根据这些支持向量点来最大化margin,来找到了最优的分类线(machine,分类器),这也是SVM分类算法名称的由来。
接着上面的分类问题来分析,假设支持向量机最终要找的线是
l
2
l_2
l2,决策边界两条线是
l
1
l_1
l1和
l
3
l_3
l3,那么假设
l
2
l_2
l2的方程为
w
T
⋅
x
+
b
=
0
w^T{\cdot}x+b=0
wT⋅x+b=0,这里w表示
(
w
1
,
w
2
)
T
(w_1,w_2)^T
(w1,w2)T,x表示
(
x
1
,
x
2
)
T
(x_1,x_2)^T
(x1,x2)T,我们想要确定
l
2
l_2
l2直线,只需要确定w和b即可,此外,由于
l
1
l_1
l1和
l
3
l_3
l3线是
l
2
l_2
l2的决策分类边界线,一定与
l
2
l_2
l2是平行的,平行就意味着斜率不变,b变化即可,所以我们可以假设线
l
1
l_1
l1的方程为
w
T
⋅
x
+
b
=
c
w^T{\cdot}x+b=c
wT⋅x+b=c,
l
3
l_3
l3线的方程为
w
T
⋅
x
+
b
=
−
c
w^T{\cdot}x+b=-c
wT⋅x+b=−c。

【知识补充】:
二维空间 ( x 1 , y 1 ) (x_1,y_1) (x1,y1)到直线 A x + B y + C = 0 Ax+By+C=0 Ax+By+C=0的距离公式为:
两条平行线 A x + B y + C 1 = 0 Ax+By+C_1=0 Ax+By+C1=0与 A x + B y + C 2 = 0 Ax+By+C_2=0 Ax+By+C2=0之间的距离公式为:
我们希望的是决策边界上的样本点到 l 2 l_2 l2直线的距离d越大越好。我们可以直接计算 l 1 l_1 l1或 l 3 l_3 l3上的点到直线 l 2 l_2 l2的距离,假设将空间点扩展到n维空间后,点 x i = ( x 1 , x 2 , … , x n ) x_i=(x_1,x_2,\dots,x_n) xi=(x1,x2,…,xn)到直线 w T ⋅ x + b = 0 w^T{\cdot}x+b=0 wT⋅x+b=0(严格意义上来说直线变成了超平面)的距离为:
以上 ∣ ∣ w ∣ ∣ = w 1 w + w 2 2 + ⋯ + w n 2 ||w||=\sqrt{w_1^w+w_2^2+\dots+w_n^2} ∣∣w∣∣=w1w+w22+⋯+wn2 ,读作“w的模”。
由于 l 1 l_1 l1、 l 2 l_2 l2和 l 3 l_3 l3三条直线平行,d也是两条平行线之间的距离,我们可以根据两条平行线之间的距离公式得到d值如下:
我们可以看到无论计算点到直线的距离还是两个平行线之间的距离,最终结果是一致的。对于 l 1 l_1 l1直线,我们可以相对应成比例的 w T ⋅ x + b = c w^T{\cdot}x+b=c wT⋅x+b=c 缩小各项的系数,例如变成 w T 2 ⋅ x + b 2 = c 2 \frac{w^T}{2}{\cdot}x+\frac{b}{2}=\frac{c}{2} 2wT⋅x+2b=2c ,这条直线还是原本本身的直线,现在我们可以把它变成 w T c ⋅ x + b c = c c = 1 \frac{w^T}{c}{\cdot}x+\frac{b}{c}=\frac{c}{c}=1 cwT⋅x+cb=cc=1,即改写后的 l 3 l_3 l3 直线 w T ⋅ x + b = 1 w^T{\cdot}x+b=1 wT⋅x+b=1还是原来的直线,同理,对于 l 1 l_1 l1直线我们也可以变换成 w T ⋅ x + b = − 1 w^T{\cdot}x+b=-1 wT⋅x+b=−1,所以上图可以改变成如下:
那么变换之后的d可以根据两条平行线之间的距离得到:
我们希望决策边界上的点到超平面 l 2 l_2 l2距离d越大越好。我们将 l 3 l_3 l3上方的点分类标记为“1”类别,将 l 1 l_1 l1下方的点分类标记为“-1”类别,那么我们可以得到如下公式:
两式两侧分别乘以对应的类别可以合并为一个式子: y ⋅ ( w T ⋅ x i + b ) > = 1 y{\cdot}(w^T{\cdot}x_i+b)>=1 y⋅(wT⋅xi+b)>=1所以在计算d的最大值时,是有限制条件的,这个限制条件就是 y ⋅ ( w T ⋅ x i + b ) > = 1 y{\cdot}(w^T{\cdot}x_i+b)>=1 y⋅(wT⋅xi+b)>=1
所以对于所有样本点我们需要在满足 y ⋅ ( w T ⋅ x i + b ) > = 1 y{\cdot}(w^T{\cdot}x_i+b)>=1 y⋅(wT⋅xi+b)>=1条件下,最大化 d = 1 ∣ ∣ w ∣ ∣ d=\frac{1}{||w||} d=∣∣w∣∣1,就是最小化 ∣ ∣ w ∣ ∣ ||w|| ∣∣w∣∣,等效于最小化 1 2 ∣ ∣ w ∣ ∣ 2 \frac{1}{2}||w||^2 21∣∣w∣∣2,这样转换的目的就是为了后期优化过程中求导时方便操作,不会影响最终的结果,所以在支持向量机SVM中要确定一个分类线,我们要做的就是在 y ⋅ ( w T ⋅ x i + b ) > = 1 y{\cdot}(w^T{\cdot}x_i+b)>=1 y⋅(wT⋅xi+b)>=1条件下最小化 1 2 ∣ ∣ w ∣ ∣ 2 \frac{1}{2}||w||^2 21∣∣w∣∣2,记为:
以上n代表样本总数,缩写表示“Subject to”是“服从某某条件”的意思,上述公式描述的是一个典型的不等式约束条件下的二次型函数优化问题,同时也是支持向量机的基本数学模型,这里我们称支持向量机的目标函数。
拉格朗日乘数法主要是将有等式约束条件优化问题转换为无约束优化问题,拉格朗日乘数法如下:
假设 x = [ x 1 , x 2 , … , x n ] x=[x_1,x_2,\dots,x_n] x=[x1,x2,…,xn]是一个n维向量, f ( x ) f(x) f(x)和 h ( x ) h(x) h(x)含有x的函数,我们需要找到满足 h ( x ) = 0 h(x)=0 h(x)=0条件下$f(x)¥最小值,如下:
可以引入一个自变量 λ \lambda λ, λ \lambda λ可以取任意值,则上式严格等价于下式:
L ( x , λ ) L(x,\lambda) L(x,λ)叫做Lagrange函数(拉格朗日函数), λ \lambda λ叫做拉格朗日乘子(其实就是系数)。令 L ( x , λ ) L(x,\lambda) L(x,λ)对x的导数为0,对 λ \lambda λ的导数为0,求解出x, λ \lambda λ的值,那么x就是函数 f ( x ) f(x) f(x)在附加条件 h ( x ) h(x) h(x)下极值点。
以上就是拉格朗日乘数法,通俗理解拉格朗日乘数法就是将含有等式条件约束优化问题转换成了无约束优化问题构造出拉格朗日函数 L ( x , λ ) L(x,\lambda) L(x,λ),让 L ( x , λ ) L(x,\lambda) L(x,λ)对未知数x和 λ \lambda λ进行求导,得到一组方程式,可以计算出对应的x和 λ \lambda λ结果,这个x对应的 f ( x ) f(x) f(x)函数值就是在条件 h ( x ) h(x) h(x)下的最小值点。
拉格朗日函数转换成等式过程的证明涉及到导数积分等数学知识,这里不再证明。
参考文章:https://blog.csdn.net/Soft_Po/article/details/118332454
假设我们面对的是不等式条件约束优化问题,如下:
假设 x = [ x 1 , x 2 , … , x n ] x=[x_1,x_2,\dots,x_n] x=[x1,x2,…,xn]是一个向量, f ( x ) f(x) f(x)和 h ( x ) h(x) h(x)含有x的函数,我们需要找到满足 h ( x ) ≤ 0 h(x)\le0 h(x)≤0条件下 f ( x ) f(x) f(x)的最小值,如下:
针对上式,显然是一个不等式约束最优化问题,不能再使用拉格朗日乘数法,因为拉格朗日乘数法是针对等式约束最优化问题。
但是我们可以考虑想办法将这种不等式问题转换成等式问题,从而使用拉格朗日乘数法。我们可以考虑加入一个“松弛变量” a 2 a^2 a2让条件 h ( x ) ≤ 0 h(x)\le0 h(x)≤0来达到等式的效果,即使条件变成 h ( x ) + a 2 = 0 h(x)+a^2=0 h(x)+a2=0,这里加上 a 2 a^2 a2的原因是保证加的一定是一个非负数,即: a 2 ≥ 0 a^2\ge0 a2≥0,但是目前不知道这个 a 2 a^2 a2是多少,一定会找到一个合适的 a 2 a^2 a2值使得 h ( x ) + a 2 = 0 h(x)+a^2=0 h(x)+a2=0成立,所以将①式改写成如下:
以上②式就变成了等式条件约束优化问题,我们就可以使用拉格朗日乘数法来求解满足等式条件下 f ( x ) f(x) f(x)最小值对应的x值。
通过拉格朗日乘数法,将②式转化为如下:
但是在上式中 λ \lambda λ值必须满足 λ ≥ 0 \lambda\ge0 λ≥0,由于 L ( x , λ , a ) L(x,\lambda,a) L(x,λ,a)变成了有条件的拉格朗日函数,这里需要要求 min L ( x , λ , a ) {\min}L(x,\lambda,a) minL(x,λ,a)对应下的x值。至于为什么 λ ≥ 0 \lambda\ge0 λ≥0及为什么计算的是 min L ( x , λ , a ) {\min}L(x,\lambda,a) minL(x,λ,a)下对应的x值,这里证明涉及到很多几何性质,这里也不在证明。
参考文章:https://blog.csdn.net/Soft_Po/article/details/118358564
所以将上式转换成如下拉格朗日函数:
以上我们可以看到将不等式条件约束优化问题加入“松弛变量”转换成等式条件约束优化问题,使用拉格朗日乘数法进行转换得到 L ( x , λ , a ) L(x,\lambda,a) L(x,λ,a),我们先抛开min,下面我们可以对拉格朗日函数 L ( X , λ , a ) L(X,\lambda,a) L(X,λ,a)对各个未知数求导,让对应的导数为零,得到以下联立方程:
从上式⑥式可知 λ a = 0 {\lambda}a=0 λa=0,我们分两种情况讨论:
1)
λ
=
0
,
a
≠
0
\lambda=0,a\not=0
λ=0,a=0
由于
λ
=
0
\lambda=0
λ=0,根据③式可知,约束不起作用,根据①式可知
h
(
x
)
≤
0
h(x)\le0
h(x)≤0。
2)
λ
≠
0
,
a
=
0
\lambda\not=0,a=0
λ=0,a=0
由于
λ
≠
0
\lambda\not=0
λ=0 ,根据③式可知
λ
>
0
\lambda\gt0
λ>0 。由于
a
=
0
a=0
a=0,约束条件起作用,根据⑤式可知,
h
(
x
)
=
0
h(x)=0
h(x)=0
综上两个步骤我们可以得到 λ ⋅ h ( x ) = 0 \lambda{\cdot}h(x)=0 λ⋅h(x)=0 ,且在约束条件起作用时, λ > 0 , h ( x ) = 0 \lambda>0,h(x)=0 λ>0,h(x)=0 ;约束条件不起作用时, λ = 0 , h ( x ) < 0 \lambda=0,h(x)\lt0 λ=0,h(x)<0。
上面方程组中的⑥式可以改写成 λ ⋅ h ( x ) = 0 \lambda{\cdot}h(x)=0 λ⋅h(x)=0 。由于 a 2 > 0 a^2>0 a2>0,所以将⑤式也可以改写成 h ( x ) ≤ 0 h(x)\le0 h(x)≤0,所以上面方程组也可以转换成如下:
以上便是不等式约束优化问题的KKT(Karush-Kuhn-Tucker)条件,我们回到最开始要处理的问题上,根据③式可知,我们需要找到合适的
x
,
λ
,
a
x,\lambda,a
x,λ,a 值使
L
(
x
,
λ
,
a
)
L(x,\lambda,a)
L(x,λ,a)最小但是合适的
x
,
λ
,
a
x,\lambda,a
x,λ,a 必须满足KKT条件。
我们对③式的优化问题可以进行优化如下:
由于 a 2 a^2 a2且 λ ≥ 0 \lambda\ge0 λ≥0, λ a 2 \lambda{a^2} λa2一定大于零,所以进一步可以简化为如下:
满足最小化⑧式对应的 x , λ x,\lambda x,λ 值一定也要满足KKT条件,假设现在我们找到了合适的参数x值使 f ( x ) f(x) f(x)取得最小值P【注意:这里根据①式来说,计算 f ( x ) f(x) f(x)的最小值,这里假设合适参数x值对应 f ( x ) f(x) f(x)的的值P就是最小值,不存在比这更小的值。】,由于⑧式中一定小于等于零,所以一定有:
也就是说一定有:
为了找到最优的 λ \lambda λ 值,我们一定想要 L ( x , λ ) L(x,\lambda) L(x,λ) 接近P,即找到合适的 λ \lambda λ最大化,可以写成 max λ L ( x , λ ) \max\limits_{\lambda}L(x,\lambda) λmaxL(x,λ),所以⑧式求解合适的 x , λ x,\lambda x,λ值最终可以转换成如下:
对偶问题是我们定义的一种问题,对于一个不等式约束的原问题:
我们定义对偶问题为(对上面方程的求解等效求解下面方程):
其实就是把min和max对调了一下,当然对应的变量也要变换。
对偶问题有什么好处呢?对于原问题,我们要先求里面的max,再求外面的min。而对于对偶问题,我们可以先求里面的min。有时候,先确定里面关于x的函数最小值,比原问题先求解关于 λ \lambda λ的最大值,要更加容易解。
但是原问题跟对偶问题并不是等价的,这里有一个强对偶性、弱对偶性的概念,弱对偶性是对于所有的对偶问题都有的一个性质。
这里给出一个弱对偶性的推导过程:
其中, x ∗ , λ ∗ x^*,\lambda^* x∗,λ∗是函数取最大值最小值的时候对应的最优解,也就是说,原问题始终大于等于对偶问题:
如果两个问题是强对偶的,那么这两个问题其实是等价的问题:
所有的下凸函数都满足强对偶性,也就是说所有下凸函数都满足上式。
【备注】:对弱对偶性推导的理解如下图所示:

通过2.小节我们知道SVM目标函数如下:
根据拉格朗日乘数法、KKT条件、对偶问题我们可以按照如下步骤来计算SVM目标函数最优的一组w值。
将SVM目标函数转换为如下:
根据3.2中的⑨式构建拉格朗日函数如下:
以上不等式转换成拉格朗日函数必须满足KKT条件,详见3.2 KKT条件,这里满足的KKT条件如下:
由于原始目标函数 1 2 ∣ ∣ w ∣ ∣ 2 \frac{1}{2}||w||^2 21∣∣w∣∣2是个下凸函数,根据3.3中对偶问题可知 L ( w , b , λ ) L(w,b,\lambda) L(w,b,λ)一定是强对偶问题,所以可以将a式改写成如下:
针对b式,我们假设参数 λ \lambda λ固定,使 L ( w , b , λ ) L(w,b,\lambda) L(w,b,λ)对参数w和b进行求导得到如下:
进一步可以得到:
按照解方程组的思想,我们现在将以上计算得到的结果代入到b式中得到:
即:
我们可以发现以上公式经过转换只含有 λ \lambda λ的方程求极值问题,但是 λ \lambda λ含有 λ i , λ j , ⋯ \lambda_i,\lambda_j,\cdots λi,λj,⋯这些未知数(注意不是2个),那么我们要求的一组w如何得到呢?只要针对以上公式得到 λ \lambda λ值后,我们可以根据c式进一步求解到对应的一组w值。针对上式求极值问题,我们常用 SMO(Sequential Minimal Optimization) 算法求解 λ i , λ j , ⋯ \lambda_i,\lambda_j,\cdots λi,λj,⋯
注意:d式中 ( x i ⋅ x j ) (x_i\cdot{x_j}) (xi⋅xj)代表两个向量的点积,也叫内积,例如: x i = ( x i 1 , x i 2 ) , x j = ( x j 1 , x j 2 ) x_i=(x_{i1},x_{i_2}),x_j=(x_{j1},x_{j2}) xi=(xi1,xi2),xj=(xj1,xj2)那么两个向量点积结果为 x i 1 ⋅ x j 1 + x i 2 ⋅ x j 2 x_{i1}\cdot{x_{j1}}+x_{i2}\cdot{x_{j2}} xi1⋅xj1+xi2⋅xj2。
SMO(Sequential Minimal Optimization),序列最小优化算法,其核心思想非常简单:**每次只优化一个参数,其他参数先固定住,仅求当前这个优化参数的极值。**下面我们只说SVM中如何利用SMO算法进行求解最终结果的,这里不再进行公式推导。
我们根据d式可以看到有 λ i 、 λ j , i = 1 , 2 , … , n \lambda_i、\lambda_j,i=1,2,\dots,n λi、λj,i=1,2,…,n很多参数,由于优化目标中含有约束条件: ∑ i = 1 n λ i y i = 0 \sum\limits_{i=1}^n\lambda_iy_i=0 i=1∑nλiyi=0,此约束条件中 i = 1 , 2 , 3 , … , n , y i i=1,2,3,\dots,n,y_i i=1,2,3,…,n,yi代表每个样本所属类别-1或者1。
根据SMO算法假设将KaTeX parse error: Undefined control sequence: \lambnda at position 11: \lambda_3,\̲l̲a̲m̲b̲n̲d̲a̲_4,\dots,\lambd…参数固定,那么 λ 1 , λ 2 \lambda_1,\lambda_2 λ1,λ2之间的关系也确定了,可以将约束条件: ∑ i = 1 n λ i y i = 0 \sum\limits_{i=1}^n\lambda_iy_i=0 i=1∑nλiyi=0改写成
我们可以将上式中c看成是 λ 3 , λ 4 , … , λ n \lambda_3,\lambda_4,\dots,\lambda_n λ3,λ4,…,λn乘以对应的类别y得到的常数,根据e式我们发现 λ 1 , λ 2 \lambda_1,\lambda_2 λ1,λ2之间有等式关系,即: λ 2 = − c − λ 1 y 1 y 2 \lambda_2=\frac{-c-\lambda_1y_1}{y_2} λ2=y2−c−λ1y1,也就是说我们可以使用 λ 1 \lambda_1 λ1的表达式代替 λ 2 \lambda_2 λ2,这样我们就可以将d式看成只含有 λ 1 ≥ 0 \lambda_1\ge0 λ1≥0这一个条件下最优化问题,并且我们可以将 λ 2 = − c − λ 1 y 1 y 2 \lambda_2=\frac{-c-\lambda_1y_1}{y_2} λ2=y2−c−λ1y1代入到d式,d式中只含有 λ 1 \lambda_1 λ1一个未知数求极值问题,可以对函数进行求导,令导数为零,得到 λ 1 \lambda_1 λ1的值,然后根据 λ 1 \lambda_1 λ1的值计算出 λ 2 \lambda_2 λ2的值。通过以上固定参数方式多次迭代计算得到一组 λ \lambda λ值。
根据4.2中的c式,如下:
我们可以知道获取了一组 λ \lambda λ的值,我们可以得到一组w对应的值。根据4.1中的KKT条件:
根据f式中式可知,当 λ ≥ 0 \lambda\ge0 λ≥0时,一定有 1 − y i ⋅ ( w T ⋅ x i + b ) = 0 1-y_i\cdot(w^T\cdot{x_i}+b)=0 1−yi⋅(wT⋅xi+b)=0,对于这样的样本就属于支持向量点,就在分类边界上,我们将对应的w代入到下式中
一定可以计算出b的值。我们将g式两边乘以 y i y_i yi,得到
由于 y i 2 = 1 y_i^2=1 yi2=1,所以得到最终b的结果如下:
假设我们有S个支持向量,以上b的计算可以使用任意一个支持向量代入计算即可,如果数据严格是线性可分的,这些b结果是一致的。对于数据不是严格线性可分的情况,参照后面的软间隔问题,一般我们可以采用一种更健壮的方式,将所有支持向量对应的b都求出,然后将其平均值作为最后的结果,最终b的结果如下:
S代表支持向量点的集合,也就是在边界上点的集合。
综上所述,我们可以的到最终的w和b的值如下:
确定w和b之后,我们就能构造出最大分割超平面: w T ⋅ x + b = 0 w^T\cdot{x}+b=0 wT⋅x+b=0,新来样本对应的特征代入后得到的结果如果是大于0那么属于一类,小于0属于另一类。
以上讨论问题都是基于样本点完全的线性可分,我们称为硬间隔如下图:
如果存在部分样本点不能完全线性可分,大部分样本点线性可分的情况,如下图所示:
那么我们就需要用到软间隔,相比于硬间隔的苛刻条件,我们允许个别样本点出现在间隔带里面,比如:

即我们允许部分样本点不满足约束条件:
为了度量这个间隔软到何种程度,我们为每个样本引入一个“松弛变量” ξ i , ξ i ≥ 0 \xi_i,\xi_i\ge0 ξi,ξi≥0(中文:克西)加入松弛变量后,我们的约束条件变成 y ⋅ ( w T ⋅ x i + b ) ≥ 1 − ξ i y\cdot(w^T\cdot{x_i}+b)\ge1-\xi_i y⋅(wT⋅xi+b)≥1−ξi,这样不等式就不会那么严格,数据点在不同的约束条件下的情况如下:
加入软间隔后我们的目标函数变成了:
其中C是一个大于0的常数,这里在原有的目标函数中加入 C ∑ i = 1 n ξ i C\sum\limits_{i=1}^n\xi_i Ci=1∑nξi 可以理解为错误样本的惩罚程度,我们希望在对应条件下 min 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 n ξ i \min\frac{1}{2}||w||^2+C\sum\limits_{i=1}^n\xi_i min21∣∣w∣∣2+Ci=1∑nξi 变小,对应的也是希望 C ∑ i = 1 n ξ i C\sum\limits_{i=1}^n\xi_i Ci=1∑nξi 变小,当C为无穷大, ξ i \xi_i ξi 必然无穷小,这样的话SVM就变成一个完全线性可分的SVM。如果C为有对应的值时, ξ i \xi_i ξi 对应的会有一个大于0的值,这样的SVM就是允许部分样本不遵守约束条件。
接下来我们对新的目标函数h式求解最优化问题,步骤与1.4 SVM“硬间隔”完全线性可分步骤完全一样。
1)构造拉格朗日函数
将h式目标函数改写成如下:
构造拉格朗日函数如下:
上式中 λ i , μ i \lambda_i,\mu_i λi,μi是拉格朗日乘子, w , b , ξ w,b,\xi w,b,ξ是我们要计算的主问题参数。
2)对偶关系转化
目标函数是个下凸函数,对应的拉格朗日函数复合强对偶性,所以可以根据强对偶向,将对偶问题转换为:
即
使用j式对 w , b , ξ w,b,\xi w,b,ξ求导,并令导数为零,得到如下关系:
整理之后得到:
将以上关系代入到j式:
我们发现上式中求 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,所以在约束条件中一定有此条件,所以我们得到最终的目标函数可以写成如下:
推导到以上之后,我们发现结果和硬间隔结果一样,参照4.3 d式,只是结果中多了约束条件 C = λ i + μ i C=\lambda_i+\mu_i C=λi+μi
3)求解结果
同样我们也可以利用SMO算法对式L求解得到一组合适的 λ \lambda λ值和 μ \mu μ值,由于综上所述,我们可以的到最终的w和b的值如下:
这里得到的w和b虽然和硬分割结果一样,但是这是加入松弛变量之后得到的w和b的值,根据L式的条件 C = λ i + μ i C=\lambda_i+\mu_i C=λi+μi和 λ i ≥ 0 , μ i ≥ 0 \lambda_i\ge0,\mu_i\ge0 λ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属于另一类。
from sklearn import svm import numpy as np def read_data(path): with open(path) as f : lines=f.readlines() lines=[eval(line.strip()) for line in lines] X,y=zip(*lines) X=np.array(X) y=np.array(y) return X,y if __name__ == '__main__': X_train,y_train=read_data("./data/train_data") X_test,y_test=read_data("./data/test_data") #C对样本错误的容忍,这里就是SVM中加入松弛变量对应的C, model= svm.SVC(C=1.0) model.fit(X_train,y_train.ravel()) #打印支持向量 print(model.support_vectors_) #打印支持向量下标 print(model.support_) #使用SVM应用到测试集,返回正确率 score = model.score(X_test,y_test) print(score)
网格搜索就是手动给定模型中想要改动的所有参数,程序自动使用穷举法来将所有的参数或者参数组合都运行一遍,将对应得到的模型做K折交叉验证,将得分最高的参数或参数组合当做最佳结果,并得到模型。也就是说网格搜索用来获取最合适的一组参数,不需要我们手动一个个尝试。使用网格搜索由于针对每个参数下的模型需要做K折交叉验证最终导致加大了模型训练时间,所以一般我们可以在小的训练集中使用网格搜索找到对应合适的参数值,再将合适的参数使用到大量数据集中训练模型。例如:逻辑回归中使用正则项时,我们可以先用一小部分训练集确定合适的惩罚系数,然后将惩罚系数应用到大量训练集中训练模型。
from sklearn import svm import numpy as np from sklearn.model_selection import GridSearchCV def read_data(path): with open(path) as f : lines=f.readlines() lines=[eval(line.strip()) for line in lines] X,y=zip(*lines) X=np.array(X) y=np.array(y) return X,y if __name__ == '__main__': X_train,y_train=read_data("./data/train_data") X_test,y_test=read_data("./data/test_data") #np.logspace(0,5,6) 创建等比数列,logspace(开始值,结束值,数据个数) #np.logspace(0,5,6)得到的就是10^0,10^1,10^2,10^3,10^4,10^5 search_space = {'C': np.logspace(-3, 3, 7)} print(search_space['C']) model= svm.SVC() #网格搜索 ,cv的值就是指定K折交叉验证中的k gridsearch = GridSearchCV(model, param_grid=search_space,cv=5) gridsearch.fit(X_train,y_train.ravel()) #交叉验证中测试的最好的结果 cv_performance = gridsearch.best_score_ print("交叉验证最好结果:",cv_performance) test_performance = gridsearch.score(X_test, y_test) #交叉验证中测试的最好的参数 print("C",gridsearch.best_params_['C'])
软间隔情况下,SVM的目标函数如下:
其实这里我们说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 ⋅ x i + b ) − ξ i ≤ 0 , ξ i ≥ 0 1-y\cdot(w^T\cdot{x_i}+b)-\xi_i\le0,\xi_i\ge0 1−y⋅(wT⋅xi+b)−ξi≤0,ξi≥0我们可以改写成如下:
根据下图结合以上两个条件我们可以继续改写成如下:
上式等价于:
以上公式就是SVM的损失函数,称为“Hinge Loss”,也被叫做“合页损失函数”。其图像如下:
特点是当 y ⋅ ( w T ⋅ x + i + b ) ≥ 1 y\cdot(w^T\cdot{x+i}+b)\ge1 y⋅(wT⋅x+i+b)≥1时损失为0。
我们可以将m式代入到h式得到新的目标函数,暂时先不关注约束条件,新的目标函数如下:
针对新的目标函数我们同样也是最小化整体目标函数。我们发现以上目标函数与逻辑回归L2正则化的损失函数在形式上非常类似,将上式可以改写成如下:
逻辑回归L2正则化损失函数如下:
也可以改写成如下:
如果将逻辑损失函数图像与“Hinge Loss”图像放在一起图像如下:
通过上图我们可以看出,在训练逻辑回归时,损失永远不会为0,因此即使分类正确,逻辑回归仍然会不停的训练,以求得更小的损失和更大的概率,但是极有可能出现过拟合,这就是为什么我们需要在梯度下降中提前终止的原因。但是在SVM中,如果分类正确可以直接达到 ∑ i = 1 n ξ i = 0 \sum\limits_{i=1}^n\xi_i=0 i=1∑nξi=0,不再进行对分类无益的训练,即学习到一定程度就不再学习。
在前面SVM讨论的硬间隔和软间隔都是指的样本完全可分或者大部分样本点线性可分的情况。那么如果样本完全线性不可分如下图所示:
我们可以使用升维方式来解决这种线性不可分的问题,例如目前只有两个维度 x 1 , x 2 x_1,x_2 x1,x2,我们可以基于已有的维度进行升维得到更多维度,例如: x 1 x 2 、 x 1 x 2 , x 2 x 2 x_1x_2、x_1x_2,x_2x_2 x1x2、x1x2,x2x2,这样我们可以将以上问题可以转换成高维可分问题,如下图:
SVM中线性不可分问题就是非线性SVM问题,对这种问题我们可以将样本映射到高维空间,再通过间隔最大化的方式学习得到支持向量机。
假设原有特征有如下三个 x 1 、 x 2 、 x 3 x_1、x_2、x_3 x1、x2、x3,那么基于三个已有特征进行两两组合(二阶交叉)我们可以得到如下更多特征:
我们在训练模型时将以上组合特征可以参与到模型的训练中,其代价是运算量过大,比如原始特征有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和n的内积如下:
对结果进行平方得到:
【备注】: ( a + b + c ) 2 = a 2 + b 2 + c 2 + 2 a b + 2 a c + a b c (a+b+c)^2=a^2+b^2+c^2+2ab+2ac+abc (a+b+c)2=a2+b2+c2+2ab+2ac+abc
我们发现o式和p式结果一样,也就是

以上在m和n向量中只有3个元素时推导成立,那么在m和n中如果有多个元素时也一样成立。
我们发现,如果最终目标只是计算向量升维后的内积
ϕ
m
⋅
ϕ
n
\phi{m}\cdot\phi{n}
ϕm⋅ϕn,根据q式可知,我们可以先计算原始向量的内积KaTeX parse error: Undefined control sequence: \codt at position 2: m\̲c̲o̲d̲t̲{n},再进行平方运算,而不需要真正的进行高运算量的升维操作。这种通过两个低维向量进行数学运算得到它们投影至高维空间时向量的内积方法叫做核方法,相应的算法叫做核函数,上面案例核函数记为:
以上核函数叫做多项式核函数,常用的核函数有如下几种,不同的核函数的区别是将向量映射到高维空间时采用的升维方法不同,不过高维向量都是不需要计算出来的。
线性核函数: 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 ) = ( a ( x i T ⋅ x j ) + c ) d a , c , d 都 是 参 数 K(x_i\cdot{x_j})=(a(x_i^T\cdot{x_j})+c)^d\quad a,c,d都是参数 K(xi⋅xj)=(a(xiT⋅xj)+c)da,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}}\quad \delta是参数 K(xi⋅xj)=e−2δ2∣∣xi−xj∣∣2δ是参数
这样我们可以通过核函数将数据映射到高维空间,但是核函数是在低维上进行计算,而将实质上的分类效果表现在了高维空间上,来解决在原始空间中线性不可分的问题。
在SVM中我们可以使用常用的核函数:线性核函数、多项式核函数、高斯核函数来进行升维解决线性不可分问题,应用最广泛的就是高斯核函数,无论是小样本还是大样本、高维或者低维,高斯核函数均适用,它相比于线性核函数来说,线性核函数只是高斯核函数的一个特例,线性核函数适用于数据本身线性可分,通过线性核函数来达到更理想情况。高斯核函数相比于多项式核函数,多项式核函数阶数比较高时,内部计算时会导致一些元素值无穷大或者无穷小,而在高斯核函数会减少数值的计算困难。
综上,我们在非线性SVM中使用核函数时,先使用线性核函数,如果不行尝试换不同的特征,如果还不行那么可以直接使用高斯核函数。
非线性SVM使用核函数代码如下:
from sklearn import svm from sklearn import datasets from sklearn.model_selection import train_test_split as ts ''' ‘rbf’:高斯核函数 ‘linear’:线性核函数 ‘poly’:多项式核函数 ''' if __name__ == '__main__': #import our data iris = datasets.load_iris() X = iris.data y = iris.target #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)
根据一些样本点,我们可以通过拉格朗日乘数法、KKT条件、对偶问题、SMO算法计算出支持向量机SVM的分类线 w T ⋅ x + b = 0 w^T\cdot{x}+b=0 wT⋅x+b=0,其中
S代表的是边界上的样本点。得到的分割下如下图所示:
我们可以看出SVM在训练过程中找到的是两类点的分割线,计算样本中有少量异常点,在训练模型时依然能很正确的找到中间分割线,因为训练SVM时考虑了全量数据,确定这条线的b时只与支持向量点(边界上的点)有关。同样在测试集中就算有一些样本点是异常点也不会影响其正常分类,SVM具有抗干扰能力强的特点。
此外,由于训练SVM需要所有样本点参与模型训练,不然不能缺点这条线,所以当数据量大时,SVM训练占用内存非常大。这时SVM模型的缺点。
SVM同样支持多分类,我们可以将一个多分类问题拆分成多个二分类问题,例如有A,B,C三类,我们使用SVM训练时可以训练3个模型,第一个模型针对是A类和不是A类进行训练。第二个模型针对是B类和不是B类进行训练。第三个模型针对是C类和不是C类进行训练。这样可以解决多分类问题。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。