机器学习笔记(十)——入门支持向量机(SVM)
一、SVM原理与模型数学推导
支持向量机,SVM(Support Vector Machine),其实就是一个线性分类器。在最初接到这个算法时,我们可能会一头雾水:这个名词好奇怪[问号脸],怎么“支持”?什么“向量”,哪来的“机”?
(一)由决策边界开始
1 分类中的“不适定问题”
首先,我们看一个简单的二分类问题。在二维的特征平面中,所有的数据点分为了两类:蓝色圆形和黄色三角。我们的目标是找到了一条决策边界,将数据分类。但实际上我们可以找到多条决策边界。
这就所谓的“不适定问题”。“不适定问题”会影响模型的泛化性。比如在下面的模型中,被黄色箭头标出的点被决策边界划为蓝色圆点,但实际上它和黄色三角更近一些。也就说决策边界的选择,不仅要考虑已经存在的数据上的是否分类正确,还要考虑是否能够更好地划分未出现的测试数据:
逻辑回归算法如何解决“不适定问题”问题呢?首先定义一个概率函数sigmoid函数:
σ(t)=11+e−tσ(t)=\frac {1}{1+e^{-t}}σ(t)=1+e−t1
然后根据概率函数进行建模:
P(Y=1)=11+e−θT⋅XbP(Y=1)=\frac{1}{1+e^{-θ^T\cdot X_b}}P(Y=1)=1+e−θT⋅Xb1
建立损失函数:
J(θ)=−1m∑i=1my(i)log(σ(θT⋅Xb(i)))+(1−y(i))log(1−σ(θT⋅Xb(i)))J(θ)=-\frac{1}{m}\sum_{i=1}^my^{(i)}log(σ(θ^T\cdot X_b^{(i)}))+(1-y^{(i)})log(1-σ(θ^T\cdot X_b^{(i)}))J(θ)=−m1i=1∑my(i)log(σ(θT⋅Xb(i)))+(1−y(i))log(1−σ(θT⋅Xb(i)))
最小化损失函数,从而求出一条决策边界(线性):
x2=−θ0−θ1x1θ2x_2=\frac{-θ_0-θ_1x_1}{θ_2}x2=θ2−θ0−θ1x1
(以上内容逻辑回归算法)
也就说,逻辑回归的损失函数完全是由训练数据集确定的。
2 SVM中的决策边界
支撑向量机如何解决“不适定问题呢”?SVM要找到一条泛化性比较好的决策边界,就是这条直线要离两个分类都尽可能的远,我们认为这样的决策边界就是好的:
如上图所示:在上面的两个类别中,离决策边界最近的点到决策边界的距离尽可能地远。
那也就是说,我们可以忽略其他大部分的数据点,只关注这几个特殊的点即可。
(二)Support Vector & Margin
1 定义及思想
将最优决策边界向上&下平移,在遇到第一个点时停下来,这个点被称为支撑向量Support Vector;支撑向量到决策边界的距离是d;这两条平移后的直线的间隔(2d)被称为最大间隔Margin。
支撑向量就是支撑着两条平移边界的点,我们只需要重点研究这几个支撑向量即可,这也是SVM名称的由来;Margin就是分界面可以移动的范围,范围越大表示容错能力越强。
所以我们可以看到,所谓的支撑向量机,最初就是一个线性分类器,只不过这个线性分类器不仅能把样本分对,可以最大化Margin。
到目前为止,我们就将SVM转换为了一个最优化问题,下面的工作就是求出Margin的数学表达式,即将支撑向量机思想转化为数学问题。
2 转化为最优化问题(核心)
回忆解析几何的知识,点(x ,y)到直线Ax+By+C=0Ax+By+C=0Ax+By+C=0的距离:
d=∣Ax+By+C∣A2+B2d=\frac {|Ax+By+C|}{\sqrt{A^2+B^2}}d=A2+B2∣Ax+By+C∣
扩展到n维空间:x点ωTx+b=0ω^Tx+b=0ωTx+b=0到(其中ω是n维向量,b是截距)的距离为:
d=ωTx+b∣∣ω∣∣,∣∣ω∣∣=ω12+ω22+...+ωn2+d=\frac{ω^Tx+b}{||ω||},||ω||=\sqrt{ω_1^2+ω_2^2+...+ω_n^2+}d=∣∣ω∣∣ωTx+b,∣∣ω∣∣=ω12+ω22+...+ωn2+
然后我们去找决策边界的表达式:
求出在满足下面的条件下,ω的值是多少。
{ωTx(i)+b≥1∀y(i)=1ωTx(i)+b≤−1∀y(i)=−1\left\{\begin{matrix} ω^Tx^{(i)}+b\geq 1 & \forall y^{(i)}=1\\ ω^Tx^{(i)}+b\leq -1 & \forall y^{(i)}=-1\end{matrix}\right.{ωTx(i)+b≥1ωTx(i)+b≤−1∀y(i)=1∀y(i)=−1
我们将上面的两个式子进行合并,即可以将y(i)y^{(i)}y(i)提到前面去。这样,支撑向量机的所有数据点都要满足下面的式子:
y(i)(ωTx(i)+b)≥1y^{(i)}(ω^Tx^{(i)}+b)\geq 1y(i)(ωTx(i)+b)≥1
对于任意支撑向量点x到决策边界的距离为d,我们要最大化Margin,将前面的式子带入后得到max2∣ωTx(i)+b∣∣∣ω∣∣max\frac{2|ω^Tx^{(i)}+b|}{||ω||}max∣∣ω∣∣2∣ωTx(i)+b∣,也就是max2∣∣ω∣∣max\frac{2}{||ω||}max∣∣ω∣∣2。即相当于最小化min12ωTωmin\frac{1}{2}ω^Tωmin21ωTω。
OK,现在我们已经得到了SVM的最优化问题:
Φ(x)=12ωTωΦ(x)=\frac{1}{2}ω^TωΦ(x)=21ωTω s.t. y(i)(ωTx(i)+b)≥1y^{(i)}(ω^Tx^{(i)}+b)\geq 1y(i)(ωTx(i)+b)≥1
即最优化的目标函数为min12ωTωmin\frac{1}{2}ω^Tωmin21ωTω,还要有限定条件(s.t.subjecttto,s.t. subjecttto,s.t.subjecttto,受
限制于):所有数据满足y(i)(ωTx(i)+b)≥1y^{(i)}(ω^Tx^{(i)}+b)\geq 1y(i)(ωTx(i)+b)≥1
我们发现,SVM的最优化问题是有限制条件的,与之前接触的没有限制条件的全局最优化问题的计算方法很不同。
(三)求解有条件限制的最优化问题
1 数学推导
通过六步数学推导,求解有条件限制的最优化问题。如果觉得吃力,大家可以仅仅了解推导过程,记住结果即可。
第一步:给出表达式
对于有约束条件的最优化问题,用拉格朗日乘数法来解决,得到(aia_iai是拉格朗日系数):
Lp=12∣∣ω∣∣2−∑i=1laiyi(ωT⋅xi+b)+∑i=1laiL_p=\frac{1}{2}||ω||^2-\sum_{i=1}^la_iy_i(ω^T\cdot x_{i}+b)+\sum_{i=1}^la_iLp=21∣∣ω∣∣2−i=1∑laiyi(ωT⋅xi+b)+i=1∑lai
此时,我们要求LpL_pLp基于ω,b的极小值。
第二步:求导
我们对ω,b进行求导,可以得到两个式子:
∂Lp∂ω=0⇒ω=∑i=1laiyixi\frac{\partial L_p}{\partial ω}=0\Rightarrow ω=\sum_{i=1}^l{a_iy_ix_i}∂ω∂Lp=0⇒ω=i=1∑laiyixi
∂Lp∂b=0⇒∑i=1laiyi=0\frac{\partial L_p}{\partial b}=0\Rightarrow \sum_{i=1}^la_iy_i=0∂b∂Lp=0⇒i=1∑laiyi=0
从上两式子可以看出,我们已经求得了ω和a的关系,只要后面接着能够求出优化函数极大化对应的ω,就可以求出ω了,至于b,由于上两式已经没有b,所以最后的b可以有多个。
第三步:转换对偶问题
将ω,b的求导结果带回到原式LpL_pLp中,得到新的目标函数LDL_DLD:
LD≡∑i−12∑i,jaiajyiyjxi⋅xjL_D\equiv \sum_i-\frac{1}{2}\sum_{i,j}a_ia_jy_iy_jx_i\cdot x_jLD≡i∑−21i,j∑aiajyiyjxi⋅xj
≡∑i−12aTHa\equiv \sum_i-\frac{1}{2}a^TH_a ≡i∑−21aTHa
whereHi,j=yiyjxi⋅xjwhere H_{i,j}=y_iy_jx_i\cdot x_jwhereHi,j=yiyjxi⋅xj
s.t∑iaiyi=0s.t \sum_ia_iy_i=0s.t∑iaiyi=0 & ai≥0a_i\geq 0ai≥0
其实LDL_DLD和LPL_PLP是对偶问题。我们可以通过拉格朗日对偶将优化问题转化为等价的对偶问题来求解,原问题和对偶问题在一般情况下是不等价的,但是在SVM中是等价的。
第四步:求a
把LDL_DLD方程解出来,会得到很多a,大部分都为0,少部分非0,就是支撑向量。
第五步:求ω
我们将所有非零的支撑向量相乘并累加起来,最终得到ω=∑i=1laiyixi⋅xω=\sum_{i=1}^la_iy_ix_i\cdot xω=∑i=1laiyixi⋅x。
这里要注意,两个向量做内积,是SVM运算的精华所在。
第六步:求b
已知ys(xs⋅ω+b)=1y_s(x_s\cdot ω +b)=1ys(xs⋅ω+b)=1,将ω 的结果带入,并且在两侧同时乘以ysy_sys后得到:ys2(∑m∈Samymxm⋅xs+b)y_s^2(\sum_{m \in S}a_my_mx_m\cdot x_s + b)ys2(∑m∈Samymxm⋅xs+b),则得到b:
b=1N∑m∈S(ys−∑m∈Samymxm⋅xs)b=\frac{1}{N}\sum_{m \in S}(y_s-\sum_{m \in S}a_my_mx_m\cdot x_s)b=N1m∈S∑(ys−m∈S∑amymxm⋅xs)
2 SVM如何求解示例
通过一个简单的例子,展示SVM如何求解。有两个样本:
通过约束条件:∑i=1laiyi=0\sum_{i=1}^la_iy_i=0∑i=1laiyi=0,可以得到:
∑i=12aiyi=0⇒a1−a2=0⇒a1=a2\sum_{i=1}^2a_iy_i=0 \Rightarrow a_1-a_2=0 \Rightarrow a_1=a_2i=1∑2aiyi=0⇒a1−a2=0⇒a1=a2
我们要优化的表达式为:LD=∑iai−12aTHaL_D=\sum_ia_i-\frac{1}{2}a^TH_aLD=∑iai−21aTHa。需要先求出H.
将a带入到矩阵H中,已知:Hi,j=yiyjxi⋅xjH_{i,j}=y_iy_jx_i\cdot x_jHi,j=yiyjxi⋅xj;则有:
H=[H11H12H21H22]=[2000]H=\begin{bmatrix} H_{11} & H_{12}\\ H_{21} & H_{22} \end{bmatrix}=\begin{bmatrix} 2 & 0\\ 0 & 0 \end{bmatrix}H=[H11H21H12H22]=[2000]
带入到表达式中,得到:
LD≡∑i=12ai−12[a1,a2]H[a1a2]=2ai−a12L_D\equiv \sum_{i=1}^2a_i-\frac{1}{2}[a_1,a_2]H\begin{bmatrix} a_1\\ a_2 \end{bmatrix}=2a_i-a_1^2LD≡i=1∑2ai−21[a1,a2]H[a1a2]=2ai−a12
则表达式LDL_DLD的最大值为:a1=1,a2=1a_1=1,a_2=1a1=1,a2=1。
带回到ω中则可以得到:ω=∑i=12aiyixi=[1,1]ω=\sum_{i=1}^2a_iy_ix_i=[1,1]ω=∑i=12aiyixi=[1,1];计算b:b=−ωx1+1=−2+1=−1b:b=-ωx_1+1=-2+1=-1b:b=−ωx1+1=−2+1=−1。
最终得到判决平面为:g(x)=ωx+b=x1+x2−1g(x)=ωx+b=x_1+x_2-1g(x)=ωx+b=x1+x2−1;Margin为M=2∣∣ω∣∣=2M=\frac{2}{||ω||}=\sqrt 2M=∣∣ω∣∣2=2
(四)小结
SVM算法其最核心的思想就是从Input Space向更高维的Feature Space的映射,进行有Margin的线性分类。
二、软间隔与sklearn中的SVM
(一)Soft Margin
1. 为何需要Soft Margin
在线性可分问题中,对于样本点来说,存在一根直线可以将样本点划分,我们称之为Hard Margin SVM;但是(同样线性不可分),有时候会出现不那么完美,样本点会有一些噪声或者异常点,并不能完全分开。即没有一条直线可以将样本分成两类。那么就提出了Soft Margin SVM。
2. Soft Margin的思想
Soft Margin SVM的思想也很朴素,就是在Hard Soft的基础上,将原来的约束条件放宽一些。增加容错性。
在Hard Soft中的约束条件为:
Φ(x)=12ωTωs.t.y(i)(ωTx(i)+b)≥1Φ(x)=\frac{1}{2}ω^Tω \; \; s.t. \; \; y^{(i)}(ω^Tx^{(i)}+b)\geq 1Φ(x)=21ωTωs.t.y(i)(ωTx(i)+b)≥1
对于限制条件y(i)(ωTx(i)+b)≥1y^{(i)}(ω^Tx^{(i)}+b)\geq 1y(i)(ωTx(i)+b)≥1,形象地说,Margin区域里必须是任何数据点都没有,所有的数据点都必须在y(i)(ωTx(i)+b)=1y^{(i)}(ω^Tx^{(i)}+b)=1y(i)(ωTx(i)+b)=1与y(i)(ωTx(i)+b)=−1y^{(i)}(ω^Tx^{(i)}+b)=- 1y(i)(ωTx(i)+b)=−1两条直线的外侧。
如果有些数据点不能满足这个要求,就对条件加以宽松,在margin区域外给他一个宽松量(大于等于0):
Φ(x)=12ωTωs.t.y(i)(ωTx(i)+b)≥1−ζiΦ(x)=\frac{1}{2}ω^Tω \; \; s.t. \; \; y^{(i)}(ω^Tx^{(i)}+b)\geq 1-ζ_iΦ(x)=21ωTωs.t.y(i)(ωTx(i)+b)≥1−ζi
但是我们很容易地想到:容错空间ζi\zeta_iζi也不能无限制的放大。在最小化的同时加上所有点的容错空间的和,就可以在最小化的同时又可以容忍一点程度的错误。并且通过参数CCC来平衡重要程度。
因此Soft Margin SVM最优化问题对应的数学表达式为:
Φ(x)=12ωTω+C∑i=1mζis.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0Φ(x)=\frac{1}{2}ω^Tω+C\sum_{i=1}^mζ_i \; \; s.t. \; \; y^{(i)}(ω^Tx^{(i)}+b)\geq 1-ζ_i \;ζ_i\geq 0Φ(x)=21ωTω+Ci=1∑mζis.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0
3. 正则化思想
我们观察上面的表达式的形式,其实相当于在Soft Margin SVM中加入了L1正则。可以将理解为正则化项,避免因为训练出的模型往极端的方式发展,让模型的拥有一定的容错能力,泛化性有所提升。
相应的,也有L2正则,即在的求和项上有所不同:
Φ(x)=12ωTω+C∑i=1mζi2s.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0Φ(x)=\frac{1}{2}ω^Tω+C\sum_{i=1}^mζ_i^2 \; \; s.t. \; \; y^{(i)}(ω^Tx^{(i)}+b)\geq 1-ζ_i \;ζ_i\geq 0Φ(x)=21ωTω+Ci=1∑mζi2s.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0
系数CCC越大,相应的容错空间越小。如果取正无穷,意味着逼迫着容错空间趋近于零,也就变成了Hard Margin SVM。
(二)Soft Margin的目标函数
那么Soft Margin的目标函数长什么样呢?还是用拉格朗日的方法:
Lp=12∣∣ω∣∣2+C∑i=1lζi−∑i=1lai[yi(ω⋅xi+b)−1+ζi]−∑i=1lμiζiL_p=\frac{1}{2}||ω||^2+C\sum_{i=1}^lζ_i-\sum_{i=1}^la_i[y_i(ω\cdot x_{i}+b)-1+ζ_i]-\sum_{i=1}^lμ_iζ_iLp=21∣∣ω∣∣2+Ci=1∑lζi−i=1∑lai[yi(ω⋅xi+b)−1+ζi]−i=1∑lμiζi
由于优化函数增加了惩罚项,且增加了一些约束条件,因此目标函数变得很复杂了。其实求解方法和之前是一样的,同样是分别对变量求偏导等于0:
∂Lp∂ω=0⇒ω=∑i=1laiyixi\frac{\partial L_p}{\partial ω}=0 \Rightarrow ω=\sum_{i=1}^la_iy_ix_i∂ω∂Lp=0⇒ω=i=1∑laiyixi
∂Lp∂b=0⇒∑i=1laiyi=0\frac{\partial L_p}{\partial b}=0 \Rightarrow \sum_{i=1}^la_iy_i=0 ∂b∂Lp=0⇒i=1∑laiyi=0
∂Lp∂ζi=0⇒C=ai+μi\frac{\partial L_p}{\partial ζ_i}=0 \Rightarrow C=a_i+ μ_i∂ζi∂Lp=0⇒C=ai+μi
带回到原表达式中得到:
LD=∑iai−12aTHas.t.0≤ai≤Cand∑iaiyi=0L_D=\sum_ia_i-\frac{1}{2}a^THa \: \: s.t.\: \: 0\leq a_i\leq C \: and \sum_i a_iy_i=0LD=i∑ai−21aTHas.t.0≤ai≤Candi∑aiyi=0
SVM的美妙之处,就是加了Soft Margin这么一个复杂的东西,但是通过求导之后,发现解决问题的方法殊途同归,并没有很复杂。
(三)使用sklearn中的SVM
1. SVM需要标准化处理
在使用SVM算法时,需要先对数据进行标准化处理。
SVM算法寻找的是使得Margin区间最大的中间的决策边界(超平面),而衡量Margin使用的是数据点之间的距离。涉及距离的,就应当对量纲问题进行关注,即进行标准化处理。
对于SVM算法来说,如果特征在不同维度上,数据尺度不同的话,非常影响SVM算法的决策边界。
2 数据准备及处理
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasetsiris = datasets.load_iris()
X = iris.data
y = iris.target
X = X[y<2,:2]
y = y[y<2]plt.scatter(X[y==0,0],X[y==0,1],color='red')
plt.scatter(X[y==1,0],X[y==1,1],color='blue')
plt.show()
然后进行数据标准化处理:
from sklearn.preprocessing import StandardScalerstandardScaler = StandardScaler()
standardScaler.fit(X)
X_std = standardScaler.transform(X)
3 SVM使用及C的选择
使用sklearn.svm包中的类LinearSVC,即使用支撑向量机做分类。
首先取一个非常大的C值进行观察,在这种情况下,算法近似Hard Margin
from sklearn.svm import LinearSVC svc = LinearSVC(C=1e9)
svc.fit(X_std,y)
LinearSVC(C=1000000000.0, class_weight=None, dual=True,
fit_intercept=True,
intercept_scaling=1, loss=‘squared_hinge’, max_iter=1000,
multi_class=‘ovr’, penalty=‘l2’, random_state=None, tol=0.0001,
verbose=0)
下面我们要观察决策边界,除了决策边界以外还想要观察整个Margin区域。要想画出Margin的两条边界,那么如何求出呢?我们知道决策边界为wx+b=0wx+b=0wx+b=0,相应地Margin边界为wx+b=+1wx+b=+1wx+b=+1、wx+b=−1wx+b=-1wx+b=−1。这就要求我们知道系数www和截距bbb。SVC中每个特征对应一个系数,现在是二维数据,可以得到w0w_0w0和w1w_1w1。下面求出系数和截距:
# 系数
svc.coef_
#array([[ 4.03244351, -2.50699244]])# 截距
svc.intercept_
#array([0.92735089])
然后绘制决策边界以及Margin的边界:
def plot_svc_decision_boundary(model, axis): x0, x1 = np.meshgrid(np.linspace(axis[0], axis[1], int((axis[1]-axis[0])*100)).reshape(-1, 1),np.linspace(axis[2], axis[3], int((axis[3]-axis[2])*100)).reshape(-1, 1),)X_new = np.c_[x0.ravel(), x1.ravel()]y_predict = model.predict(X_new)zz = y_predict.reshape(x0.shape)from matplotlib.colors import ListedColormapcustom_cmap = ListedColormap(['#EF9A9A','#FFF59D','#90CAF9'])plt.contourf(x0, x1, zz, linewidth=5, cmap=custom_cmap)# 绘制Margin区域上下两根线w = model.coef_[0]b = model.intercept_[0]# w0 * x0 + w1 * x1 + b = +1# w0 * x0 + w1 * x1 + b = -1plot_x = np.linspace(axis[0],axis[1],200)up_y = -w[0]/w[1] * plot_x - b/w[1] + 1/w[1]down_y = -w[0]/w[1] * plot_x - b/w[1] - 1/w[1]up_index = (up_y >= axis[2]) & (up_y <= axis[3])down_index = (down_y >= axis[2]) & (down_y <= axis[3])plt.plot(plot_x[up_index], up_y[up_index], color='black')plt.plot(plot_x[down_index], down_y[down_index], color='black')plot_svc_decision_boundary(svc, axis=[-3, 3, -3, 3])
plt.scatter(X_std[y==0,0], X_std[y==0,1])
plt.scatter(X_std[y==1,0], X_std[y==1,1])
plt.show()
通过上面的图片,可以非常清晰地看到,有三个蓝色数据点落在上面的边界,有两个橙色的数据点落在下边界上,这就是支撑向量。因为近似于Hard Margin SVM 因此Margin之间是没有任何数据的。既保证了正确分类,又让里决策边界最近的点到决策边界的距离最远。
然后取一个非常小的C值,来看看Soft Margin的表现:
svc2 = LinearSVC(C=0.01)
svc2.fit(X_std,y)plot_svc_decision_boundary(svc2, axis=[-3, 3, -3, 3])
plt.scatter(X_std[y==0,0], X_std[y==0,1])
plt.scatter(X_std[y==1,0], X_std[y==1,1])
plt.show()
可见有一个蓝色的点被错误地分类了,C越小,Margin越大。其中有很多数据点,给出了很大的容错空间。
三、巧妙的Kernel Trick
SVM,本质上就是个线性分类器,保证Margin最大。实际上都是线性SVM,包括Soft Margin解决的也不是线性不可分问题,而是解决在线性可分问题下存在噪点、异常点等问题。那么如何解决一个线性不可分问题呢?
(一)使用多项式处理非线性数据
处理非线性数据最典型的思路就是使用多项式的方式:扩充原本数据,制造新的多项式特征。
准备数据:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsX, y = datasets.make_moons(noise=0.20,random_state=123)plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()
下面使用多项式特征,用SVM算法进行分类:
from sklearn.preprocessing import PolynomialFeatures, StandardScaler
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipelinedef PolynomialSVC(degree, C=1.0):return Pipeline([("poly", PolynomialFeatures(degree=degree)),("std_scaler", StandardScaler()),("linearSVC", LinearSVC(C=C))])poly_svc = PolynomialSVC(degree=3)
poly_svc.fit(X,y)
然后我们使用之前用到的plot_decision_boundary方法绘制决策边界:
通过多项式的方式,让决策边界不再是一条直线了,而是一条曲线。
对于SVM算法来说,可以不使用多项式PolynomialFeatures的方式。而是使用一种巧妙的方法。
(二)SVM解决非线性问题
SVM算法如何解决线性不可分问题?下面通过两个例子进行展示。
1. 例子1
上面的图片有两种示例情况。对于最上面的情形来说,是线性可分的一维数据,在红蓝之间找到一个阈值,即可将二者分开(外面套着圆圈的点是支持向量)。
第二种情况就有所不同了,红-蓝-红,不管如何选择阈值,都不能把它分开。
SVM使用了一种非常巧妙的思路:一维空间不能解决,投影到二维空间。空间中的分布变成了如下的样子:
横坐标是x,纵坐标是x2x^2x2,相当于引入了一个新的维度。此时,就可以用一条线将其分开。
在原始空间中无法使用线性分类器,就将其映射到另一空间(Feature Space)当中,使其容易分。
2. 例子2
在下面的样本数据集中,红色点在中心,蓝色点在四周,所以一根线是肯定分不开的。
如果我们一定要在当前空间将其分开的话,可以找到一个圆圈作为决策边界,将其分离:
那么如何通过坐标变化,将其映射到新的空间中,得到线性可分的形式呢?将横坐标变为x12x_1^2x12纵坐标变为x22x_2^2x22,这样数据在空间分布中如下图所示:
我们可以想象,有一个内功深厚的武林高手,面对桌子上的一堆混在一起的绿豆和红豆(数据点),一掌拍在桌子上,用内力将其逼到空中(从低维空间映射到高维空间),再它们在空中分散的时候(在高维空间上线性可分),然后再一刀将其分开(决策平面)。如下图:
(三)认识核函数
现在我们已经知道,可以将数据从原始空间映射到Feature Space中去,就可以解决原本的线性不可分问题。那么如何做映射呢?
其实我们并不用特意地去设计映射(实际上我们也很难在高维空间去设计映射),而是使用固定的几种映射方法即可。这些映射方法就是核函数。
核函数本身不是SVM特有的一种技巧,事实上,只要我们在求解最优化问题中,存在xi⋅xjx_i\cdot x_jxi⋅xj,都可以将其转换为K(xi⋅xj)K(x_i\cdot x_j)K(xi⋅xj),下面让我们具体学习。
1. 多项式核函数
下面我们介绍一种映射方法:Φ(x)Φ(x)Φ(x):
Φ(x)Φ(x)Φ(x)这种映射方法实际上是将维度升上去,映射到一个非常高的维度(大约有m22\frac{m^2}{2}2m2维)。
我们知道,高维数据的运算是十分复杂的,那将数据升维的好处是是什么呢?又该如何计算呢?其实这其中就有SVM算法的精妙之处。
在《图文详解SVM原理与模型数学推导》中3.1小节,求解有条件限制的最优化问题的过程中最后求解w=∑i=1laiyixi⋅xw=\sum_{i=1}^la_iy_ix_i\cdot xw=∑i=1laiyixi⋅x时介绍过:两个向量做内积是SVM运算的精髓。
在原始空间中,两个向量做内积映射到高维空间中则变成xi⋅xj=Φ(xi)⋅Φ(xj)x_i\cdot x_j=Φ(x_i)\cdot Φ(x_j)xi⋅xj=Φ(xi)⋅Φ(xj)。展开后相乘得到:
合并之后得到很复杂的表达式:
Φ(a)⋅Φ(b)=1+2∑i=1maibi+∑i=1mai2bi2+∑i=1m−1∑j=i+1m2aiajbibjΦ(a)\cdot Φ(b)=1+2\sum_{i=1}^ma_ib_i+\sum_{i=1}^ma_i^2b_i^2+\sum_{i=1}^{m-1}\sum_{j=i+1}^{m}2a_ia_jb_ib_jΦ(a)⋅Φ(b)=1+2i=1∑maibi+i=1∑mai2bi2+i=1∑m−1j=i+1∑m2aiajbibj
但是,数学家们神奇地发现(具体怎么发现的,我们不用知道…),存在这样一个表达式:(a⋅b+1)2(a\cdot b+1)^2(a⋅b+1)2,它的展开式居然也是上面的表达式,这就是SVM中最重要的一个特性:
K(a,b)=(a⋅b+1)2=Φ(a)⋅Φ(b)K(a,b)=(a\cdot b+1)^2=Φ(a)\cdot Φ(b)K(a,b)=(a⋅b+1)2=Φ(a)⋅Φ(b)
这就是SVM算法的精妙之处:数学家设计出一种巧妙的数学变换,使高维空间的操作等价于低维空间的操作,解决了高维空间中的计算量问题,大大减少了运算量。
数据从低维映射到高维以后,问题的可分析性会增加,会变得更容易;但是高维空间的运算量太大,引入了Kernel Trick。
上面就是所谓的多项式核函数。可以拓展为一般形式:
K(x,y)=(x⋅y+c)dK(x,y)=(x\cdot y +c)^dK(x,y)=(x⋅y+c)d
其中d为多项式的阶数,在sklearn中,degree的默认参数为3.
2 高斯核函数
高斯核函数是SVM算法中使用最多的核函数,也被称作是RBF核(Radial Basis Function Kernel):
K(x,y)=e−γ∣∣x−y∣∣2K(x,y)=e^{-γ||x-y||^2}K(x,y)=e−γ∣∣x−y∣∣2
其中与高斯函数的γγγ成反比,即γγγ越大,高斯分布越窄;γγγ越小,高斯分布越宽。∣∣x−y∣∣2||x-y||^2∣∣x−y∣∣2表示向量的范数,可以理解为向量的模。
高斯核函数的数据映射是非常复杂的,其本质是将一个样本点映射到一个无穷维的特征空间。我们只需要关注映射后的结果即可。
下面看看高斯核函数本质上是在做什么事?现在先对核函数进行一个改变,将原本的∣∣x−y∣∣2||x-y||^2∣∣x−y∣∣2中的y值替换成两个固定点l1,l2l_1,l_2l1,l2。我们称这两个特殊的点为地标landmark。
高斯核函数升维的过程就是对于原本的每个x值,如果有两个landmark的话,就将其维为二维样本点,每个样本的取值是高斯核函数的值:
x⇒(e−γ∣∣x−l1∣∣2,e−γ∣∣x−l2∣∣2)x\Rightarrow (e^{-γ||x-l_1||^2},e^{-γ||x-l_2||^2})x⇒(e−γ∣∣x−l1∣∣2,e−γ∣∣x−l2∣∣2)
通过这样的映射,就可以将线性不可分数据变得线性可分。
我们再返过来看高斯核函数:
K(x,y)=e−γ∣∣x−y∣∣2K(x,y)=e^{-γ||x-y||^2}K(x,y)=e−γ∣∣x−y∣∣2
我们认为yyy就是地标点landmark的话,那么实际上在高斯核函数中,对于每一个数据点都是landmark,有多少样本,就有多少地标点。将mn的数据映射成mm的数据。
(四) SVM最终优化函数
SVM本质就是求解下面最优化问题:
12∣∣ω∣∣2+C∑i=1mζis.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0\frac{1}{2}||ω||^2+C\sum_{i=1}^mζ_i \; \; s.t. \; \; y^{(i)}(ω^Tx^{(i)}+b)\geq 1-ζ_i \;ζ_i\geq 021∣∣ω∣∣2+Ci=1∑mζis.t.y(i)(ωTx(i)+b)≥1−ζiζi≥0
为了求解有条件的最优化问题,转换为下面的形式:
max∑iai−12∑i,jaiajyiyjxi⋅xjs.t.∑iaiyi00≤ai≤Cmax\sum_ia_i-\frac{1}{2}\sum_{i,j}a_ia_jy_iy_jx_i\cdot x_j \; s.t. \sum_ia_iy_i0 \;0\leq a_i\leq Cmaxi∑ai−21i,j∑aiajyiyjxi⋅xjs.t.i∑aiyi00≤ai≤C
要注意,上面的形式是求最大值max,当然,如果不习惯,也可以转换成最小值min。
min12∑i,jaiajyiyjxi⋅xj−∑iais.t.∑iaiyi00≤ai≤Cmin\frac{1}{2}\sum_{i,j}a_ia_jy_iy_jx_i\cdot x_j-\sum_ia_i \; s.t. \sum_ia_iy_i0 \;0\leq a_i\leq Cmin21i,j∑aiajyiyjxi⋅xj−i∑ais.t.i∑aiyi00≤ai≤C
然后引入核函数进行替换:
min12∑i,jaiajyiyjK(xi,xj)−∑iais.t.∑iaiyi00≤ai≤Cmin\frac{1}{2}\sum_{i,j}a_ia_jy_iy_jK(x_i,x_j)-\sum_ia_i \; s.t. \sum_ia_iy_i0 \;0\leq a_i\leq Cmin21i,j∑aiajyiyjK(xi,xj)−i∑ais.t.i∑aiyi00≤ai≤C
其中K(xi,xj)=Φ(xi)⋅Φ(xj)K(x_i,x_j)=Φ(x_i)\cdot Φ(x_j)K(xi,xj)=Φ(xi)⋅Φ(xj)。但是实际上我们从来不用计算Φ(xi),Φ(xj)Φ(x_i), Φ(x_j)Φ(xi),Φ(xj),直接用不同的核函数代入,如:
K(a,b)=(x⋅y+c)dK(a,b)=e−γ∣∣a−b∣∣2K(a,b)=(x\cdot y +c)^d \; K(a,b)=e^{-γ||a-b||^2}K(a,b)=(x⋅y+c)dK(a,b)=e−γ∣∣a−b∣∣2
(五)小结
SVM算法作为数据挖掘领域十大经典算法之一,其中设计了很多精妙的思想。
在低维空间中线性不可能的数据,可以转化成高维度数据,使得数据更具有分析性;然后使用核函数,其在高维空间上的运算等价于低维空间,从而解决了运算量大的问题。
四、多项式核函数与RBF核函数代码实现及调参
(一)使用多项式核函数的SVM
1 数据准备及模型训练
首先准备数据:
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasetsX, y = datasets.make_moons(noise=0.20,random_state=123)plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()
sklearn中关于多项式核函数SVM的使用。
首先也需要返回一个Pipeline对象,其有两步:第一步是对数据进行标准化;第二步实例化SVC并将kernel参数设置为poly。这样就自动对传递的数据进行多项式化了。
from sklearn.svm import SVCdef PolynomialKernelSVC(degree, C=1.0):return Pipeline([("std_scaler", StandardScaler()),("kernelSVC", SVC(kernel='poly',degree=degree,C=C))])poly_kernel_svc = PolynomialKernelSVC(degree=3)
poly_kernel_svc.fit(X, y)
我们看看决策边界是什么样的?
plot_decision_boundary(poly_kernel_svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()
2 调参
我们再尝试着保持阶数degree不变,去调大参数C:
poly_kernel_svc = PolynomialKernelSVC(degree=3,C=200)
poly_kernel_svc.fit(X, y)
则得到如下的决策边界:
通过肉眼观察可见,参数C越大,中间的“凸起”越尖锐。我们知道,参数C是正则化项的系数,C越大,越接近于Hard Margin;C越小,容错性越大。
下面调试一个degree参数:
poly_kernel_svc = PolynomialKernelSVC(degree=4)
poly_kernel_svc.fit(X, y)
通过一些尝试发现,degree参数为偶数时,决策边界类似于双曲线的形式,而为奇数时,则是以直线为基础。大家可以使用网格搜索找到最佳参数。但是我们要注意,多项式阶数degree参数越大,则越容易出现过拟合。
(二)RBF核函数
下面使用sklearn中的高斯核函数,查看器决策边界,同时比较参数对于决策边界的影响。
使用上节的数据,使用sklearn.svm只需要将SVC类的参数kernel传入rbf,并且传入参数gamma即可。
from sklearn.preprocessing import StandardScaler
from sklearn.svm import SVC
from sklearn.pipeline import Pipelinedef RBFKernelSVC(gamma=1.0):return Pipeline([('std_scaler', StandardScaler()),('svc', SVC(kernel='rbf', gamma=gamma))])svc = RBFKernelSVC(gamma=1.0)
svc.fit(X,y)
下面我们查看其决策边界:
plot_decision_boundary(svc, axis=[-1.5, 2.5, -1.0, 1.5])
plt.scatter(X[y==0,0], X[y==0,1])
plt.scatter(X[y==1,0], X[y==1,1])
plt.show()
这就是使用RBF核函数,在γ=1.0γ=1.0γ=1.0时的决策边界。看上去比多项式核函数稍好一些。
2 RBF核函数几何意义以及调参
下面我们调整gamma参数,可以更加直观地看到RBF核函数的特点。先调大gamma参数:
svc = RBFKernelSVC(gamma=100)
svc.fit(X,y)
可见分类效果极其不好,看上去甚至有点恶心。
我们知道,γγγ参数取值越大,意味着高斯函数的“山峰”越窄。那对于决策边界有何影响呢?针对其中的某一类,在每个样本点的周围都形成了一个“山峰”(想象,这是一个俯视图,蓝色点是“山顶”),以“山峰”比较窄,所以看起来就在每个蓝色点的周围圆环区域就比较。
由此可见,RBF核函数,实际上只找到一类,然后在以该类中的每个点为“山尖”,用gamma参数表示“山峰的粗细”,所有的数据点连成“山脉”,这一区域是一类范围,其他范围都属于另一类。
当然了,上面的结果太过拟合了。我们减少gamma值再来看看:
svc = RBFKernelSVC(gamma=10)
svc.fit(X,y)
由此可见,“山峰”变得更比刚才“粗”了,从而连成了“山脉”。下面将gamma变得更小,极端一些,变成0.1,其决策边界如下:
我们看到,这个决策边界变得和线性边界差不多了,有点欠拟合了。由此我们得到:γγγ越小,模型复杂度就越小,倾向于欠拟合;γγγ越大,模型复杂度就越高,倾向于过拟合。这就要结合具体业务进行调参了。
(三)小结
SVM算法中的多项式核函数与RBF核函数的使用。在使用多项式核函数时,多项式阶数degree决定了决策边界的形状以及模型的复杂程度,参数C是决定了正则化项的权重,即模型的容错性。在使用RBF核函数时,决策边界对应的几何意义是什么样子,并且看到了在调节参数γγγ时对决策边界的影响。
五、回归问题及系列回顾总结
(一) 解决回归问题
1 解决回归问题的思想
SVM思想也可以解决回归问题。回归问题的本质就是找到一根能够很好滴拟合数据点的线(直线、曲线)。**不同回归算法的关键是怎么定义拟合。**比如我们之前学习的线性回归算法,定义拟合的方式就是数据点到拟合直线的MSE最小。
而对于SVM算法来说,如何定义“拟合”呢?
指定一个Margin值,在Margin区域的范围内,包含的数据点越多越好。这就表示这个Margin范围能够比较好地表达样本数据点,在这种情况下取中间的直线作为真正回归结果,用它来预测其他点的y值。
这和SVM算法解决分类问题的思路是相反的,在解决分类问题时,我们期望Margin中的范围越少越好。但是解决回归问题恰恰相反,我们希望所定义的Margin范围能够拟合更多的数据。
在具体训练SVM解决回归问题时,需要指定Margin范围,这里就引入了一个超参数εεε,即Margin的边界到中间直线的距离。
那么这种思想如何转换成具体的最优化问题表达式极其推导,就不介绍了。我们直接看看如何在sklearn中使用它。
2 sklearn算法中的使用
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_splitboston = datasets.load_boston()
X = boston.data
y = boston.target
X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=666)from sklearn.svm import LinearSVR
from sklearn.svm import SVR
from sklearn.preprocessing import StandardScaler
from sklearn.pipeline import Pipelinedef StandardLinearSVR(epsilon = 0.1):return Pipeline([('std_scaler', StandardScaler()),('linearSVR', LinearSVR(epsilon=epsilon))])svr = StandardLinearSVR()
svr.fit(X_train,y_train)
svr.score(X_test, y_test)
# 输出:0.6358704741572658
虽然得到的分数不高,但实际上我们还有很多参数可以调节。除了epsilon以外,我们还可以调节C。并且如果不使用线性分类器LinearSVR,我们还可以使用SVR包,可以添加kernel,这样就又有很多参数可以调节了。
(二)算法回顾 Road Map
上个世纪六十年代,就提出了SVM的概念,到九十年代才逐渐完善。
最初就是一个线性分类器,对其进行改进,使得Margin最大化,这就导出了Linear SVM,定义了Margin,将其数学表达式求出来,去优化这个函数。
Linear SVM也有一些问题,即在实际情况下不能完美地将各个数据点分开,在不满足限制条件的下就求不到数学解。为了解决线性可分的情况下存在异常点的问题,就提出了Soft Margin的思想,增加正则化项,提高容错性。
那么如何解决线性不可能问题呢?把原始空间的问题映射到高维空间,将线性不可分问题转换成线性可分问题,即将a⋅b⇒Φ(a)⋅Φ(b)a\cdot b\Rightarrow Φ(a)\cdot Φ(b)a⋅b⇒Φ(a)⋅Φ(b)。这种想法非常好,但是高维数据做内积,计算量太大了。
为了解决这个问题,数学家提出了Kernel Trick核函数:Φ(a)⋅Φ(b)=K(a,b)Φ(a)\cdot Φ(b)=K(a,b)Φ(a)⋅Φ(b)=K(a,b)。实际上我们从来不会去真正去求高维映射,而是直接用核函数来代替了,既相当于在高维空间进行操作,又解决了计算量大的问题。
(三)总结
SVM算法是一个很优秀的算法,在集成学习和神经网络之类的算法没有表现出优越性能前,SVM基本占据了分类模型的统治地位。目前则是在大数据时代的大样本背景下,SVM由于其在大样本时超级大的计算量,热度有所下降,但是仍然是一个常用的机器学习算法。
SVM算法的主要优点有:
- 解决高维特征的分类问题和回归问题很有效,在特征维度大于样本数时依然有很好的效果。
- 仅仅使用一部分支持向量来做超平面的决策,无需依赖全部数据。
- 有大量的核函数可以使用,从而可以很灵活的来解决各种非线性的分类回归问题。
- 样本量不是海量数据的时候,分类准确率高,泛化能力强。
SVM算法的主要缺点有:
- 如果特征维度远远大于样本数,则SVM表现一般。
- SVM在样本量非常大,核函数映射维度非常高时,计算量过大,不太适合使用。
- 非线性问题的核函数的选择没有通用标准,难以选择一个合适的核函数。
- SVM对缺失数据敏感。
机器学习笔记(十)——入门支持向量机(SVM)相关推荐
- sklearn和libsvm吗_机器学习笔记(3)-sklearn支持向量机SVM
文章用于总结对sklearn支持向量机模块的使用,系统回顾作者近期的相关学习,部分内容来源网站(侵权联系必删). 第一部分 SVM用途及优缺点 1. 主要用途: classification(分类). ...
- 吴恩达《Machine Learning》精炼笔记 7:支持向量机 SVM
作者 | Peter 编辑 | AI有道 系列文章: 吴恩达<Machine Learning>精炼笔记 1:监督学习与非监督学习 吴恩达<Machine Learning>精 ...
- 机器学习中的算法-支持向量机(SVM)基础
机器学习中的算法-支持向量机(SVM)基础 版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处 ...
- 机器学习-第六章 支持向量机(SVM)
机器学习-第六章 支持向量机(SVM) D系鼎溜关注 2020.02.09 21:19:41字数 1,131阅读 458 6.1 间隔与支持向量 开倍速观看视频之后,对课本所说的会更加了解. 支持向量 ...
- 机器学习笔记十四:随机森林
在上一篇机器学习笔记十三:Ensemble思想(上)中,简要的提了一下集成学习的原理和两种主要的集成学习形式. 而在这部分要讲的随机森林,就算是其中属于bagging思路的一种学习方法.为了篇幅,b ...
- python sklearn 支持向量机_python机器学习库sklearn之支持向量机svm介绍
python机器学习库sklearn之支持向量机svm介绍tcB太阳2平台注册|网站分类目录 python数据挖掘系列教程tcB太阳2平台注册|网站分类目录 这里只讲述sklearn中如何使用svm算 ...
- 吴恩达机器学习(十)支持向量机(SVM)
目录 0. 前言 1. 代价函数(Cost Function) 2. 假设函数(Hypothesis) 3. 范数表示 4. 高斯核函数(Gaussian Kernel) 5. SVM实现多分类 6. ...
- 吴恩达机器学习笔记 | 人工智能入门笔记(一)
文章目录 机器学习 基础介绍 什么是机器学习? 监督学习 无监督学习 单变量线性回归 模型表示 代价函数 代价函数的直观理解 梯度下降 梯度下降的直观解释理解 梯度下降的线性回归 线性代数回顾 矩阵和 ...
- svm 支持向量机 回归 预测_机器学习:简单理解支持向量机SVM
在介绍过贝叶斯之后,今天尝试着给大家介绍支持向量机SVM. 在机器学习中,SVM试图找到一个最佳的超平面,该平面可以最佳地分割来自不同类别的观察结果.一个在N-1维的超平面可以分割Ñ维的特征空间.例如 ...
- 吴恩达|机器学习作业6.0支持向量机(SVM)
6.0.支持向量机 1)题目: 在本练习中,您将使用支持向量机来建立一个垃圾邮件分类器. 在本练习的前半部分,您将使用支持向量机(SVM)处理各种两维的样本数据集.使用这些数据集进行实验将帮助您直观地 ...
最新文章
- AFN 切换BaseUrl
- 贪吃蛇python零基础教程_自学python-tkinter项目-贪吃蛇的程序(0基础入门学习)...
- MFC中Mat实现打开本地图片
- java七大_Java 7七大新功能
- Y_CLIENT_QHD_504 role in GM6 ZSAP_CRM_BCR_SALESREP_DAIDE
- OpenShift 4 - 用 Operator 创建 Jenkins 环境
- VSCode Vim
- JavaScript:手写JSONP
- Atitit 提升用户体验 生物识别 与登录 身份验证
- 做好震荡筑底打持久战的准备
- 怎么在安全模式里找计算机用户,安全模式怎么解除
- 新美域杂志新美域杂志社新美域编辑部2022年第6期目录
- iOS开发之Block详解
- 基于蒙特卡洛法的规模化电动车有序充放电及负荷预测(PythonMatlab实现)
- python全案例学习_Python全案例学习与实践
- Shell脚本中dirname命令的使用
- BigDecimal 科学计数法转换 正负数转换
- nodelist与HTMLCollection
- 在钉钉环境下打开测试网页
- 红叶李之Linux bash 基础特性