李宏毅深度学习笔记-SVM支持向量机

什么是支持向量机?

image-20200610100532180

支持向量机有两个特色:

  • 第一个是使用了Hinge Loss(折页损失函数、铰链损失函数)
  • 另一个是最厉害的地方,有个kernel trick(核技巧)

Hinge Loss+kernel trick就是支持向量机

机器学习三个步骤

image-20200610102623385

思考二分类任务,一个机器学习任务的解决过程有三个步骤

现在有一笔标注数据,\(\hat{y}\)用+1,-1表示,代表两个类别。

step1:定义一个函数\(g(x)\),这个\(g(x)\)里有另外一个函数\(f(x)\)\(f(x)>0\)时output就是+1,\(f(x)<0\)时output就是-1。

step2:定义一个很理想的损失函数\(L(f)\),为\(g(x)\)在训练集上犯的错误总和,\(\delta\)的意思是,当\(g=y\)时output=1,\(g \neq y\) 时output=0。

step3:由于损失函数不可微分,优化很困难,因此用一个近似的函数\(l(f(x^n),\hat{y}^n)\)替代\(\delta\)

\(l(f(x^n),\hat{y}^n)\)可以自己随意定。

image-20200610104121003

横轴是\(\hat{y}^n f(x)\) ,纵轴是loss,我们希望\(\hat{y}^n\)为+1时,\(f(x)\)越正,\(\hat{y}^n\)为-1时,\(f(x)\)越负,总体上希望\(\hat{y}^n f(x)\) 越大越好(同号)。原则上,\(\hat{y}^n f(x)\)越大,loss应该越小。

理想的损失函数为\(\delta(g(x^n)\neq \hat{y}^n)\),但是没办法微分:

  • \(\hat{y}^n f(x)\)是负数的话,loss为1
  • \(\hat{y}^n f(x)\)是正数的话,loss为0

近似的损失函数为\(l(f(x^n),\hat{y}^n)\) ,上图纵轴就是\(l(f(x^n),\hat{y}^n)\)的值,\(l()\)可以选择各种不同的函数

理想损失函数的图像如上图黑色线所示

Square Loss

image-20200610110015772

例如希望当\(\hat{y}^n=1\)时,\(f(x)\)越接近于1,\(\hat{y}^n=-1\)时,\(f(x)\)越接近于-1,这个就是均方误差,可以写成\(l(f(x^n),\hat{y}^n)=(\hat{y}^nf(x^n)-1)^2\)

  • \(\hat{y}^n=1\)变为\((f(x^n)-1)^2\),意味着\(f(x^n)\)越接近1越好。

  • \(\hat{y}^n=-1\)变为\((-f(x^n)-1)^2=(f(x^n)+1)^2\),意味着\(f(x^n)\)越接近-1越好。

\(l(f(x^n),\hat{y}^n)\)的变化如上图红色曲线,这个是不合理的,说过\(\hat{y}^n f(x)\)越大,loss应该越小。

Sigmoid+Square Loss

image-20200610132245254

Sigmoid函数用一个\(\sigma\)表示,可以写成式子\(l(f(x^n),\hat{y}^n)=(\sigma(\hat{y}^nf(x))-1)^2\)

  • \(\hat{y}^n=1\)时变为\((\sigma(f(x))-1)^2\),意味着\(\sigma(f(x))\)接近于1越好。

  • \(\hat{y}^n=-1\)时变为\((\sigma(-f(x))-1)^2=(1-\sigma(f(x))-1)^2\),意味着\(\sigma(f(x))\)接近于0越好。

\((\sigma(\hat{y}^nf(x))-1)^2\)的图像为蓝色曲线

Sigmoid+cross entropy

image-20200610141852433

之前说过在logistic回归里不会使用Square Loss作为loss,而是使用交叉熵。交叉熵的意思是分布\(\sigma(f(x))\)和分布ground truth之间的差异,那么目标就是最小化交叉熵。

交叉熵损失的式子为:\(\large l(f(x^n),\hat{y}^n)=ln(1+exp(-\hat{y}^nf(x)))\)

这个式子是不是合理的?

是合理的:

\(\hat{y}^n\)乘上\(f(x)\)接近于无穷大时,\(exp(-\hat{y}^nf(x))=0\),那么\(ln(1+0)=0\)\(\hat{y}^nf(x)\)越大,损失越小

\(\hat{y}^n\)乘上\(f(x)\)接近于负无穷大时,\(exp(-\hat{y}^nf(x))\)为无穷大,那么\(ln(1+无穷大 )\) 还是无穷大

交叉熵的图像是上图绿色的线,上图里对Loss除了\(ln(2)\)(不会影响最优解),除以\(ln(2)\)可以让交叉熵损失变为ideal 损失的上界。想法就是既然没办法直接最小化ideal 损失,那就最小化它的上界交叉熵损失/\(ln(2)\) ,进而间接最小化ideal 损失。

Square Loss和cross entropy的对比

现在可以知道为什么使用cross entropy而不是Square Loss作为损失函数

如果把\(\hat{y}^nf(x)\)从-2移到-1,对sigmoid函数来说:

  • sigmoid+square error的变化很小,照理说在值非常负的时候,要有很大的梯度,要赶快调整值,但使用square error发现,调整值对total loss影响不大,没有太多回报,以至于不想调整非常负的值

  • sigmoid+cross entropy的变化很大,调整值可以得到回报,就会很乐意把非常负的值往正的地方推。

所以使用cross entropy更容易训练

hinge loss

image-20200611204920242

hinge loss是一个很特别的式子,写成\(\large l(f(x^n),\hat{y}^n)=max(0,1-\hat{y}^nf(x))\)

  • 如果\(\hat{y}^n=1\),loss 函数就是\(max(0,1-f(x))\),只要\(1-f(x)<0\),即\(f(x)>1\),那么loss就是0

  • 如果\(\hat{y}^n=-1\),loss 函数就是\(max(0,1+f(x))\),当\(1+f(x)<0\),即\(f(x)<-1\),loss为0

对一个正例来说,如果\(f(x)>1\),那么\(f(x)\)就是一个正确的值

对一个负例来说,如果\(f(x)<-1\),那么\(f(x)\)是一个正确的值

把hinge loss画出就像上图紫色线,会发现只要\(\hat{y}^n f(x)>1\),loss就已经是0了,而且根据step1得到的函数就已经能够分类的比较正确了(\(\hat{y}^n\)\(f(x)\)同向,\(\hat{y}f(x)>0\))。但在hinge loss看来还不够好,\(0<\hat{y}^n f(x)<1\)那一段损失还是大于0,这促使机器在那一段让\(\hat{y}^n f(x)\)大于1。

为什么max里是1?

是1的话,hinge loss才会是ideal loss的一个合适的上界,用其他值的话可能联系不紧密。所以我们最小化hinge loss,就可能可以间接最小化ideal loss。

hinge loss和cross entropy 对比

最大的不同在于对已经分类正确的样本的态度,如果把\(\hat{y}^n f(x)\)从1挪到2

  • 对cross entropy 来说损失会下降,那么cross entropy就会想要更好,让\(\hat{y}^n f(x)\)变得更大进而减少loss
  • 对hinge loss来说及格就好,只要\(\hat{y}^n f(x)>1\)就结束

在实际应用上这两个损失差别没有很显著,有些时候可以看到hinge loss略胜一筹,但也没有很多。hinge loss有一个优势是不太在意离群值,学习的结果比较鲁棒,因为及格就好就不会有太大反应。

Linear SVM

什么是线性SVM

image-20200611214831126

step1:

现在的函数是线性的,为\(\large f(x)=\sum\limits_{i}w_ix_i+b\),把1看成\(x_0\),式子可以变为\(\large f(x)=\sum\limits_{i}w_ix_i+bx_0\)把这个式子看成是两个向量\(\begin{bmatrix} w \\ b \\ \end{bmatrix},\)\(\begin{bmatrix}x \\ 1 \end{bmatrix}\)的内积,最后就是\(w^Tx\)。在SVM里就说\(f(x)>0\)时属于哪一个class,\(f(x)<0\)时属于另外一个class。

step2:

SVM使用了hinge loss作为损失函数,通常还会加上一个正则化项。这个hinge loss是凸函数,\(\large l(f(x^n),\hat{y}^n)=max(0,1-\hat{y}^n f(x))\)很像ReLU激活函数,而L2的正则化也是一个凸函数,把两个凸函数叠加起来仍然是凸函数

step3:

如果损失函数是凸函数,那么在梯度下降时,不管初始值在哪里,都可以达到最优点。hinge loss在某些点不可微(菱菱角角的地方),把很多不可微的凸函数叠起来就会变成上图紫色曲线一样,有很多菱菱角角的地方。但这不是大问题,比如讲ReLU的时候,有不可微的点,但是可以做梯度下降。

step1的函数不是一定要线性的,只不过线性有很多好的特性,不是线性的也是可以用梯度下降学习的,所以SVM是有deep版本的。在做深度学习的时候,不是用交叉熵损失,而是用hinge loss,那么就是deep版本的SVM。

logistic和线性SVM的差别

唯一的差别是损失函数,线性SVM是hinge loss,logistic回归是交叉熵损失。

使用梯度下降训练SVM

image-20200612101652829

虽然大多数时候,我们不是用梯度下降来学习SVM,但是的确用梯度下降也是可以的。 有一个用梯度下降训练SVM的方法叫做Picasso。

假如损失函数为\(L(f)\),用的hinge loss,梯度下降只要损失函数能微分就可以用。

\(w_i\)做偏微分,\(w_i\)只跟\(f(x)\)有关,\(\large \frac{\partial f(x^n)}{\partial w_i}=x_i^n\)

\(l(f(x^n),\hat{y}^n)\) 是hinge loss函数,长得跟ReLu很像,图像如上图右边紫色线(\(\hat{y}^nf(x^n)\)为横坐标),\(f(x)\)的值取决于现在的model \(w\)是多少。

  • 如果\(1-\hat{y}^nf(x^n)>0\),那么model作用在紫色线左边斜线部门,对\(f(x^n)\)的微分为\(-\hat{y}^n\)

  • 在紫色线右边部分,对\(f(x^n)\)的微分为0

\(L(f)\)\(w_i\)的偏微分为上图最下方式子,\(\large -\delta(\hat{y}^nf(x^n)<1)\hat{y}^n\)取决于model现在的参数是什么, 可以写为\(\large c^n(w)\),然后使用梯度更新参数。

image-20200612123959628

平常的SVM公式

把hinge loss用\(\large \epsilon^n\)替换,\(\large \epsilon^n=max(0,1-\hat{y}^nf(x))\),只是换了一下符号,目标是最小化total loss。

不考虑最小化这件事,条件\(\begin{matrix} \epsilon^n \geq 0 \\ \epsilon^n \geq1-\hat{y}^nf(x) \\ \end{matrix}\) \(\neq\)\(\epsilon^n=max(0,1-\hat{y}^nf(x))\)),如果max条件里最大的是0,前一个条件下可以取1,2......(理论上可以取大于等于0的任何值),显然\(\epsilon^n\)取值不同。

但考虑最小化后,条件\(\begin{matrix} \epsilon^n \geq 0 \\ \epsilon^n \geq1-\hat{y}^nf(x) \\ \end{matrix}\) \(=\)\(\epsilon^n=max(0,1-\hat{y}^nf(x))\)),因为加了最小化条件,所以\(\epsilon^n\)是所有可能取值里最小的。

例如:

  • \(\epsilon^n=max(0,1-\hat{y}^nf(x))\)条件下,\(\epsilon^n=0\),意味着 \(0 > 1-\hat{y}^nf(x))\),那么\(\begin{matrix} \epsilon^n \geq 0 \\ \epsilon^n \geq1-\hat{y}^nf(x) \\ \end{matrix}\)应该取\(\epsilon^n \geq 0\),取最小值就是0

  • \(\epsilon^n=max(0,1-\hat{y}^nf(x))\)条件下,\(\epsilon^n=1-\hat{y}^nf(x)\),意味着\(0 < 1-\hat{y}^nf(x))\),那么\(\begin{matrix} \epsilon^n \geq 0 \\ \epsilon^n \geq1-\hat{y}^nf(x) \\ \end{matrix}\)应该取\(\epsilon^n \geq1-\hat{y}^nf(x)\),最小值是\(\epsilon^n=1-\hat{y}^nf(x)\)

上图下面红框的式子就是我们熟悉的SVM,告诉我们\(\hat{y}^n\)\(f(x)\)要同号,相乘后要大于等于1(一个间隔),但是间隔是软的,有时候没办法让\(\hat{y}^nf(x) \geq 1\),那么把间隔放宽一点变成\(1-\epsilon^n\)\(\epsilon^n\)(松弛变量)必须大于等于0,\(< 0\)是把间隔变大,我们的目的是变小。

最后变成,要最小化的目标函数,加上一些约束条件(\(\epsilon^n\)的约束)。这是一个二次规划问题(最小化、最大化的同时有约束条件)。

SVM的核方法

image-20200612134527203

Kernal方法里,最容易困惑的地方是要先明白实际上找出来的权重是所有数据的线性组合。一般证明的方法都是用拉格朗日乘子法(利用拉个朗日对偶性)。这里用另一个角度证明。

之前说过可以用梯度下降来最小化SVM,计算出梯度为\(\large \sum\limits_{n}c^n(w)x_i^n\),权重更新式子为\(\large w_i \leftarrow \eta \sum\limits_{n}c^n(w)x_i^n\)。假设有\(w\)有k维,更新的式子如上图左下方所示。

写成向量形式,\({\bf{w}}=\begin{bmatrix} w_1\\w_2\\ \vdots \\ w_k \\ \end{bmatrix}\)\({\bf{x^n}}=\begin{bmatrix} x_1^n\\x_2^n\\ \vdots \\ x_k^n \\ \end{bmatrix}\)\(\large {\bf{w}}\leftarrow {\bf{w}}-\eta \sum\limits_n c^n({\bf{w}}){\bf{x}^n}\)

假设\({\bf{w}}\)的初始化是一个0向量,那么每次更新的时候,都是加上所有数据的线性组合,那么最后解出来的\(w\)

就是\({\bf{x^n}}\)的线性组合。

\(\large c^n(w)=\frac{\partial l(f(x^n),\hat{y}^n)}{\partial f(x^n)}\),使用hinge loss时,如果作用在max=0的区域,那么微分\(\large c^n(w)\)就是0,而往往微分算出来就是0,也就是不是所有的\({\bf{x^n}}\)都会被加到\({\bf{w}}\)里去。那么最后解出来\({\bf{w}}^*\),线性组合的权重可能是稀疏的,可能很多的数据对应的\(\alpha^*=0\),而\(\alpha^* \neq 0\)的数据点\({\bf{x^n}}\) 就是支持向量。

不是所有的点都会被选为支持向量的,只有少数的点,所以SVM相较于其他方法是鲁棒的。像logistic选的是交叉熵损失,就没有稀疏的特性,交叉熵损失在每个地方的微分都不等于0,解出来的\(\alpha^*\)就不会是稀疏的。

只有支持向量才会对参数有影响,其他数据点对model没有任何影响。

image-20200612144429164

\(w\)写成是数据点的线性组合,最大的好处是可以使用核技巧。想法是这样的,我们知道\(w\)是数据点的线性组合,写成矩阵形式就是\(w={\bf{X} }{\bf{\alpha}}\)\({\bf{X}}=({\bf{x^1,x^2,...,x^N}})\),这里的每个\({\bf{x}}\)都是一个向量,\({\bf{\alpha}}=\begin{bmatrix} \alpha_1 \\ \alpha_2 \\ \vdots \\ \alpha_N \end{bmatrix}\)

那么\(f(x)={\bf{w^T x}}\)可以改写为\(f(x)={\bf{\alpha}^T}{\bf{X}^T}{\bf{x}}= \begin{bmatrix} \alpha_1 & \alpha_2 & \cdots & \alpha_N \end{bmatrix} \begin{bmatrix} {\bf{x^1 \cdot x\\ x^2 \cdot x \\ \vdots \\ x^N \cdot x}} \end{bmatrix}=\sum\limits_n \alpha_n ({\bf{x^n \cdot x}})\)

\(f(x)\)怎么算,把\(\bf{x}\)代进来,和数据集里的每一个数据\(\bf{x^n}\) 做内积,在求和\(\alpha_n\)的乘积和。如果使用的是hinge loss,那么\(\alpha^n\)就是稀疏的,所以只要和支持向量做计算就可以了,不会和所有数据点做内积。

\({\bf{x^n \cdot x}}\)写成一个函数\(K({\bf{x^n,x}})\)表示内积,这个函数就是核函数。

image-20200612154655549

step1是写成把\({\bf{x^n,x}}\)代进核函数,再乘以\(\alpha_n\)的乘积和的形式,这个model里未知的是\(\alpha_n\)

在step2和3,就是找一组最好的\(\{\alpha_1^*,...,\alpha_n^*,...,\alpha_N^*\}\)来最小化损失函数L

损失函数为\(\large L(f)=\sum\limits_n l(f(x^n),\hat{y}^n)=\sum\limits_n l(\sum\limits_{n'} \alpha_{n'}K(x^{n'},x^n),\hat{y}^n)\)\(l()\)函数里的两个input是\(f(x^n)\) (step1的函数)和target \(\hat{y}^n\)

看损失函数的式子可以知道,我们现在不需要知道向量\({\bf{x}}\),只需要知道\({\bf{x}}\)和另外一个向量\({\bf{z}}\)的内积,或者说只要知道核函数就可以做所有的优化。并不需要去知道\(x^{n'},x^n\)长什么样子,只需要知道\(K(x^{n'},x^n)\)的值是什么,能算出来就行。

核技巧不只是局限在SVM上,logistic的函数也是\(w\)和数据的线性组合,所有也有基于核技巧的logistic回归。线性回归也可以用同样的方法,所以也有基于核技巧的线性回归。

image-20200612161134899

怎么使用核技巧?

之前讲过使用线性的模型有很多的限制,比如要对input的特征做特征转换之后才可以让线性模型处理。在神经网络里就用了好几个隐藏层在做特征转换。

假设现在有一笔二维的数据,要先对它做特征转换,再使用线性SVM。假设特征转换结果是\(\phi(x)=\begin{bmatrix} x_1^2 \\ \sqrt{2}x_1x_2 \\ x_2^2 \\ \end{bmatrix}\),即想要考虑\(x_1,x_2\)之间的关系。现在核函数\(K(x,z)\),是计算\(x,z\)经过特征转换后的向量内积,最简单的算法是先把\(x,z\)代到特征转换函数里,变成新的特征后,再计算内积,算出来的结果如上图右下方。

计算公式可以简化,\(\phi(x) \cdot \phi(z)=(x \cdot z)^2\),所以说对\(x,z\)做特征转换再做内积,等同于在原来特征空间上先做内积再平方。这招有时候会有好处,有时候直接使用核函数计算会比先做特征转换再做内积快。

image-20200612163659134

举个例子:

\(x,z\)现在都是高维向量,做特征转换是投影到更高维的平面,在更高维平面里会考虑所有特征两两之间的关系。假设原始\(x,z\)是k维,那更高维的维度是\(k+C_k^2\)

如果使用核函数,可以很容易计算\(\phi(x)\)\(\phi(z)\)的内积,就是计算\(x,z\)的内积(k个元素相乘)再取平方。

如果先做特征转换再做内积,由于维度很高,计算量会比核函数的大。

Radial Basis Function Kernel (径向基函数核)

image-20200612193156053

\(K(x,z)\)等于\(x\)\(z\) 的距离乘上\(-\frac{1}{2}\),再取exp。式子在衡量\(x,z\) 的相似度,越像核函数的值越大,\(x=z\) 的话值为1,完全不一样则值为0。

\(K(x,z)\)也可以化成两个高维向量做内积的形式,其实这两个高维向量是无穷多维,把一个\(x\)转到无穷多维再做内积,根本做不到,但是先求\(x\)\(z\) 的距离再乘上\(-\frac{1}{2}\)取exp则可以计算。

为什么径向基函数核相当于两个无穷多维向量的内积?

\(exp(-\frac{1}{2}||x-z||_2)\),化为\(C_xC_zexp(x\cdot z)\)\(x\)的2范式用\(C_x\)表示(只与x有关),\(z\)的2范式用\(C_z\)表示(只与\(z\)有关),对\(exp(x\cdot z)\)做泰勒展开得到上图展开后的式子。

  • \(C_x C_z\)可以看成是两个只有一个维度的向量的内积
  • \(C_xC_z(x\cdot z)\)可以看成\(x\)乘上\(C_x\)\(z\)乘上\(C_z\)再做内积
  • \(x ,z\)内积的平方相当于两个高维向量的内积,高维向量会考虑\(x,z\)内两两维度的关系,如果是三次方,就会考虑三三维度的关系

现在把属于\(x\)的向量都串起来(如上图红色线),把属于\(z\)的向量也串起来,因为泰勒展开后有无穷多项,所以串起来后\(x,z\)各自都有无穷长的向量,最后这两个无穷多向量做内积的结果就是核函数的结果。

所以使用RBF核,相当于在无穷多维的平面上做事情,可以想象是很容易过拟合的。

Sigmoid Kernel

image-20200612200448765

核函数为\(K(x,z)=tanh(x\cdot z)\),只与\(tanh(x\cdot z)\)是哪两个高维向量内积的结果,自己用泰勒展开了解。

在用\(x\)做test代到\(f\)里面的时候,其实是在计算与所有训练集数据\(x^n\)核函数的值再乘上\(\alpha_n\) 之和。用Sigmoid Kernel的时候,就是\(x\)与所有训练数据\(x^n\)的内积做tanh()再乘上\(\alpha_n\)之和。

Sigmoid Kernel的\(f(x)\)可以想成是一个只有一层隐藏层的神经网络。把\(x\) input,会跟所有的\(x^n\)做内积再通过tanh()。就像是一个神经网络的input是\(x\),隐藏层权重是\(x^n\) ,通过激活函数tanh()得到output,再乘上\(\alpha_n\) ,最后加起来得到\(f(x)\)

注意,上图的\(\alpha_n\),n是下标

神经元里每一个权重就是一个数据点,有几个支持向量就有几个神经元。

自己设计核

image-20200612202149212

既然有了核技巧,那就可以直接设计核函数\(K(x,z)\),可以不用理会\(x,z\)长什么样子,只要\(K(x,z)\)里代入\(x,z\)能得到一个值,这个值代表\(x,z\)转换后的高维向量的内积。

什么时候

假设\(x\)是有结构的数据,比如是一个sequence,如果sequence长度不一样,那就不容易表示为一个向量,也就不知道\(x\)长什么样子,也不知道\(\phi(x)\)是什么样子。

但是可以直接定核函数,核函数就是投影到高维以后的内积(被投影向量长度乘以投影长度),所以核函数往往就是一个类似相似度的东西。如果今天定义一个函数,可以评估\(x,z\)的相似度,就算\(x,z\)是有结构的数据,比如树形结构,就算是序列也没关系,只要知道如何计算两个树形结构数据或两个序列的相似度,就可以把相似度作为核来使用。

不是所有相似度函数都可以作为核,但是有一个叫Merce’ theory可以告诉你哪些函数是可以的,所以有办法验证核函数是否会有两个高维向量做内积。

在语音上,假设分类对象是音频段,每个音频段用向量序列表示。每个音频段长度不一样,所以向量序列的长度可能不一样。比如一个分类任务是给你一段声音讯号,判断说话者的情绪,可能分成高兴、生气等等之类的。想用SVM,但是一段声音讯号没办法直接用一个向量来描述,怎么办呢?不管声音讯号变成向量后是什么样子,你都可以直接定核\(K(x,z)\) ,来表明 input 一段声音讯号\(x\)和另外一段声音讯号\(z\)后,output应该是什么。

怎么定两个sequence之间的kernel?

reference在上图最下方。

SVM的其它变种

image-20200612204513282

现在SVM还有很多变种,比如用SVM做回归(SVR) ,回归是要求model的output和target越近越好,那做SVR的话,进入到target某一个距离里面loss就为0。

Ranking SVM被用在要考虑的东西是一个排序list的时候。

One-class SVM是说,正例的样本自称一类,负例就散布在其他地方。

深度学习和SVM的区别

image-20200612204921480

深度学习的隐藏层可以看成是特征转换,输出层可以看成是线性分类器。

SVM也是做类似的事情,先用一个核函数,把特征转换到高维空间上,再在高维空间使用线性分类器,线性分类器的损失函数一般使用hinge loss。

事实上,SVM的核是可学习的,但是没办法学得像深度学习那样多,可以做的事情是有好几个不同的核,把不同核结合起来,中间的权重是可以学习的。当只有一个核时,SVM就像是只有一层隐藏层的神经网络,把核做线性组合时,就像是有2层隐藏层的神经网络。

posted @ 2020-06-12 20:59  yueqiudian  阅读(1741)  评论(0编辑  收藏  举报