支持向量机|机器学习方法(李航)

支持向量机,可以看着是升级版的感知机,与感知机相比。他们都是找到一个超平面对数据集进行分割,区别在于,感知机模型得到的超平面空间中可以有无穷个超平面,但支持向量机仅含有一个,这一个超平面与样本点的间隔是最大化的。

支持向量机学习方法包含三种模型:

  • 线性可分支持向量机,要求训练集线性可分,通过硬间隔最大化得到超平面。
  • 线性支持向量机,要求训练集近似线性可分,通过软间隔最大化获得超平面
  • 非线性支持向量机,训练集线性不可分,可通过使用核函数将线性不可分的训练集转换为线性可分的数据集,并通过软间隔最大化获得超平面。

线性可分支持向量机

对于线性可分的数据集,学习的目标是在特征空间中找到一个分离超平面,能将实例分到不同的类。分离超平面将特征空间划分为两部分,一部分是正类,一部分是负类。分离超平面的法向量指向的一侧为正类,另一侧为负类。

并且要求这个分离超平面距离最近的两个点的距离之和最大,这个分离超平面被称为间隔最大分离超平面。

线性可分支持向量机的数学模型为:
f ( x ) = s i g n ( w ∗ ∗ x + b ∗ ) f(x)=sign(w^**x+b^*) f(x)=sign(wx+b)

其中 w ∗ ∗ x + b ∗ = 0 w^**x+b^* = 0 wx+b=0就是间隔最大分离超平面。

我们所需要求得的模型就是这个间隔最大的分离超平面。

函数间隔和几何间隔

函数间隔

一般来说,一个点距离分离超平面的远近可以表示分类预测的确信程度。在超平面 w ∗ x + b = 0 w*x+b=0 wx+b=0确定的情况下, ∣ w ∗ x + b ∣ |w*x+b| wx+b能够相对地表示点x距离超平面的远近。而 w ∗ x + b w*x+b wx+b的符号与类标记 y y y的符号是否一致能够表示分类是否正确。因为在二分类问题中, y y y要么为1,要么为-1,所以可用 y ( w ∗ x + b ) y(w*x+b) y(wx+b)来表示分类的正确性及确信度,这就是函数间隔的概念。

定义超平面关于样本点 ( x i , y i ) (x_i,y_i) (xi,yi)的函数间隔为:
γ ^ i = y i ( w ⋅ x i + b ) \hat{\gamma}_i=y_i(w \cdot x_i+b) γ^i=yi(wxi+b)
定义超平面 ( w , b ) (w,b) (w,b)关于训练数据集 T T T的函数间隔为超平面 ( w , b ) (w,b) (w,b)关于 T T T中所有样本点 ( x i , y i ) (x_i,y_i) (xi,yi)的函数间隔的最小值:
γ ^ = min ⁡ i = 1 , . . . , N γ ^ i \hat{\gamma} = \min_{i=1,...,N}\hat{\gamma}_i γ^=i=1,...,Nminγ^i
但是选择分离超平面时,只有函数间隔还不够。因为只要成比例改变 w w w b b b超平面并没有改变,函数间隔却改变了。

几何间隔

因为函数间隔无法确定 w w w b b b,所以可以对 w w w施加约束,如规范化 ∣ ∣ w ∣ ∣ = 1 ||w||=1 ∣∣w∣∣=1,这样函数间隔就成为几何间隔。

定义超平面关于样本点 ( x i , y i ) (x_i,y_i) (xi,yi)的几何间隔为:
γ i = y i ( w ∣ ∣ w ∣ ∣ ⋅ x i + b ∣ ∣ w ∣ ∣ ) \gamma_i=\quad y_i\left( \frac{w}{||w||} \cdot x_i+\frac{b}{||w||} \right) γi=yi(∣∣w∣∣wxi+∣∣w∣∣b)

定义超平面(w,b)关于训练数据集T的几何间隔为超平面(w,b)关于T中所有样本点(xi,yi)的几何间隔的最小值:
γ = min ⁡ i = 1 , . . . , N γ i \gamma=\min_{i=1,...,N}\gamma_i γ=i=1,...,Nminγi

几何间隔与函数间隔的关系:
γ = γ ^ ∣ ∣ w ∣ ∣ \gamma=\frac{\hat{\gamma}}{||w||} γ=∣∣w∣∣γ^

最大间隔法

求一个最大间隔分离超平面,可以用约束最优化问题的形式来表示:
max ⁡ w , b γ s . t . y i ( w ∣ ∣ w ∣ ∣ ⋅ x i + b ∣ ∣ w ∣ ∣ ) ≥ γ , i = 1 , 2 , . . . , N \begin{aligned} & \max_{w,b}\gamma \\ &s.t. \quad y_i\left( \frac{w}{||w||} \cdot x_i+\frac{b}{||w||} \right)\geq \gamma,\quad i=1,2,...,N \end{aligned} w,bmaxγs.t.yi(∣∣w∣∣wxi+∣∣w∣∣b)γ,i=1,2,...,N
我们可以通过几何间隔和函数间隔的关系代入上面的公式:
max ⁡ w , b γ ^ ∣ ∣ w ∣ ∣ s . t . y i ( w ⋅ x i + b ) ≥ γ ^ , i = 1 , 2 , . . . , N \begin{aligned} & \max_{w,b}\frac{\hat{\gamma}}{||w||} \\ &s.t.\quad y_i\left( w \cdot x_i+b \right)\geq \hat{\gamma},\quad i=1,2,...,N \end{aligned} w,bmax∣∣w∣∣γ^s.t.yi(wxi+b)γ^,i=1,2,...,N
因为函数间隔对w和b按比例改变,函数间隔也按此比例改变的特性,w和b的改变并不会影响上式中的目标函数的优化和约束条件,因此,我们可以对函数间隔随意取值,为了方便,我们取 γ ^ = 1 \hat{\gamma}=1 γ^=1

另外,我们可以将最大化问题转换为最小化问题,即将 max ⁡ 1 ∣ ∣ w ∣ ∣ \max \frac{1}{||w||} max∣∣w∣∣1转换为 min ⁡ ∣ ∣ w ∣ ∣ \min ||w|| min∣∣w∣∣,这样得到的问题为:
min ⁡ w , b ∣ ∣ w ∣ ∣ s . t . y i ( w ⋅ x i + b ) − 1 ≥ 0 , i = 1 , 2 , . . . , N \begin{aligned} & \min_{w,b}||w|| \\ &s.t.\quad y_i\left( w \cdot x_i+b \right)-1\geq 0,\quad i=1,2,...,N \end{aligned} w,bmin∣∣w∣∣s.t.yi(wxi+b)10,i=1,2,...,N
可以使用拉格朗日乘数法求解。

同时为了之后的计算方便,我们可以将问题转变为:
min ⁡ w , b 1 2 ∣ ∣ w ∣ ∣ 2 s . t . y i ( w ⋅ x i + b ) − 1 ≥ 0 , i = 1 , 2 , . . . , N \begin{aligned} & \min_{w,b}\frac12||w||^2 \\ &s.t.\quad y_i\left( w \cdot x_i+b \right)-1\geq 0,\quad i=1,2,...,N \end{aligned} w,bmin21∣∣w2s.t.yi(wxi+b)10,i=1,2,...,N
因为 ∣ ∣ w ∣ ∣ ≥ 0 ||w||\geq 0 ∣∣w∣∣0,因此平方后再乘以一个系数不会对最小化问题产生影响。

上述的问题是一个凸二次规划问题。

现在,我们只需解答上述问题,得到最优特征向量 w ∗ w^* w和最优偏置 b ∗ b^* b,就可以得到最大间隔分离超平面和决策函数。问题在于如何求解该问题。

对偶算法

可以参考最大熵模型使用过拉格朗日乘数法和对偶法解决约束条件下的最优化问题。

这里和最大熵模型使用的拉格朗日乘子法的不同在于,最大熵模型中的约束条件是等式约束条件,而这里是不等式约束条件,对于这样的情况,可以应用KKT条件去求得最优值。

构建拉格朗日函数:
L ( w , b , a ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 N a i ( y i ( w ⋅ x i + b ) − 1 ) = 1 2 ∣ ∣ w ∣ ∣ 2 − ∑ i = 1 N a i y i ( w ⋅ x i + b ) + ∑ i = 1 N a i L(w,b,a)=\frac12||w||^2-\sum_{i=1}^Na_i(y_i(w \cdot x_i+b)-1)=\frac12||w||^2-\sum_{i=1}^Na_i y_i(w \cdot x_i+b)+\sum_{i=1}^Na_i L(w,b,a)=21∣∣w2i=1Nai(yi(wxi+b)1)=21∣∣w2i=1Naiyi(wxi+b)+i=1Nai
其中 α = ( α 1 , α 2 , … , α N ) α=(α_1,α_2,…,α_N) α=(α1,α2,,αN)为拉格朗日乘子向量。

原始问题为:
min ⁡ w , b max ⁡ a L ( w , b , a ) \min_{w,b}\max_{a}L(w,b,a) w,bminamaxL(w,b,a)
其对偶问题为:
max ⁡ a min ⁡ w , b L ( w , b , a ) \max_a\min_{w,b}L(w,b,a) amaxw,bminL(w,b,a)
现在求对偶问题的内部最小化。

我们对w和b分别求偏导,并令偏导数等于0。
∇ w L ( w , b , a ) = w − ∑ i = 1 N a i y i x i = 0 ∇ b L ( w , b , a ) = − ∑ i = 1 N a i y i = 0 \nabla_wL(w,b,a)=w-\sum_{i=1}^Na_iy_ix_i=0 \\ \nabla_b L(w,b,a)=-\sum_{i=1}^Na_iy_i=0 wL(w,b,a)=wi=1Naiyixi=0bL(w,b,a)=i=1Naiyi=0
得到:
w = ∑ i = 1 N a i y i x i ∑ i = 1 N a i y i = 0 w=\sum_{i=1}^Na_iy_ix_i \\ \sum_{i=1}^Na_iy_i=0 w=i=1Naiyixii=1Naiyi=0
将上面的结论代入到拉格朗日函数之中:
min ⁡ w , b L ( w , b , a ) = 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) − ∑ i = 1 N a i y i ( ( ∑ j = 1 N a j y j x j ) ⋅ x i + b ) + ∑ i = 1 N a i = 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) − ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) − ∑ i = 1 N a i y i b + ∑ i = 1 N a i = − 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) + ∑ i = 1 N a i \begin{align*} \min_{w,b}L(w,b,a)&=\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)-\sum_{i=1}^Na_iy_i\left(\left(\sum_{j=1}^Na_jy_jx_j\right) \cdot x_i+b \right)+\sum_{i=1}^Na_i \\ &=\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)-\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)-\sum_{i=1}^Na_iy_ib+\sum_{i=1}^Na_i \\ &=-\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)+\sum_{i=1}^Na_i \end{align*} w,bminL(w,b,a)=21i=1Nj=1Naiajyiyj(xixj)i=1Naiyi((j=1Najyjxj)xi+b)+i=1Nai=21i=1Nj=1Naiajyiyj(xixj)i=1Nj=1Naiajyiyj(xixj)i=1Naiyib+i=1Nai=21i=1Nj=1Naiajyiyj(xixj)+i=1Nai
接下来求对偶问题中的外部极大化问题:

我们可以通过在右侧乘以一个-1,将最大化问题转换为求最小化的问题:
min ⁡ a 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) − ∑ i = 1 N a i s . t . ∑ i = 1 N a i y i = 0 a i ≥ 0 , i = 1 , 2 , . . . , N \begin{aligned} & \min_a\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)-\sum_{i=1}^Na_i \\ &s.t.\quad \sum_{i=1}^Na_iy_i=0 \\ & a_i \geq 0,i=1,2,...,N \end{aligned} amin21i=1Nj=1Naiajyiyj(xixj)i=1Nais.t.i=1Naiyi=0ai0,i=1,2,...,N
通过约束条件我们可以得到α的各个分量之间的关系,代入原式后,对 α i α_i αi求偏导,并使偏导数为0,求得α向量。

利用KKT求最优w和b

线性可分支持向量机中的原问题和对偶问题互相之间是强对偶关系,而KKT是强对偶关系的充要条件。

因为原始问题和对偶问题是强对偶关系,所以一定满足KKT条件:
∇ w L ( w ∗ , b ∗ , a ∗ ) = w ∗ − ∑ i = 1 N a i ∗ y i x i = 0 (1) \nabla_wL(w^*,b^*,a^*)=w^*-\sum_{i=1}^Na_i^*y_ix_i=0 \tag{1} wL(w,b,a)=wi=1Naiyixi=0(1)

∇ b L ( w ∗ , b ∗ , a ∗ ) = − ∑ i = 1 N a i ∗ y i = 0 (2) \nabla_b L(w^*,b^*,a^*)=-\sum_{i=1}^Na_i^*y_i=0 \tag{2} bL(w,b,a)=i=1Naiyi=0(2)

a i ∗ ( y − i ( x i + b ∗ ) − 1 ) = 0 , i = 1 , 2 , . . . , N (3) a_i^*(y-i(x_i+b^*)-1)=0,i=1,2,...,N \tag{3} ai(yi(xi+b)1)=0,i=1,2,...,N(3)

y i ( w ∗ ⋅ x i + b ∗ ) − 1 ≥ 0 , i = 1 , 2 , . . . N (4) y_i(w^* \cdot x_i + b^*)-1 \geq0,i=1,2,...N \tag{4} yi(wxi+b)10,i=1,2,...N(4)

a i ∗ ≥ 0 , i = 1 , 2 , . . . N (5) a_i^* \geq 0,i=1,2,...N \tag{5} ai0,i=1,2,...N(5)

在上面的五个KKT条件中,上标星号表示为最优解。等式(1)和等式(2)是我们之前在内部极小化拉格朗日函数的时候求得的,剩下的三个式子是KKT条件需要满足的。

那么根据等式(1),我们可以很容易的得到:
w ∗ = ∑ i a i ∗ y i x i w^*=\sum_{i}a_i^*y_ix_i w=iaiyixi
主要来看b,主要关注于式(3),(4)和(5)。

a i ∗ ≥ 0 a_i^* \geq 0 ai0时, y i ( w ∗ ⋅ x i + b ∗ ) − 1 = 0 y_i(w^* \cdot x_i + b^*)-1 = 0 yi(wxi+b)1=0,此时 $|w^* \cdot x_i + b^*|=1 $。

而函数距离就是通过 ∣ w ⋅ x + b ∣ |w·x+b| wx+b来得到。

也就是说当 a i ∗ ≥ 0 a_i^* \geq 0 ai0时,我们找到了距离超平面的函数距离最小的样本点,这样的样本点我们称之为支持向量。

而当 a i ∗ = 0 a_i^* = 0 ai=0时, y i ( w ∗ ⋅ x i + b ∗ ) − 1 y_i(w^* \cdot x_i + b^*)-1 yi(wxi+b)1 可以是大于等于0,即这些样本点与超平面的函数距离大于支持向量,同时因为 a i ∗ = 0 a_i^* = 0 ai=0 ,说明这些样本点在我们的模型中并未被考虑进去,也就是说它们对最大距离分离超平面的确定没有关系。

于是,存在一个样本点 ( x i , y i ) (x_i,y_i) (xi,yi)使 a i ∗ ≥ 0 a_i^* \geq 0 ai0 ,根据 y i ( w ∗ ⋅ x i + b ∗ ) − 1 = 0 y_i(w^* \cdot x_i + b^*)-1=0 yi(wxi+b)1=0 ,可以得到:
y i 2 ( w ∗ ⋅ x i + b ∗ ) = y i → b ∗ = y i − w ∗ ⋅ x i → b ∗ = y i − ∑ i a i ∗ y i x i ⋅ x j y_i^2(w^* \cdot x_i + b^*)=y_i\rightarrow b^*=y_i-w^* \cdot x_i \rightarrow b^*=y_i-\sum_ia_i^*y_ix_i \cdot x_j yi2(wxi+b)=yib=yiwxib=yiiaiyixixj

现在我们得到了最优 w ∗ w^* w b ∗ b^* b,同时 α i ∗ α_i^* αi也在上一节通过求偏导得到,于是也就得到了最大距离分离超平面和决策函数:
∑ i = i N a i ∗ y i ( x ⋅ x i ) + b ∗ = 0 f ( x ) = s i g n ( ∑ i = 1 N a i ∗ y i ( x ⋅ x i ) + b ∗ ) \sum_{i=i}^Na_i^*y_i(x \cdot x_i)+b^*=0 \\ f(x)=sign\left( \sum_{i=1}^Na_i^*y_i(x \cdot x_i)+b^* \right) i=iNaiyi(xxi)+b=0f(x)=sign(i=1Naiyi(xxi)+b)

线性支持向量机

在线性不可分的数据集中,一个超平面不可能把所有样本点都正确分类,因此至少存在一个样本点 ( x k , y k ) (x_k,y_k) (xk,yk),使 ( y k ) ( w ⋅ ( x k ) + b ) < 0 (yk)(w·(xk)+b)<0 (yk)(w(xk)+b)<0,所以 ( y k ) ( w ⋅ ( x k ) + b ) − 1 < 0 (y_k)(w·(x_k)+b)-1<0 (yk)(w(xk)+b)1<0,与不等式约束矛盾。

在线性支持向量机中,我们将线性可分支持向量机的硬间隔最大化改为软间隔最大化,就可以在近似线性可分的数据集中运用支持向量机了。

所谓近似线性可分的数据集,就是训练数据中有一些样本点,将这些样本点去除后就可以得到线性可分的数据集。这些样本点,我们称其为特异点。

特异点不满足函数间隔大于等于1的约束条件,这时,我们对每个样本点引入一个松弛变量 ξ ≥ 0 \xi \geq 0 ξ0 ,使函数间隔加上松弛变量大于等于1,于是约束条件变为:
y i ( w ⋅ x i + b ) ≥ 1 − ξ y_i(w \cdot x_i +b) \geq 1- \xi yi(wxi+b)1ξ
同时,将原来的目标函数变为:
1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i \frac12||w||^2+C\sum_{i=1}^N\xi_i 21∣∣w2+Ci=1Nξi
其中 C > 0 C>0 C>0为惩罚参数,C值大时对误分类的惩罚增大,反之,对误分类的惩罚减小。于是,最小化上式可以理解为,使前一项尽量小,即间隔尽量大,并且使误分类点的数量尽量小,也就是让后一项尽量小。参数C在两者之间有调和作用。这种间隔最大化的方法,称为软间隔最大化。

比较直观的理解松弛变量,就是松弛变量的加入不再要求特异点与分离超平面的函数距离大于等于1,但与此同时也需要给予最小化式子惩罚,以此来限制过于松弛的情况,而系数C则是用来调节间隔的软硬程度。

这样,我们就可以和训练线性可分的数据集一样来训练近似线性可分的数据集了。于是我们得到的问题为:
min ⁡ w , b , ξ 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i s . t . y i ( w ⋅ x i + b ) ≥ 1 − ξ i , i = 1 , 2 , . . . , N ξ i ≥ 0 , i = 1 , 2 , . . . , N \begin{aligned} & \min_{w,b,\xi}\frac12||w||^2+C\sum_{i=1}^N\xi_i \\ &s.t.\quad y_i(w \cdot x_i+b) \geq 1-\xi_i,i=1,2,...,N \\ & \xi_i \geq 0,i=1,2,...,N \end{aligned} w,b,ξmin21∣∣w2+Ci=1Nξis.t.yi(wxi+b)1ξi,i=1,2,...,Nξi0,i=1,2,...,N
从上面的问题中可以看出来,线性可分支持向量机是线性支持向量机中的一种特殊情况,如果数据集中没有特异点,则对于每个样本点来说松弛变量都为0,则近似线性可分转变为线性可分的情况。

线性支持向量机最后得到的超平面和决策函数为:
w ∗ ⋅ x i + b ∗ = 0 f ( x ) = s i g n ( w ∗ ⋅ x + b ∗ ) w^* \cdot x_i + b^* = 0 \\ f(x)=sign(w^* \cdot x + b^*) wxi+b=0f(x)=sign(wx+b)

对偶算法

首先建立拉格朗日函数:
L ( w , b , ξ , a , μ ) = 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i − ∑ i = 1 N a i ( y i ( w ⋅ x i + b ) − 1 + ξ i ) − ∑ i = 1 N μ i ξ i L(w,b,\xi,a,\mu)=\frac12||w||^2+C\sum_{i=1}^N\xi_i-\sum_{i=1}^Na_i(y_i(w \cdot x_i+b)-1+\xi_i)-\sum_{i=1}^N\mu_i\xi_i L(w,b,ξ,a,μ)=21∣∣w2+Ci=1Nξii=1Nai(yi(wxi+b)1+ξi)i=1Nμiξi
其中拉格朗日乘数 α i ≥ 0 α_i≥0 αi0 μ i ≥ 0 \mu_i≥0 μi0

原始问题为:
min ⁡ w , b , ξ max ⁡ a , μ L ( w , b , ξ , a , μ ) \min_{w,b,\xi}\max_{a,\mu}L(w,b,\xi,a,\mu) w,b,ξmina,μmaxL(w,b,ξ,a,μ)
对偶问题为:
max ⁡ a , μ min ⁡ w , b , ξ L ( w , b , ξ , a , μ ) \max_{a,\mu}\min_{w,b,\xi}L(w,b,\xi,a,\mu) a,μmaxw,b,ξminL(w,b,ξ,a,μ)
首先,对于内部极小化问题,对求偏导,并使偏导数等于0:
∇ w L ( w , b , ξ , a , μ ) = w − ∑ i = 1 N a i y i x i = 0 (1) \nabla_wL(w,b,\xi,a,\mu)=w-\sum_{i=1}^Na_iy_ix_i=0 \tag{1} wL(w,b,ξ,a,μ)=wi=1Naiyixi=0(1)

∇ b L ( w , b , ξ , a , μ ) = − ∑ i = 1 N a i y i = 0 (2) \nabla_bL(w,b,\xi,a,\mu)=-\sum_{i=1}^Na_iy_i=0 \tag{2} bL(w,b,ξ,a,μ)=i=1Naiyi=0(2)

∇ ξ L ( w , b , ξ , a , μ ) = C − a i − μ i = 0 (3) \nabla_\xi L(w,b,\xi,a,\mu)=C-a_i-\mu_i=0 \tag{3} ξL(w,b,ξ,a,μ)=Caiμi=0(3)

得到:
w = ∑ i = 1 N a i y i x i w=\sum_{i=1}^Na_iy_ix_i w=i=1Naiyixi

∑ i = 1 N a i y i = 0 \sum_{i=1}^Na_iy_i=0 i=1Naiyi=0

C − a i − μ i = 0 C-a_i-\mu_i=0 Caiμi=0

再将上面三个等式代回至拉格朗日函数中:
min ⁡ w , b , ξ L ( w , b , ξ , a , μ ) = − 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) + ∑ i = 1 N a i \min_{w,b,\xi}L(w,b,\xi,a,\mu)=-\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)+\sum_{i=1}^Na_i w,b,ξminL(w,b,ξ,a,μ)=21i=1Nj=1Naiajyiyj(xixj)+i=1Nai
再解对偶问题的外部极大化问题,得到问题:
max ⁡ a − 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) + ∑ i = 1 N a i ∑ i = 1 N a i y i = 0 s . t . C − a i − μ i = 0 μ i ≥ 0 , i = 1 , 2 , . . . , N \max_a-\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)+\sum_{i=1}^Na_i \\ \sum_{i=1}^Na_iy_i=0 \\ s.t.\quad C-a_i-\mu_i=0 \\ \mu_i \geq 0,i=1,2,...,N amax21i=1Nj=1Naiajyiyj(xixj)+i=1Naii=1Naiyi=0s.t.Caiμi=0μi0,i=1,2,...,N
在约束条件中,我们可以利用后面三个式子将μi消去:因为 μ i = C − α i \mu_i=C-α_i μi=Cαi,且 μ i ≥ 0 μ_i\geq 0 μi0,所以 C − α i ≥ 0 C-α_i \geq 0 Cαi0,又因为 α i ≥ 0 α_i\geq 0 αi0,所以 C ≥ α i ≥ 0 C \geq α_i \geq 0 Cαi0

并且我们将最大化问题通过乘以一个-1转换为最小化问题。

于是上述问题转变为:
min ⁡ a 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j ( x i ⋅ x j ) − ∑ i = 1 N a i s . t . ∑ i = 1 N a i y i = 0 0 ≤ a i ≤ C , i = 1 , 2 , . . . , N \begin{aligned} &\min_a\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_j(x_i \cdot x_j)-\sum_{i=1}^Na_i \\ &s.t. \quad \sum_{i=1}^Na_iy_i=0 \\ &0\leq a_i \leq C,i=1,2,...,N \end{aligned} amin21i=1Nj=1Naiajyiyj(xixj)i=1Nais.t.i=1Naiyi=00aiC,i=1,2,...,N
此时根据约束条件中α的各个分量的关系,代入极小化的式子中,并对每一个αi求偏导,并令偏导数为0,即可得到α向量。

线性支持向量机的KKT条件

与线性可分支持向量机相似,由于原始问题和对偶问题之间满足强对偶关系,因此可以利用KKT条件对 w ∗ w^* w b ∗ b^* b进行求解。以下是线性支持向量机的KKT条件:
∇ w L ( w ∗ , b ∗ , ξ ∗ , a ∗ , μ ∗ ) = w ∗ − ∑ i = 1 N a i ∗ y i x i = 0 (1) \nabla_wL(w^*,b^*,\xi^*,a^*,\mu^*)=w^*-\sum_{i=1}^Na_i^*y_ix_i=0 \tag{1} wL(w,b,ξ,a,μ)=wi=1Naiyixi=0(1)

∇ b L ( w ∗ , b ∗ , ξ ∗ , a ∗ , μ ∗ ) = − ∑ i = 1 N a i ∗ y i = 0 (2) \nabla_bL(w^*,b^*,\xi^*,a^*,\mu^*)=-\sum_{i=1}^Na_i^*y_i=0 \tag{2} bL(w,b,ξ,a,μ)=i=1Naiyi=0(2)

∇ ξ L ( w ∗ , b ∗ , ξ ∗ , a ∗ , μ ∗ ) = C − a i ∗ − μ i ∗ = 0 (3) \nabla_\xi L(w^*,b^*,\xi^*,a^*,\mu^*)=C-a_i^*-\mu_i^*=0 \tag{3} ξL(w,b,ξ,a,μ)=Caiμi=0(3)

a i ∗ ( y i ( w ∗ ⋅ x i + b ∗ ) − 1 + ξ i ∗ ) = 0 (4) a_i^*(y_i(w^* \cdot x_i +b^*)-1+\xi_i^*)=0 \tag{4} ai(yi(wxi+b)1+ξi)=0(4)

μ i ∗ ξ i ∗ = 0 (5) \mu_i^*\xi_i^*=0 \tag{5} μiξi=0(5)

y i ( w ∗ ⋅ x i + b ∗ ) − 1 + ξ i ∗ ≥ 0 (6) y_i(w^* \cdot x_i + b^*)-1+\xi_i^* \geq 0 \tag{6} yi(wxi+b)1+ξi0(6)

ξ i ∗ ≥ 0 (7) \xi_i^* \geq 0 \tag{7} ξi0(7)

a i ∗ ≥ 0 (8) a_i^* \geq 0 \tag{8} ai0(8)

μ i ∗ ≥ 0 , i = 1 , 2 , . . . , N (9) \mu_i^* \geq 0 ,i=1,2,...,N \tag{9} μi0,i=1,2,...,N(9)

若存在 α m = C α_m=C αm=C,则根据式(3)可得, μ m = 0 μ_m=0 μm=0,根据式(4)可得 y m ( w ∗ ⋅ x m + b ∗ ) − 1 + ξ m ∗ ≥ 0 y_m(w^* \cdot x_m + b^*)-1+\xi_m^* \geq 0 ym(wxm+b)1+ξm0 ,则无法确定 b ∗ b^* b,根据式(5)可得 ξ m ∗ > 0 \xi_m^* > 0 ξm>0 ,可知该点为特异点。

若存在 α k = 0 α_k=0 αk=0,则根据式(3)可得, μ k = C μ_k=C μk=C,根据式(4)可得 y k ( w ∗ ⋅ x k + b ∗ ) − 1 + ξ k ∗ > 0 y_k(w^* \cdot x_k + b^*)-1+\xi_k^* > 0 yk(wxk+b)1+ξk>0 ,则无法确定 b ∗ b^* b,根据式(5)可得$ \xi_k^*=0$ ,所以 y k ( w ∗ ⋅ x k + b ∗ ) − 1 > 0 y_k(w^* \cdot x_k + b^*)-1 > 0 yk(wxk+b)1>0 ,可知该点为普通样本点。

若存在 0 < α j < C 0<α_j<C 0<αj<C,则根据式(3)可得, μ j ≠ 0 μ_j \ne 0 μj=0,根据式(4)可得 y k ( w ∗ ⋅ x k + b ∗ ) − 1 + ξ k ∗ = 0 y_k(w^* \cdot x_k + b^*)-1+\xi_k^* = 0 yk(wxk+b)1+ξk=0 ,且根据式(5)可得$ \xi_k^*=0 $,所以 y k ( w ∗ ⋅ x k + b ∗ ) − 1 = 0 y_k(w^* \cdot x_k + b^*)-1 = 0 yk(wxk+b)1=0 ,样本点落在间隔边界上,可确定 b ∗ b^* b

由此可得:
b ∗ = y i − ∑ i = i N y i a i ∗ ( x i ⋅ x j ) b^*=y_i-\sum_{i=i}^Ny_ia_i^*(x_i \cdot x_j) b=yii=iNyiai(xixj)
由式(1)可得:
w ∗ = ∑ i = 1 N a i ∗ y i x i w^*=\sum_{i=1}^Na_i^*y_ix_i w=i=1Naiyixi
再代入之前求得的 α ∗ α^* α,可得线性支持向量机的分离超平面和分类决策函数。

线性支持向量机的支持向量

我们将 a i > 0 a_i>0 ai>0时对应的样本点称为线性支持向量机的支持向量。

在这里插入图片描述

软间隔的支持向量 x i x_i xi或者在间隔边界上,或者在间隔边界与分离超平面之间,或者在分离超平面误分一侧。

合页损失函数

线性支持向量机还可以通过最小化合页损失函数来获得分离超平面。

合页损失函数为:
∑ i = 1 N [ 1 − y i ( x ⋅ x i + b ) ] + + λ ∣ ∣ w ∣ ∣ 2 \sum_{i=1}^N[1-y_i(x \cdot x_i+b)]_++\lambda||w||^2 i=1N[1yi(xxi+b)]++λ∣∣w2
其中第一项是经验损失,下标+表示:
[ Z ] + = { z , z > 0 0 , z ≤ 0 [Z]_+= \begin{cases} z, \quad z>0 \\ 0, \quad z \leq 0 \end{cases} [Z]+={z,z>00,z0
放在SVM的情况中, 1 − y i ( x ⋅ x i + b ) > 0 1-y_i(x \cdot x_i+b) > 0 1yi(xxi+b)>0 时, y i ( x ⋅ x i + b ) < 1 y_i(x \cdot x_i+b)<1 yi(xxi+b)<1,函数距离小于1,该样本点要么是被正确分类的但位于分离超平面和间隔边界之间,要么是特异点,损失就是 1 − y i ( x ⋅ x i + b ) 1−y_i(x \cdot x_i+b) 1yi(xxi+b),若 1 − y i ( x ⋅ x i + b ) < 0 1−y_i(x \cdot x_i+b)<0 1yi(xxi+b)<0 ,代表该样本点被正确分类且在间隔边界之外,损失为0。

合页损失函数的第二项为正则化项,是用来防止过拟合的。

现在证明为何原始最优化问题等价于合页损失函数最小化。

原始最优化问题:
min ⁡ w , b , ξ 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i s . t . y i ( w ⋅ x i + b ) ≥ 1 − ξ i , i = 1 , 2 , . . . , N ξ i ≥ 0 , i = 1 , 2 , . . . , N \begin{aligned} &\min_{w,b,\xi}\frac12||w||^2+C\sum_{i=1}^N\xi_i \\ &s.t. \quad y_i(w \cdot x_i +b )\geq 1-\xi_i, i=1,2,...,N \\ & \xi_i \geq 0,i=1,2,...,N \end{aligned} w,b,ξmin21∣∣w2+Ci=1Nξis.t.yi(wxi+b)1ξi,i=1,2,...,Nξi0,i=1,2,...,N
在合页损失函数最小化中,我们令 [ 1 − y i ( x ⋅ x i + b ) ] + = ξ i [1-y_i(x \cdot x_i+b)]_+=\xi_i [1yi(xxi+b)]+=ξi ,则约束条件中 ξ i ≥ 0 \xi_i \geq 0 ξi0 成立。

且当 1 − y i ( x ⋅ x i + b ) > 0 1-y_i(x \cdot x_i+b)>0 1yi(xxi+b)>0 时, 1 − y i ( x ⋅ x i + b ) = ξ i 1-y_i(x \cdot x_i+b) = \xi_i 1yi(xxi+b)=ξi ,则$1-\xi_i = y_i(x \cdot x_i+b) $。

1 − y i ( x ⋅ x i + b ) ≤ 0 1-y_i(x \cdot x_i+b) \leq 0 1yi(xxi+b)0时, ξ i = 0 \xi_i=0 ξi=0,所以 $y_i(x \cdot x_i+b) \geq 1-\xi_i $ ,于是约束条件中的 $y_i(x \cdot x_i+b) \geq 1-\xi_i $ 成立。

所以合页损失最小化可以转变为:
min ⁡ w , b ∑ i = 1 N ξ i + λ ∣ ∣ w ∣ ∣ 2 \min_{w,b}\sum_{i=1}^N\xi_i+\lambda ||w||^2 w,bmini=1Nξi+λ∣∣w2
因为 λ \lambda λ是正则化项的系数,用于调节模型的拟合程度,为超参数,在学习模型时可将其视作常数,因此可以用 1 2 C \frac12C 21C来代替。

于是转变为:
min ⁡ w , b 1 C ( 1 2 ∣ ∣ w ∣ ∣ 2 + C ∑ i = 1 N ξ i ) \min_{w,b}\frac1C\left(\frac12||w||^2+C\sum_{i=1}^N\xi_i\right) w,bminC1(21∣∣w2+Ci=1Nξi)
括号外的 1 C \frac1C C1是一个常数,不影响最小化过程,可忽略,因此我们得到线性支持向量机的原始最优化问题。

将合页损失函数直观地表现出来为:

在这里插入图片描述

其中横轴为函数间隔,虚线为感知机的合页损失函数。线性支持向量机与感知机的差别在于,线性支持向量机不仅需要将样本点正确分类,而且与分离超平面的函数距离需要超过1才没有损失,因此线性支持向量机对分类更为严格。

非线性支持向量机

对于一组既非线性可分,也非近似线性可分的数据集,我们称其为线性不可分的,下图展示了线性可分,近似线性可分和线性不可分的数据集。
在这里插入图片描述

书中介绍了核方法的技术,将线性不可分的数据集转换为线性可分的数据集。

核方法

非线性转换为线性

对于线性不可分数据集(比如下图左侧),无法使用一条直线将正负实例分开,但可以使用椭圆曲线将其分开,在其它可能的线性不可分数据集中,也许可以使用其它类型的曲线正确分类,这样的曲线称之为超曲面,这样的问题称之为非线性可分问题。

在这里插入图片描述
-home.csdnimg.cn/images/20230724024159.png?origin_url=.%5Cimages%5C7.8.png&pos_id=img-oqjmgl81-1708431465859)

对于这一类问题,我们可以将实例进行非线性变换,从线性不可分(上图左侧)变成线性可分(上图右侧)。

我们可以用数学语言对其进行表达,以上图的椭圆曲线为例,设原空间为 x ⊂ R 2 , z = ( x ( 1 ) , x ( 2 ) ) T ∈ X x\subset R^2,z=(x^{(1)},x^{(2)})^T \in X xR2,z=(x(1),x(2))TX,新空间为 z ⊂ R 2 , z = ( z ( 1 ) , z ( 2 ) ) T ∈ Z z\subset R^2,z=(z^{(1)},z^{(2)})^T \in Z zR2,z=(z(1),z(2))TZ,那么原空间到新空间的映射为:
z = ϕ ( x ) = ( ( x ( 1 ) ) 2 , ( x ( 2 ) ) 2 ) T z=\phi(x)=((x^{(1)})^2,(x^{(2)})^2)^T z=ϕ(x)=((x(1))2,(x(2))2)T
经过变换,原空间 X ⊂ R 2 X\subset R^2 XR2 变换为新空间 Z ⊂ R 2 Z\subset R^2 ZR2,原空间中的点相应地变换为新空间中的点。原空间中的椭圆可以表示为:
w 1 ( x ( 1 ) ) 2 + w 2 ( x ( 2 ) ) 2 + b = 0 w_1(x^{(1)})^2+w_2(x^{(2)})^2+b=0 w1(x(1))2+w2(x(2))2+b=0

变换成为新空间中的直线:
w 1 ( z ( 1 ) ) 2 + w 2 ( z ( 2 ) ) 2 + b = 0 w_1(z^{(1)})^2+w_2(z^{(2)})^2+b=0 w1(z(1))2+w2(z(2))2+b=0

在变换后的新空间里,可以用一条直线将变换后的正负实例点正确分开。这样,原空间的非线性可分问题就变成了新空间的线性可分问题。这样的转换都是从低维的原空间向更高维的新空间进行转换,也就是将原本用较少数量的特征可以代表的样本点,转换为用较多的特征代表的样本点。

我们将原空间称为输入空间X,映射后的新空间称为特征空间H。

核函数:

线性可分或者近似线性可分的情况下,使用了拉格朗日对偶问题,需要计算样本点的内积,会导致需要大量的计算量。而非线性可分问题,进行了输入空间X到特征空间H的映射后,其特征数量将从输入空间的M个特征转变为特征空间中更大的数量,对样本点内积的计算量变得更大。

为了解决这个问题,提出了核技巧的方法,也就是利用核函数,绕过暴力计算样本点内积的过程,而直接求得最终的内积。

核函数的定义:

如果存在一个从X到H的映射:
ϕ ( x ) : x → H \phi(x):x\rightarrow H ϕ(x):xH
使得对所有 x , z ∈ X x,z \in X x,zX ,函数 K ( x , z ) K(x,z) K(x,z)满足条件:
K ( x , z ) = ϕ ( x ) ⋅ ϕ ( z ) K(x,z)=\phi(x) \cdot \phi(z) K(x,z)=ϕ(x)ϕ(z)
则称 K ( x , z ) K(x,z) K(x,z)为核函数。其中 ϕ ( x ) \phi(x) ϕ(x) 为映射函数,表示一个X中的样本点转换到H空间后的特征向量。

可通过直接计算核函数得到H空间中的所有样本点的内积。对于给定的核函数 K ( x , z ) K(x,z) K(x,z),特征空间H核映射函数可以是不同的,但其核函数是相同的。

于是,之前拉格朗日对偶问题可以转变为:
min ⁡ a 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j K ( x i , x j ) − ∑ i = 1 N a i \min_a\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_jK(x_i,x_j)-\sum_{i=1}^Na_i amin21i=1Nj=1NaiajyiyjK(xi,xj)i=1Nai
其中K为核函数, K ( x i , x j ) K(x_i,x_j) K(xi,xj) x i x_i xi x j x_j xj的内积。

判断是否为核函数:正定核

通常所说的核函数就是正定核函数。

要使一个函数为正定核函数的充要条件是满足对称性 K ( x , z ) = K ( z , x ) K(x,z)=K(z,x) K(x,z)=K(z,x),以及正定性,即满足对任意 x i ∈ X , i = 1 , 2 , . . . , m x_i \in X,i=1,2,...,m xiX,i=1,2,...,m K ( x , z ) K(x,z) K(x,z)对应的Gram矩阵: K = [ K ( x i , x j ) ] m × m K=[K(x_i,x_j)]_{m \times m} K=[K(xi,xj)]m×m是半正定矩阵。

首先证明对称性:
K ( x , z ) = ϕ ( x ) ⋅ ϕ ( z ) K ( z , x ) = ϕ ( z ) ⋅ ϕ ( x ) K(x,z)=\phi(x) \cdot \phi(z) \\ K(z,x)=\phi(z) \cdot \phi(x) K(x,z)=ϕ(x)ϕ(z)K(z,x)=ϕ(z)ϕ(x)
因为内积 ϕ ( x ) ⋅ ϕ ( z ) = ϕ ( z ) ⋅ ϕ ( x ) \phi(x) \cdot \phi(z) = \phi(z) \cdot \phi(x) ϕ(x)ϕ(z)=ϕ(z)ϕ(x),所以 K ( x , z ) = K ( z , x ) K(x,z)=K(z,x) K(x,z)=K(z,x)。对称性得证。

接着证明正定性。

如果 K ( x , z ) K(x,z) K(x,z)是正定核函数,想要证明Gram矩阵是半正定矩阵,只需要证明存在n维实数向量 a , a T K a ≥ 0 a,a^TKa \geq 0 a,aTKa0 即可,这是证明一个矩阵是半正定矩阵的方法。

首先构造Gram矩阵:
[ K i j ] m × m = [ K ( x i , x j ) ] m × m [K_{ij}]_{m \times m} = [K(x_i,x_j)]_{m \times m} [Kij]m×m=[K(xi,xj)]m×m

其中 K i j K_{ij} Kij代表Gram矩阵中 x i x_i xi x j x_j xj的内积。

对任意m维向量 α ( α 1 , α 2 , … , α m ) ∈ R α(α_1,α_2,…,α_m) \in R α(α1α2αm)R,有:
a T K a = ( a 1 a 2 ⋯ a n ) ( K 11 K 12 ⋯ K 1 N ⋯ ⋯ K N 1 K N 2 ⋯ K N N ) ( a 1 a 2 ⋯ a N ) = ∑ i = 1 N ∑ j = 1 N a i a j K i j = ∑ i = 1 N ∑ j = 1 N a i a j ϕ ( x i ) T ϕ ( x j ) = ∑ i = 1 N a i ϕ ( x i ) T ∑ j = 1 N a j ϕ ( x j ) = ( ∑ i = 1 N a i ϕ ( x i ) ) T ( ∑ j = 1 N a j ϕ ( x j ) ) = ∣ ∣ ∑ i = 1 N a i ϕ ( x i ) ∣ ∣ 2 ≥ 0 \begin{aligned} a^TKa&= (\begin{matrix} a_1 & a_2& \cdots & a_n \end{matrix}) (\begin{matrix} K_{11} & K_{12} & \cdots & K_{1N} \\ \cdots & & & \cdots \\ K_{N1} & K_{N2} & \cdots & K_{NN} \end{matrix}) (\begin{matrix} a_1 \\ a_2 \\ \cdots \\ a_N \end{matrix}) \\ & =\sum_{i=1}^N\sum_{j=1}^Na_ia_jK_{ij} \\ & =\sum_{i=1}^N\sum_{j=1}^Na_ia_j\phi(x_i)^T\phi(x_j) \\ &= \sum_{i=1}^Na_i\phi(x_i)^T \sum_{j=1}^Na_j\phi(x_j) \\ &= \left( \sum_{i=1}^Na_i\phi(x_i) \right)^T\left( \sum_{j=1}^Na_j\phi(x_j) \right) \\ &= ||\sum_{i=1}^Na_i\phi(x_i)||^2 \geq 0 \end{aligned} aTKa=(a1a2an)(K11KN1K12KN2K1NKNN)(a1a2aN)=i=1Nj=1NaiajKij=i=1Nj=1Naiajϕ(xi)Tϕ(xj)=i=1Naiϕ(xi)Tj=1Najϕ(xj)=(i=1Naiϕ(xi))T(j=1Najϕ(xj))=∣∣i=1Naiϕ(xi)20
证明的等价定义对于构造核函数时特别有用,但检验一个函数是否为核函数时很难,因为需要对于任意的 x i ∈ X , i = 1 , 2 , ⋯   , m x_i \in X, i=1,2, \cdots ,m xiX,i=1,2,,m,检验对应的Gram矩阵,难点就在任意二字。因此,在实际问题中一般使用已有的核函数。

常用核函数

线性核:
K ( x , z ) = x ⋅ z + c K(x,z)=x \cdot z +c K(x,z)=xz+c
线性核函数是所有核函数中最简单的。

多项式核函数:
K ( x , z ) = ( a x ⋅ z + c ) p K(x,z)=(ax \cdot z +c )^p K(x,z)=(axz+c)p
其中a,c和p都是实系数,线性核就是多项式核函数的一个特例。

高斯核函数:
K ( x , z ) = e x p ( − ∣ ∣ x − z ∣ ∣ 2 2 σ 2 ) K(x,z)=exp(-\frac{||x-z||^2}{2\sigma^2}) K(x,z)=exp(2σ2∣∣xz2)
高斯核函数可以将输入空间映射到无穷维的特征空间中。我们知道非线性可分的低维的样本点在更高维空间中线性可分,在无穷维的空间中一定线性可分,因此高斯核函数是在非线性支持向量机中一定要尝试的核函数。

幂指数核:
K ( x , z ) = e x p ( − ∣ ∣ x − z ∣ ∣ 2 σ 2 ) K(x,z)=exp(-\frac{||x-z||}{2\sigma^2}) K(x,z)=exp(2σ2∣∣xz∣∣)
拉普拉斯核:
K ( x , z ) = e x p ( − ∣ ∣ x − z ∣ ∣ σ ) K(x,z)=exp(-\frac{||x-z||}{\sigma}) K(x,z)=exp(σ∣∣xz∣∣)

核函数的选择

对一个具体问题我们需要选择一个核函数以达到获得最好的模型,但如何快速做出选择并没有一个具体的方法,在很多问题上,需要尝试各个核函数,每个核函数中的参数也需要大量尝试,最后经过对比找到一个效果最好的核函数,也就得到最终的分离超曲面和决策函数。

非线性支持向量机模型学习步骤

  1. 依据下式求得 α ∗ α^* α

min ⁡ a 1 2 ∑ i = 1 N ∑ j = 1 N a i a j y i y j K ( x i , x j ) − ∑ i = 1 N a i s . t . ∑ i = 1 N a i y i = 0 0 ≤ a i ≤ C , i = 1 , 2 , . . . , N s . t . \begin{aligned} & \min_a\frac12\sum_{i=1}^N\sum_{j=1}^Na_ia_jy_iy_jK(x_i,x_j)-\sum_{i=1}^Na_i \\ &s.t. \quad \sum_{i=1}^Na_iy_i=0 \\ & 0 \leq a_i \leq C,i=1,2,...,N \end{aligned} s.t. amin21i=1Nj=1NaiajyiyjK(xi,xj)i=1Nais.t.i=1Naiyi=00aiC,i=1,2,...,Ns.t.

​ 该步骤需要选择合适的核函数和参数C。

  1. 依据下式求得 b ∗ b^* b

b ∗ = y i − ∑ i = i N y i a i ∗ K ( x i ⋅ x j ) b^*=y_i-\sum_{i=i}^Ny_ia_i^*K(x_i \cdot x_j) b=yii=iNyiaiK(xixj)

​ 该步骤需要选择一个合适的 α ∗ α^* α分量 0 < a j ∗ < C 0 < a_j^* < C 0<aj<C

  1. 获得决策函数:
    f ( x ) = s i g n ( ∑ i = i N a i ∗ y i K ( x i ⋅ x j ) + b ∗ ) f(x)=sign\left( \sum_{i=i}^Na_i^*y_iK(x_i \cdot x_j) +b^* \right) f(x)=sign(i=iNaiyiK(xixj)+b)

代码

import numpy as np
import pandas as pd
from sklearn import datasets
from sklearn.model_selection import train_test_split
import math
from tqdm import tqdm

# 加载鸢尾花数据集
iris = datasets.load_iris()
df = pd.DataFrame(iris.data)
df['label'] = iris.target
df.columns = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'label']

# 提取前100条数据
data = np.array(df.iloc[0:100, [0, 1, -1]])
# 得到x(特征向量)、y(分类标签)
x, y = data[:, :-1], data[:, -1]

# 将两类分类标签分别替换为1与-1,便于感知机处理
y = np.array([1 if i == 1 else -1 for i in y])


# 划分训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=100)

class Model:
    def __init__(self, train_data, train_label, sigma, C, toler, itertime):
        self.train_data = train_data                       # 训练集数据
        self.train_label = train_label                     # 训练集标记
        self.m, self.n = np.shape(train_data)              # self.m为训练集样本容量,self.n为特征数量
        self.sigma = sigma                                 # 高斯核分母上的超参数
        self.kernal = self.kernalMatrix()         # 高斯核矩阵
        self.alpha = np.zeros(self.m)                # 初始化拉格朗日向量,长度为训练集样本容量
        self.b = 0                                         # 初始化参数b
        self.C = C                                         # 惩罚参数
        self.toler = toler                                 # 松弛变量
        self.itertime = itertime                           # 迭代次数
        self.E = [float(-1 * y) for y in self.train_label]   # 初始化Elist,因为alpha和b初始值为0,因此E的初始值为训练集标记的值

    # 高斯核矩阵
    def kernalMatrix(self):

        # 初始化高斯核矩阵,矩阵为m*m大小
        matrix = [[0 for i in range(self.m)] for j in range(self.m)]

        # 遍历每一个样本
        for i in range(self.m):

            # 首先得到一个样本的数据
            X = self.train_data[i]

            # 仅遍历从i到self.m的样本,因为Kij和Kji的值相同,所以只需要计算一次
            for j in range(i, self.m):

                # 得到另一个样本的数据
                Z = self.train_data[j]

                # 计算核函数
                K = np.exp(-1 * np.dot(X - Z, X - Z) / (2 * np.square(self.sigma)))

                # 存储在核矩阵中对称的位置
                matrix[i][j] = K
                matrix[j][i] = K

        matrix = np.array(matrix)

        return matrix
    
    def calgxi(self, i):

        indexs = [index for index, value in enumerate(self.alpha) if value != 0]
        gxi = 0
        for index in indexs:
            gxi += self.alpha[index] * self.train_label[index] * self.kernal[i][index]
        gxi = gxi + self.b

        return gxi
    
    # 判断是否符合KKT条件
    def isSatisfyKKT(self, i):

        # 获得alpha[i]的值
        alpha_i = self.alpha[i]

        # 计算yi * g(xi)
        gxi = self.calgxi(i)
        yi = self.train_label[i]
        yi_gxi = yi * gxi

        # 判断是否符合KKT条件
        if -1 * self.toler < alpha_i < self.toler and yi_gxi >= 1:
            return True
        elif -1 * self.toler < alpha_i < self.C + self.toler and math.fabs(yi_gxi - 1) < self.toler:
            return True
        elif self.C - self.toler < alpha_i < self.C + self.toler and yi_gxi <= 1:
            return True
        return False
    
    def SMO(self):
        # 迭代
        t = 0
        parameterchanged = 1
        pbar = tqdm(total=self.itertime)

        while t < self.itertime and parameterchanged > 0:
            t += 1
            parameterchanged = 0
            '''选择两个alpha'''
            pbar.update(1)
            # 外层循环,选择第一个alpha
            for i in range(self.m):
                # 判断是否符合KKT条件,如果不满足,则选择该alpha为alpha1
                # 如果满足,则继续外层循环
                TorF = self.isSatisfyKKT(i)
                if TorF == False:
                    alpha1 = self.alpha[i]

                    # 从Earray得到alpha1对应的E1
                    E1 = self.E[i]

                    # 复制一个EMatrix,并令E1的位置为nan
                    # 这样在接下来找最大值和最小值时将不会考虑E1
                    # 这里需要使用copy,如果不用copy,改变EM_temp也会同时改变EMatrix
                    EM_temp = np.copy(self.E)
                    EM_temp[i] = np.nan

                    # 我们需要使|E1-E2|的值最大,由此选择E2
                    # 首先初始化maxE1_E2和E2及E2的下标j
                    maxE1_E2 = -1
                    E2 = np.nan
                    j = -1

                    # 内层循环
                    # 遍历EM_temp中的每一个Ei,得到使|E1-E2|最大的E和它的下标
                    for j_temp, Ej in enumerate(EM_temp):
                        if math.fabs(E1 - Ej) > maxE1_E2:
                            maxE1_E2 = math.fabs(E1 - Ej)
                            E2 = Ej
                            j = j_temp

                    # alpha2为E2对应的alpha
                    alpha2 = self.alpha[j]

                    '''求最优alpha1和alpha2'''

                    y1 = self.train_label[i]
                    y2 = self.train_label[j]

                    # 计算η
                    K11 = self.kernal[i][i]
                    K22 = self.kernal[j][j]
                    K12 = self.kernal[i][j]
                    eta = K11 + K22 - 2 * K12
                    # 计算alpha2_new
                    if eta > 0:
                         alpha2_new = alpha2 + y2 * (E1 - E2) / eta
                    else:
                        alpha2_new = alpha2

                    # 计算上限H和下限L
                    if y1 != y2:
                        L = max([0, alpha2 - alpha1])
                        H = min([self.C, self.C + alpha2 - alpha1])
                    else:
                        L = max([0, alpha2 + alpha1 - self.C])
                        H = min([self.C, alpha2 + alpha1])

                    # 剪切alpha2_new
                    if alpha2_new > H:
                        alpha2_new = H
                    elif alpha2_new < L:
                        alpha2_new = L

                    #                     # 如果H=L,说明不需要更新
                    #                     if H == L:
                    #                         continue

                    # 得到alpha1_new
                    alpha1_new = alpha1 + y1 * y2 * (alpha2 - alpha2_new)

                    '''更新b'''
                    # 计算b1_new和b2_new
                    b1_new = -1 * E1 - y1 * K11 * (alpha1_new - alpha1) - y2 * K12 * (alpha2_new - alpha2) + self.b
                    b2_new = -1 * E2 - y1 * K12 * (alpha1_new - alpha1) - y2 * K22 * (alpha2_new - alpha2) + self.b

                    # 根据alpha1和alpha2的范围确定b_new
                    if 0 < alpha1_new < self.C and 0 < alpha2_new < self.C:
                        b_new = b1_new
                    else:
                        b_new = (b1_new + b2_new) / 2

                    '''更新E'''
                    # 首先需要更新两个alpha和b
                    self.alpha[i] = alpha1_new
                    self.alpha[j] = alpha2_new
                    self.b = b_new

                    # 计算Ei_new和Ej_new
                    E1_new = self.calgxi(i) - y1
                    E2_new = self.calgxi(j) - y2

                    # 更新E
                    self.E[i] = E1_new
                    self.E[j] = E2_new

                    if math.fabs(alpha2_new - alpha2) >= 0.000001:
                        parameterchanged += 1
        pbar.update(self.itertime-t)
        pbar.close()
        # 最后遍历一遍alpha,大于0的下标即对应支持向量
        VecIndex = [index for index, value in enumerate(self.alpha) if value > 0]

        # 返回支持向量的下标,之后在预测时还需要用到
        return VecIndex

    '''计算b'''
    def OptimizeB(self):

        for j, a in enumerate(self.alpha):
            if 0 < a < self.C:
                break

        yj = self.train_label[j]
        summary = 0
        for i in range(self.alpha):
            summary += self.alpha[i] * self.train_label[i] * self.KernalMatrix[i][j]

        optimiezedB = yj - summary
        self.b = optimiezedB

    '''计算单个核函数'''
    def CalSingleKernal(self, x, z):

        SingleKernal = np.exp(-1 * np.dot(x - z, x - z) / (2 * np.square(self.sigma)))
        return SingleKernal

    '''单个新输入实例的预测'''
    def predict(self, x, VecIndex):

        # 决策函数计算
        # 求和项初始化
        summary = 0

        # Index中存储着不为0的alpha的下标
        for i in VecIndex:

            alphai = self.alpha[i]
            yi = self.train_label[i]
            Kernali = self.CalSingleKernal(x, self.train_data[i])

            summary += alphai * yi * Kernali

        # 最后+b
        # np.sign得到符号
        result = np.sign(summary + self.b)

        return result

    '''测试模型'''
    def test(self, test_data, test_label, VecIndex):

        # 测试集实例数量
        TestNum = len(test_label)

        errorCnt = 0

        # 对每一个实例进行预测
        for i in range(TestNum):

            result = self.predict(test_data[i], VecIndex)
            if result != test_label[i]:
                errorCnt += 1

        Acc = 1 - errorCnt / TestNum

        return Acc
    
perceptron = Model(x_train,y_train, 10, 200, 0.001, 100)

VecIndex = perceptron.SMO()

Acc = perceptron.test(x_test, y_test, VecIndex)
print('Accurate: ', Acc)
  • 23
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值