《hands-on ml》Chapter 5

线性分类(Linear SVM Classification)

SVM基本定义

使用SVM进行分类,和传统的线性模型有何区别,可以从下图中得出答案

左边的图为使用三个线性模型进行分类的结果,其中虚线的模型无法正确分类,其他两个实线模型可以正确分类,不过其边界太靠近某些样本了,因此预测的时候很可能出错。

而右侧是使用SVM分类的结果,实现代表分类的分界线,可见SVM不仅可以正确的分类,而且尽量远离最接近的样本。SVM其实就是寻找两个样本之间的最宽的“大马路”(图中的虚线),因此也被称为大间距分类(large margin classification)。而虚线上圈起来的样本,称为支持向量(support vector)。

SVM对于特征的取值范围比较敏感,如下图所示。如果未经过特征缩放(feature scaling),x1的取值明显比x2要大,从而导致SVM的分类间距比较窄。经过特征缩放后,间距就比之前要宽很多。


软间隔分类(Soft Margin Classification)

如果分类结果一定要非常准确,所有的样本一定要在正确的一侧,称之为硬间隔分类(hard margin classification)。但是这种硬性分类,就会存在两个问题,如下图所示

  • 左图中,一个异常值就会导致模型无法线性分类
  • 右图中,一个异常值会导致模型分类结果的间隔太窄

那么为了避免这种问题,就需要一个更加灵活的模型,可以在增加间距和允许误差(样本出现在虚线之内,甚至出现在错误的一侧)之间找到一个平衡,称之为软间隔分类(soft margin classification)。

可以通过超参数C来控制这个度,越小的C就会允许更多的误差,从而让间隔更大,效果如下图所示


非线性分类(Nonlinear SVM Classification)

对于样本非线性分布的场景,可以类似第四章的做法,添加更多的特征(比如多项式特征),从而做到线性可分隔,如下图所示。之前的x1单一特征无法做到线性可分隔,添加了新特征x2=(x1)2后,就可以很容易分隔开来。

多项式核函数(Polynomial Kernel)

之前提到过,通过增加多项式特征,再用线性模型来拟合。但是问题依旧存在,项数少的模型简单,可能不足够拟合,而项数多的复杂模型又会增加计算量。

但是SVM有个比较神奇的特性,称之为kernel trick,能够在不实际增加多项式特征的情况下,得出相同的计算结果。因此即使项数较高,也不会导致特征数膨胀,因为并没有实际增加这些特征。


高斯核函数(Gaussian RBF Kernel)

处理非线性问题的另一个技巧,就是通过一个相似性函数来计算每个样本与指定的关键点的相似度,作为新增的相似性特征。

一个比较常见的函数,就是RBF(Gaussian Radial Basis Function,径向基核函数),其定义如下:

\phi\gamma(\mathrm{x},\ell)=\exp(-\gamma\|\mathrm{x}-\ell\|^2)

这里的函数就是离目标越近取值越大。如下图所示,选择-2和1两个点作为目标,分别计算相似度函数的输出作为新的两个特征x2和x3。根据新的特征,就可以很容易找到分类之间的界限了。

那么该如何挑选合适的关键点呢?最简单的做法就是每个样本都作为关键点,这样的话,每个样本都会增加很多特征。代价就是计算量会膨胀的厉害,比如之前m个样本,每个样本n个特征,处理后就会变成每个样本有m个特征。

还好有kernel trick,可以在不增加特征的前提下,得到相同的结果。比如下图,就是使用了SVC的rbf核,有两个超参数γ与C。C前面提到过,用来控制软间隔的度,C越小就允许越多的误差。γ则用来控制RBF曲线的宽度。γ越小,曲线越宽,关键点对其他样本的影响范围越大,分界线就越平滑。


计算复杂度

LinearSVC基于liblinear库,其实现了解决线性SVM的坐标下降算法(Coordinate Descent),但是并不支持kernel trick。其与样本数与特征数呈正比,计算复杂度大约为O(m * n)。

SVC基于libsvm库,其背后的算法为SMO算法(Sequential Minimal Optimization),且支持kernel trick。其计算复杂度大约在O(m2 * n)到O(m3 * n)之间,因此样本集很大的时候就会特别慢,所以比较适合模型很复杂但是样本数不大的训练集。

ClassTime ComplexityOut-of-coreScaling requiedKernel trick
LinearSVCO(m * n)NoYesNo
SGDClassifierO(m * n)YesYesNo
SVCO(m2*n) to O(m3*n)NoYesYes

SVM回归

SVM不仅可以用于分类,也可以用于线性及非线性的回归。之前的分类,是找到一个最大的间距,间距中间尽量不出现样本。而回归的目标恰好相反,找到一个最小的间距,间距中间尽量覆盖所有的样本。间距的宽度由一个超参数ϵ来控制,ϵ越小宽度越小,因此有更多的样本不会出现在间距中。

同样可以用于多项式模型的回归。除了之前的ϵ,还有一个超参数C用来控制正则化的度,C越大正则化度越小,曲线越能拟合更多的样本。如下图所示


原理解析

决策函数及预测

线性SVM分类器用于预测时,对于一个样本x,其预测函数如下式所示

\hat{y}=\begin{cases}
   0 &\text{if } \mathrm{w}^{T}\cdot\mathrm{x} + b < 0, \\
   1 &\text{if } \mathrm{w}^{T}\cdot\mathrm{x} + b \ge0
\end{cases}

下图为两维特征下用于分类的超平面,超平面与二维平面的交界线,就是前文图中的实线,实线上预测函数值为0。虚线就是函数值为1或者-1在二维平面的投影,虚线平行于实线,其构成的就是分类的间距。训练一个线性SVM模型,就是找到这样的w和b,让间距尽可能宽,并且让分类结果正确。


训练目标

训练函数的斜率等价于||w||,由于函数为1,斜率越小,其在二维平面的投影(也就是虚线)之间的间距也就越宽。下面一幅图就说明了斜率对于间距的影响。

因此我们的训练目标就很明确了,一是让||w||尽量小,从而扩大间距,二是让样本分类尽量正确。分类正确的前提,就是positive样本函数值≥1,negtive样本函数值≤-1。

\begin{aligned}
t^{(i)}&=\begin{cases}
1 &\text{if } y^{(i)}=1 \\
-1 &\text{if } y^{(i)}=0
\end{cases}\\
\quad\\
对于&所有样本:
t^{(i)}(\mathrm{w}^{T}\cdot\mathrm{x}^{(i)} + b) \ge 1
\end{aligned}

硬间隔分类目标

因此,在一定约束下找最优解的问题,称之为约束优化问题(constrained optimization problem)。对于硬间隔分类来说,其约束优化的目标定义如下

\begin{aligned}

&\min_{\mathrm{w}, b}&&\frac{1}{2}\mathrm{w}^T\cdot\mathrm{w} \\
&\text{subject to}&&t^{(i)}(\mathrm{w}^T\cdot\mathrm{x}^{(i)}+b) \ge 1 &\text{for}\ i=1,2,...,m

\end{aligned}

这里的最小化目标,1/2 wTw,等价于1/2 ||w||2。至于为什么用l2-norm,而不是l1-norm,是因为求导就是简单的w,后续计算更方便。

软间隔分类目标

对于软间隔分类来说,每个样本增加ζ(i)参数,用来控制样本偏离的误差范围。其约束优化的目标定义如下

\begin{aligned}

&\min_{\mathrm{w}, b}&&\frac{1}{2}\mathrm{w}^T\cdot\mathrm{w} + C\sum_{i=1}^{m}\zeta^{(i)}\\
&\text{subject to}&&t^{(i)}(\mathrm{w}^T\cdot\mathrm{x}^{(i)}+b) \ge 1-\zeta^{(i)} &\text{for}\ i=1,2,...,m

\end{aligned}

这里的超参数C,用来控制误差的度。根据优化函数,就可以看出C的作用了。C越大,样本偏差的影响越大,因此越不容易出现样本偏离。


对偶问题(The dual problem)

拉格朗日函数(Lagrange function)

对于一个约束优化问题,将约束条件移入优化目标,转化为无约束的优化问题。举例来说

\begin{aligned}

&\min_{x, y}&&f(x,y)=x^2 + 2y\\
&\text{subject to}&&3x+2y+1=0

\end{aligned}

将约束条件乘上拉格朗日乘数,移入目标函数,变成新的拉格朗日函数(Lagrange function)

g(x,y,\alpha)=f(x,y)-\alpha(3x+2y+1)

拉格朗日证明,如果(x,y)为约束优化问题的一个解,则必定有一个α,使得(x, y, α)是拉格朗日函数的一个驻点(stationary point,函数在该点的一阶导数为零)。也就是说,计算出拉格朗日函数的驻点,则约束优化问题的解必定在这些驻点中。

\begin{cases}

\frac{\partial}{\partial{x}}g(x, y, \alpha)&= 2x-3\alpha\\
\quad\\
\frac{\partial}{\partial{y}}g(x, y, \alpha)&= 2-2\alpha\\
\quad\\
\frac{\partial}{\partial{\alpha}}g(x, y, \alpha)&= -3x-2y-1

\end{cases} \\
\quad\\
\hat{x}=\frac{3}{2}, \ \hat{y}=-\frac{11}{4}, \ \hat{\alpha}=1

上述的结论,仅可用于相等式的约束。当然,在某些条件下(SVM符合这些条件),可以泛化到不等式。

拉格朗日对偶性(Lagrangian Duality)

假设某不等式约束条件下的优化问题如下定义

\text{min}\ f_0(x)\\
\text{subject to } f_{i}(x) \le 0 \quad \forall i \in 1, ..., m

对应的拉格朗日函数为

L(x, \lambda)=f_0(x) + \sum_{i}\lambda_{i}f_i(x)

为了惩罚违反约束的样本,因此需要这么定义代价函数,当违反约束时代价最大化。

\begin{aligned}
J(x)=
\begin{cases}
f_0(x) &\text{if } f_i(x)\le 0,\\
\infty &\text{otherwise}
\end{cases}
\end{aligned}

因此,当所有的样本都符合约束时,L(x, 0) = f0(x);当有样本违反约束时,设置λ -> ∞,则L(x, 0) -> ∞。

\max_{\lambda}L(x, \lambda) = J(x) \\
\text{prime problem: }\quad\min_{x}\max_{\lambda}L(x, \lambda) \quad\quad\text{代价最小化}

直接求解该问题非常复杂,因此可以调换下顺序,先对x求最小,再对λ求最大。对偶问题定义如下

\begin{aligned}
&\text{dual function: }&&g(\lambda)=\min_xL(x, \lambda)\\
&\text{dual problem: }&&\max_\lambda\min_xL(x, \lambda)=\max_\lambda g(\lambda)
\end{aligned}

L(x, λ)对于x来说是一个仿射函数,而g(λ)又是该函数的极小值,因此对偶函数就是一个凹函数。求解minxL(x, λ)会比较困难,而对凹函数g(λ)求最大值,则会简单得多。

\begin{aligned}
&L(x, \lambda)\le J(x) && \forall\lambda\ge0\\
=>&\min_xL(x, \lambda)=g(\lambda)\le\min_x J(x) := p^*\\
=>&d^*=\max_\lambda g(\lambda)\le p^*
\end{aligned}

d*就是原始问题的最优解,而p*为对偶问题的最优解。从上可以看出,g(λ)为原始问题最优解的下界,因此,对偶问题的求解,就是找到最靠近最优解时的λ值。

\max_\lambda\min_xL(x, \lambda) \le \min_{x}\max_{\lambda}L(x, \lambda)

SVM中的对偶问题

硬间隔分类的拉格朗日函数如下式所示,其中α(i)乘数,称之为KKT乘数,这些乘数必须不小于0。

L(\mathrm{w},b,\alpha)=\frac{1}{2}\mathrm{w}^T\cdot\mathrm{w}-\sum_{i=1}^{m}\alpha^{(i)}(t^{(i)}(\mathrm{w}^T\cdot\mathrm{x}^{(i)}+b)-1)\\
\text{with} \quad \alpha^{(i)}\ge0\quad\text{for}\ i=1,2,...,m

同样,可以求w和b的偏微分,如下式所示

\frac{\partial}{\partial{\mathrm{w}}}L(\mathrm{w},b,\alpha)=\mathrm{w}-\sum_{i=1}^{m}\alpha^{(i)}t^{(i)}\mathrm{x}^{(i)}\\
\frac{\partial}{\partial{b}}L(\mathrm{w},b,\alpha)=-\sum_{i=1}^m\alpha^{(i)}t^{(i)}

求偏微分为0时的驻点,则可以得出

\widehat{\mathrm{w}}=\sum_{i=1}^{m}\hat{\alpha}^{(i)}t^{(i)}\mathrm{x}^{(i)}\\
\sum_{i=1}^m\hat{\alpha}^{(i)}t^{(i)}=0

将上述结果带入之前的拉格朗日函数,则可以得出SVM的对偶问题

\max_{\alpha} L(\mathrm{\widehat{w}},\hat{b},\alpha)= \sum_{i=1}^{m}\alpha^{(i)} - \frac{1}{2}\sum_{i=1}^{m}\sum_{j=1}^{m}\alpha^{(i)}\alpha^{(j)}t^{(i)}t^{(j)}\mathrm{x}^{(i)T}\cdot\mathrm{x}^{(j)}\\
\text{with} \quad \alpha^{(i)}\ge0\quad\text{for}\ i=1,2,...,m

现在目标就是要找到这样的向量α,从而继续求出w和b。

\begin{aligned}
\widehat{\mathrm{w}}&=\sum_{i=1}^{m}\hat{\alpha}^{(i)}t^{(i)}\mathrm{x}^{(i)}\\
t^{(i)}&(\mathrm{w}^{T}\cdot\mathrm{x}^{(i)} + b)=1 \\
\quad\\
&对于样本k\\
\hat{b}&=1-t^{(k)}(\widehat{\mathrm{w}}^{T}\cdot\mathrm{x}^{(k)})\\
&所有样本取均值\\
\hat{b}&=\frac{1}{n_s}\sum_{i=1}^m\left[1-t^{(i)}(\widehat{\mathrm{w}}^{T}\cdot\mathrm{x}^{(i)})\right]\\
&\text{subject to} \  \hat{\alpha}^{(i)}>0

\end{aligned}

Kernelized SVM

前文提到的二项式模型,需要将原始样本集映射到核函数计算后的训练集。一个典型的二项式核函数定义如下

\phi(\mathrm{x})=\phi\bigg(\dbinom{x_1}{x_2}\bigg)
=
\begin{pmatrix}
{x_1}^2\\
\sqrt{2}x_1 x_2\\
x_2
\end{pmatrix}

2维向量空间映射为3维向量空间,如果两个映射后的向量进行点积,结果如下

\begin{aligned}
\phi(\mathrm{a})^T\cdot\phi(\mathrm{b}) &=
{
\begin{pmatrix}
{a_1}^2\\
\sqrt{2}a_1 a_2\\
{a_2}^2
\end{pmatrix}
}^T
\cdot
\begin{pmatrix}
{b_1}^2\\
\sqrt{2}b_1 b_2\\
{b_2}^2
\end{pmatrix}
=
{a_1}^2{b_1}^2+2a_1 b_1 a_2 b_2+{a_2}^2{b_2}^2 \\
&=(a_1 b_1+a_2 b_2)^2 \\
&=\bigg(
\dbinom{a_1}{b_1}^T\cdot\dbinom{b_1}{b_2}
\bigg)^2\\
&=(\mathrm{a}^T\cdot\mathrm{b})^2
\end{aligned}

也就是说映射后的向量点积,等价于原始的向量点积。也就说,将训练集通过核函数映射到高维空间,点积后的结果等价于原始向量的点积。因此就无需映射到高维空间,从而避免了大量的计算,这就是kernel trick的精髓。

K(a, b) = (aT . b)2,就是二项式核。在机器学习中,如果一个函数ϕ具体这样的特性,两个函数的点积结果等价于原始向量的点积,不用实际进行函数的映射,这样的函数称为核函数(kernel)。常用的核函数如下:

\begin{aligned}

线性核:&&K(\mathrm{a},\mathrm{b})&=\mathrm{a}^T\cdot\mathrm{b}\\
多项式核:&&K(\mathrm{a},\mathrm{b})&=(\gamma\mathrm{a}^T\cdot\mathrm{b} + r)^d\\
高斯核:&&K(\mathrm{a},\mathrm{b})&=\text{exp}(-\gamma\|\mathrm{a}-\mathrm{b}\|^2)\\
\text{Sigmoid}核:&&K(\mathrm{a},\mathrm{b})&=\text{tanh}(\gamma\mathrm{a}^T\cdot\mathrm{b}+r)\\

\end{aligned}

将SVM模型用于预测时,通过核函数计算w的时候,ϕ(x(i))的计算量会特别大。利用核函数的特性,可以避免大计算量的运算,原理如下:

\begin{aligned}
h_{\widehat{w}, \hat{b}}(\phi(\mathrm{x}^{(n)}))&=\widehat{\mathrm{w}}^T\cdot\phi(\mathrm{x}^{(n)}) + \hat{b}\\
&=(\sum_{i=1}^m\hat{\alpha}^{(i)}t^{(i)}\phi(\mathrm{x}^{(i)}))^T\cdot\phi(\mathrm{x}^{(n)}) + \hat{b}\\
&=\sum_{i=1}^m\hat{\alpha}^{(i)}t^{(i)}(\phi(\mathrm{x}^{(i)})^T\cdot\phi(\mathrm{x}^{(n)}) + \hat{b}\\
&=\sum_{i=1}^m\hat{\alpha}^{(i)}t^{(i)}K(\mathrm{x}^{(i)}, \mathrm{x}^{(n)}) + \hat{b}\\
&\text{subject to} \  \hat{\alpha}^{(i)}>0

\end{aligned}

α != 0时的样本为支持向量,因此对于x(n)求预测值时,仅需要计算该样本与支持向量的点积,而无需计算全部的训练样本。当然,还需要计算bias term,过程如下

\begin{aligned}

\hat{b} &= \frac{1}{n_s}\sum_{i=1}^m\left[1-t^{(i)}\widehat{\mathrm{w}}^{T}\cdot\phi(\mathrm{x}^{(i)})\right]\\
&= \frac{1}{n_s}\sum_{i=1}^m\left[1-t^{(i)}\bigg(\sum_{j=1}^m\hat{\alpha}^{(j)}t^{(j)}\phi(\mathrm{x}^{(j)})\bigg)^T\cdot\phi(\mathrm{x}^{(i)})\right]\\
&= \frac{1}{n_s}\sum_{i=1}^m\left[1-t^{(i)}\sum_{j=1}^m\hat{\alpha}^{(j)}t^{(j)}K(\mathrm{x}^{(i)},\mathrm{x}^{(j)})\right]\\
&\text{subject to} \  \hat{\alpha}^{(i)}\gt0, \hat{\alpha}^{(j)}\gt0, 

\end{aligned}

发表评论