之前通过一个系列对支持向量机(以下简称SVM)算法的原理做了一个总结,本文从实践的角度对scikit-learn SVM算法库的使用做一个小结。scikit-learn SVM算法库封装了libsvm 和 liblinear 的实现,仅仅重写了算法了接口部分。

1. scikit-learn SVM算法库使用概述

    scikit-learn中SVM的算法库分为两类,一类是分类的算法库,包括SVC, NuSVC,和LinearSVC 3个类。另一类是回归算法库,包括SVR, NuSVR,和LinearSVR 3个类。相关的类都包裹在sklearn.svm模块之中。

    对于SVC, NuSVC,和LinearSVC 3个分类的类,SVC和 NuSVC差不多,区别仅仅在于对损失的度量方式不同,而LinearSVC从名字就可以看出,他是线性分类,也就是不支持各种低维到高维的核函数,仅仅支持线性核函数,对线性不可分的数据不能使用。

    同样的,对于SVR, NuSVR,和LinearSVR 3个回归的类, SVR和NuSVR差不多,区别也仅仅在于对损失的度量方式不同。LinearSVR是线性回归,只能使用线性核函数。

    我们使用这些类的时候,如果有经验知道数据是线性可以拟合的,那么使用LinearSVC去分类 或者LinearSVR去回归,它们不需要我们去慢慢的调参去选择各种核函数以及对应参数, 速度也快。如果我们对数据分布没有什么经验,一般使用SVC去分类或者SVR去回归,这就需要我们选择核函数以及对核函数调参了。

    什么特殊场景需要使用NuSVC分类 和 NuSVR 回归呢?如果我们对训练集训练的错误率或者说支持向量的百分比有要求的时候,可以选择NuSVC分类 和 NuSVR 。它们有一个参数来控制这个百分比。

    这些类的详细使用方法我们在下面再详细讲述。

2. 回顾SVM分类算法和回归算法

    我们先简要回顾下SVM分类算法和回归算法,因为这里面有些参数对应于算法库的参数,如果不先复习下,下面对参数的讲述可能会有些难以理解。

    对于SVM分类算法,其原始形式是:$$min\;\; \frac{1}{2}||w||_2^2 +C\sum\limits_{i=1}^{m}\xi_i $$ $$ s.t.  \;\; y_i(w \bullet \phi(x_i) + b)  \geq 1 - \xi_i \;\;(i =1,2,...m)$$ $$\xi_i \geq 0 \;\;(i =1,2,...m)$$

    其中m为样本个数,我们的样本为$(x_1,y_1),(x_2,y_2),...,(x_m,y_m)$。$w,b$是我们的分离超平面的$w \bullet \phi(x_i) + b = 0$系数, $\xi_i $为第i个样本的松弛系数, C为惩罚系数。$\phi(x_i)$为低维到高维的映射函数。

    通过拉格朗日函数以及对偶化后的形式为:$$ \underbrace{ min }_{\alpha}  \frac{1}{2}\sum\limits_{i=1,j=1}^{m}\alpha_i\alpha_jy_iy_jK(x_i,x_j) - \sum\limits_{i=1}^{m}\alpha_i $$ $$ s.t. \; \sum\limits_{i=1}^{m}\alpha_iy_i = 0 $$ $$0 \leq \alpha_i \leq C$$

    其中和原始形式不同的$\alpha$为拉格朗日系数向量。$K(x_i,x_j) $为我们要使用的核函数。

    对于SVM回归算法,其原始形式是:$$min\;\; \frac{1}{2}||w||_2^2 + C\sum\limits_{i=1}^{m}(\xi_i^{\lor}+ \xi_i^{\land}) $$ $$s.t. \;\;\; -\epsilon - \xi_i^{\lor} \leq y_i - w \bullet \phi(x_i ) -b \leq \epsilon + \xi_i^{\land}$$ $$\xi_i^{\lor} \geq 0, \;\; \xi_i^{\land} \geq 0 \;(i = 1,2,..., m)$$

    其中m为样本个数,我们的样本为$(x_1,y_1),(x_2,y_2),...,(x_m,y_m)$。$w,b$是我们的回归超平面的$w \bullet x_i + b = 0$系数, $\xi_i^{\lor}, \xi_i^{\land}$为第i个样本的松弛系数, C为惩罚系数,$\epsilon$为损失边界,到超平面距离小于$\epsilon$的训练集的点没有损失。$\phi(x_i)$为低维到高维的映射函数。

    通过拉格朗日函数以及对偶化后的形式为:$$ \underbrace{ min}_{\alpha^{\lor}, \alpha^{\land}}\; \frac{1}{2}\sum\limits_{i=1,j=1}^{m}(\alpha_i^{\land} - \alpha_i^{\lor})(\alpha_j^{\land} - \alpha_j^{\lor})K(x_i,x_j) - \sum\limits_{i=1}^{m}(\epsilon-y_i)\alpha_i^{\land}+ (\epsilon+y_i)\alpha_i^{\lor}  $$ $$ s.t. \; \sum\limits_{i=1}^{m}(\alpha_i^{\land} - \alpha_i^{\lor}) = 0 $$ $$ 0 < \alpha_i^{\lor} < C \; (i =1,2,...m)$$ $$ 0 < \alpha_i^{\land} < C \; (i =1,2,...m)$$

    其中和原始形式不同的$\alpha^{\lor}, \alpha^{\land}$为拉格朗日系数向量。$K(x_i,x_j) $为我们要使用的核函数。

3. SVM核函数概述

    在scikit-learn中,内置的核函数一共有4种,当然如果你认为线性核函数不算核函数的话,那就只有三种。

    1)线性核函数(Linear Kernel)表达式为:$K(x, z) = x \bullet z $,就是普通的内积,LinearSVC 和 LinearSVR 只能使用它。

    2)  多项式核函数(Polynomial Kernel)是线性不可分SVM常用的核函数之一,表达式为:$K(x, z) = (\gamma x \bullet z  + r)^d$ ,其中,$\gamma, r, d$都需要自己调参定义,比较麻烦。

    3)高斯核函数(Gaussian Kernel),在SVM中也称为径向基核函数(Radial Basis Function,RBF),它是libsvm默认的核函数,当然也是scikit-learn默认的核函数。表达式为:$K(x, z) = exp(\gamma||x-z||^2)$, 其中,$\gamma$大于0,需要自己调参定义。

    4)Sigmoid核函数(Sigmoid Kernel)也是线性不可分SVM常用的核函数之一,表达式为:$K(x, z) = tanh(\gamma x \bullet z  + r)$, 其中,$\gamma, r$都需要自己调参定义。

    一般情况下,对非线性数据使用默认的高斯核函数会有比较好的效果,如果你不是SVM调参高手的话,建议使用高斯核来做数据分析。  

4. SVM分类算法库参数小结

    这里我们对SVM分类算法库的重要参数做一个详细的解释,重点讲述调参的一些注意点。

参数 LinearSVC  SVC NuSVC
惩罚系数C 即为我们第二节中SVM分类模型原型形式和对偶形式中的惩罚系数C,默认为1,一般需要通过交叉验证来选择一个合适的C。一般来说,如果噪音点较多时,C需要小一些。 NuSVC没有这个参数, 它通过另一个参数nu来控制训练集训练的错误率,等价于选择了一个C,让训练集训练后满足一个确定的错误率
nu LinearSVC 和SVC没有这个参数,LinearSVC 和SVC使用惩罚系数C来控制惩罚力度。  nu代表训练集训练的错误率的上限,或者说支持向量的百分比下限,取值范围为(0,1],默认是0.5.它和惩罚系数C类似,都可以控制惩罚的力度。
核函数 kernel LinearSVC没有这个参数,LinearSVC限制了只能使用线性核函数

核函数有四种内置选择,第三节已经讲到:‘linear’即线性核函数, ‘poly’即多项式核函数, ‘rbf’即高斯核函数, ‘sigmoid’即sigmoid核函数。如果选择了这些核函数, 对应的核函数参数在后面有单独的参数需要调。默认是高斯核'rbf'。

还有一种选择为"precomputed",即我们预先计算出所有的训练集和测试集的样本对应的Gram矩阵,这样$K(x,z)$直接在对应的Gram矩阵中找对应的位置的值。

当然我们也可以自定义核函数, 由于我没有用过自定义核函数,这里就不多讲了。

正则化参数penalty  仅仅对线性拟合有意义,可以选择‘l1’即L1正则化 或者 ‘l2’即L2正则化。默认是L2正则化,如果我们需要产生稀疏话的系数的时候,可以选L1正则化,这和线性回归里面的Lasso回归类似。 SVC和NuSVC没有这个参数
是否用对偶形式优化dual  这是一个布尔变量,控制是否使用对偶形式来优化算法,默认是True,即采用上面第二节的分类算法对偶形式来优化算法。如果我们的样本量比特征数多,此时采用对偶形式计算量较大,推荐dual设置为False,即采用原始形式优化 SVC和NuSVC没有这个参数  
核函数参数degree  LinearSVC没有这个参数,LinearSVC限制了只能使用线性核函数 如果我们在kernel参数使用了多项式核函数 'poly',那么我们就需要对这个参数进行调参。这个参数对应$K(x, z) = (\gamma x \bullet z  + r)^d$中的$d$。默认是3。一般需要通过交叉验证选择一组合适的$\gamma, r, d$
核函数参数gamma    LinearSVC没有这个参数,LinearSVC限制了只能使用线性核函数

如果我们在kernel参数使用了多项式核函数 'poly',高斯核函数‘rbf’, 或者sigmoid核函数,那么我们就需要对这个参数进行调参。

多项式核函数中这个参数对应$K(x, z) = (\gamma x \bullet z  + r)^d$中的$\gamma$。一般需要通过交叉验证选择一组合适的$\gamma, r, d$

高斯核函数中这个参数对应$K(x, z) = exp(\gamma||x-z||^2)$中的$\gamma$。一般需要通过交叉验证选择合适的$\gamma$

sigmoid核函数中这个参数对应$K(x, z) = tanh(\gamma x \bullet z  + r)$中的$\gamma$。一般需要通过交叉验证选择一组合适的$\gamma, r$

$\gamma$默认为'auto',即$\frac{1}{特征维度}$

 核函数参数coef0  LinearSVC没有这个参数,LinearSVC限制了只能使用线性核函数

如果我们在kernel参数使用了多项式核函数 'poly',或者sigmoid核函数,那么我们就需要对这个参数进行调参。

多项式核函数中这个参数对应$K(x, z) = (\gamma x \bullet z  + r)^d$中的$r$。一般需要通过交叉验证选择一组合适的$\gamma, r, d$

sigmoid核函数中这个参数对应$K(x, z) = tanh(\gamma x \bullet z  + r)$中的$r$。一般需要通过交叉验证选择一组合适的$\gamma, r$

coef0默认为0

 样本权重class_weight  指定样本各类别的的权重,主要是为了防止训练集某些类别的样本过多,导致训练的决策过于偏向这些类别。这里可以自己指定各个样本的权重,或者用“balanced”,如果使用“balanced”,则算法会自己计算权重,样本量少的类别所对应的样本权重会高。当然,如果你的样本类别分布没有明显的偏倚,则可以不管这个参数,选择默认的"None"
分类决策decision_function_shape  LinearSVC没有这个参数,使用multi_class参数替代。 可以选择'ovo'或者‘ovo’.目前0.18版本默认是'ovo'.0.19版本将是'ovr'

OvR(one ve rest)的思想很简单,无论你是多少元分类,我们都可以看做二元分类。具体做法是,对于第K类的分类决策,我们把所有第K类的样本作为正例,除了第K类样本以外的所有样本都作为负例,然后在上面做二元分类,得到第K类的分类模型。其他类的分类模型获得以此类推。

OvO(one-vs-one)则是每次每次在所有的T类样本里面选择两类样本出来,不妨记为T1类和T2类,把所有的输出为T1和T2的样本放在一起,把T1作为正例,T2作为负例,进行二元分类,得到模型参数。我们一共需要T(T-1)/2次分类。

从上面的描述可以看出OvR相对简单,但分类效果相对略差(这里指大多数样本分布情况,某些样本分布下OvR可能更好)。而OvO分类相对精确,但是分类速度没有OvR快。一般建议使用OvO以达到较好的分类效果。

分类决策multi_class

可以选择 ‘ovr’ 或者 ‘crammer_singer’

‘ovr’和SVC和nuSVC中的decision_function_shape对应的‘ovr’类似。

'crammer_singer'是一种改良版的'ovr',说是改良,但是没有比’ovr‘好,一般在应用中都不建议使用。

SVC和nuSVC没有这个参数,使用decision_function_shape参数替代。 
缓存大小cache_size

LinearSVC计算量不大,因此不需要这个参数

在大样本的时候,缓存大小会影响训练速度,因此如果机器内存大,推荐用500MB甚至1000MB。默认是200,即200MB.

5. SVM回归算法库参数小结

    SVM回归算法库的重要参数巨大部分和分类算法库类似,因此这里重点讲述和分类算法库不同的部分,对于相同的部分可以参考上一节对应参数。

参数 LinearSVR SVR nuSVR
惩罚系数C 即为我们第二节中SVM分类模型原型形式和对偶形式中的惩罚系数C,默认为1,一般需要通过交叉验证来选择一个合适的C。一般来说,如果噪音点较多时,C需要小一些。大家可能注意到在分类模型里面,nuSVC使用了nu这个等价的参数控制错误率,就没有使用C,为什么我们nuSVR仍然有这个参数呢,不是重复了吗?这里的原因在回归模型里面,我们除了惩罚系数C还有还有一个距离误差$\epsilon$来控制损失度量,因此仅仅一个nu不能等同于C.也就是说分类错误率是惩罚系数C和距离误差$\epsilon$共同作用的结果。后面我们可以看到nuSVR中nu的作用。
nu LinearSVR 和SVR没有这个参数,用$\epsilon$控制错误率 nu代表训练集训练的错误率的上限,或者说支持向量的百分比下限,取值范围为(0,1],默认是0.5.通过选择不同的错误率可以得到不同的距离误差$\epsilon$。也就是说这里的nu的使用和LinearSVR 和SVR的$\epsilon$参数等价。
距离误差epsilon 即我们第二节回归模型中的$\epsilon$,训练集中的样本需满足$-\epsilon - \xi_i^{\lor} \leq y_i - w \bullet \phi(x_i ) -b \leq \epsilon + \xi_i^{\land}$ nuSVR没有这个参数,用nu控制错误率
是否用对偶形式优化dual   和SVC类似,可参考上一节的dual描述 SVR和NuSVR没有这个参数
正则化参数penalty   和SVC类似,可参考上一节的penalty 描述 SVR和NuSVR没有这个参数  
核函数 kernel LinearSVR没有这个参数,LinearSVR限制了只能使用线性核函数 和SVC, nuSVC类似,可参考上一节的kernel描述
核函数参数degree, gamma 和coef0 LinearSVR没有这些参数,LinearSVR限制了只能使用线性核函数 和SVC, nuSVC类似,可参考上一节的kernel参数描述
样本权重class_weight 和LinearSVC, SVC, nuSVC类似,可参考上一节的class_weight描述 
损失函数度量loss

可以选择为‘epsilon_insensitive’ 和 ‘squared_epsilon_insensitive’ ,如果选择‘epsilon_insensitive’ ,则损失度量满足$-\epsilon - \xi_i^{\lor} \leq y_i - w \bullet \phi(x_i ) -b \leq \epsilon + \xi_i^{\land}$,即和第二节的损失度量一样。是默认的SVM回归的损失度量标准形式。

如果选择为 ‘squared_epsilon_insensitive’ , 则损失度量满足$ (y_i - w \bullet \phi(x_i ) -b)^2 \leq \epsilon + \xi_i$,此时可见会少一个松弛系数。其优化过程我们在SVM原理系列里没有讲,但是目标函数优化过程是完全相似的。

一般用默认的‘epsilon_insensitive’就足够了。

SVR和NuSVR没有这个参数
缓存大小cache_size

LinearSVC计算量不大,因此不需要这个参数

在大样本的时候,缓存大小会影响训练速度,因此如果机器内存大,和SVC,nuSVC一样,推荐用500MB甚至1000MB。默认是200,即200MB.

6. SVM算法库其他调参要点

    上面已经对scikit-learn中类库的参数做了总结,这里对其他的调参要点做一个小结。

    1)一般推荐在做训练之前对数据进行归一化,当然测试集中的数据也需要归一化。。

    2)在特征数非常多的情况下,或者样本数远小于特征数的时候,使用线性核,效果已经很好,并且只需要选择惩罚系数C即可。

    3)在选择核函数时,如果线性拟合不好,一般推荐使用默认的高斯核'rbf'。这时我们主要需要对惩罚系数C和核函数参数$\gamma$进行艰苦的调参,通过多轮的交叉验证选择合适的惩罚系数C和核函数参数$\gamma$。

    4)理论上高斯核不会比线性核差,但是这个理论却建立在要花费更多的时间来调参上。所以实际上能用线性核解决问题我们尽量使用线性核。

    

(欢迎转载,转载请注明出处。欢迎沟通交流: pinard.liu@ericsson.com)   

scikit-learn 支持向量机算法库使用小结的更多相关文章

  1. Python第三方库(模块)"scikit learn"以及其他库的安装

    scikit-learn是一个用于机器学习的 Python 模块. 其主页:http://scikit-learn.org/stable/. GitHub地址: https://github.com/ ...

  2. scikit-learn 线性回归算法库小结

    scikit-learn对于线性回归提供了比较多的类库,这些类库都可以用来做线性回归分析,本文就对这些类库的使用做一个总结,重点讲述这些线性回归算法库的不同和各自的使用场景. 线性回归的目的是要得到输 ...

  3. Scikit Learn: 在python中机器学习

    转自:http://my.oschina.net/u/175377/blog/84420#OSC_h2_23 Scikit Learn: 在python中机器学习 Warning 警告:有些没能理解的 ...

  4. (原创)(四)机器学习笔记之Scikit Learn的Logistic回归初探

    目录 5.3 使用LogisticRegressionCV进行正则化的 Logistic Regression 参数调优 一.Scikit Learn中有关logistics回归函数的介绍 1. 交叉 ...

  5. mahout算法库(四)

    mahout算法库 分为三大块 1.聚类算法 2.协同过滤算法(一般用于推荐) 协同过滤算法也可以称为推荐算法!!! 3.分类算法 算法类 算法名 中文名 分类算法               Log ...

  6. SVM 支持向量机算法-实战篇

    公号:码农充电站pro 主页:https://codeshellme.github.io 上一篇介绍了 SVM 的原理和一些基本概念,本篇来介绍如何用 SVM 处理实际问题. 1,SVM 的实现 SV ...

  7. 安装Python算法库

    安装Python算法库 主要包括用NumPy和SciPy来处理数据,用Matplotlib来实现数据可视化.为了适应处理大规模数据的需求,python在此基础上开发了Scikit-Learn机器学习算 ...

  8. OpenSSL密码算法库: MD5示例小程序

    OpenSSL http://www.openssl.org/ OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库.SSL协议库以及应用程序.OpenSSL 的密码算法库包含多种加密算 ...

  9. 算法库:Matlab与C++混合编程

    算法库:Matlab与C++混合编程 最近做光流算法预演过程中,下载的源码中涉及到了Matlab和C++的混合编程.在同事Matlab2014的环境下,程序到是一下就运行通过了.但在我这Matlab2 ...

随机推荐

  1. sql with as union all

    WITH RPL (FId,Fname,Forder) AS ( SELECT ment.deptno,ment.deptname,ment.orderno FROM JTERP..fg_depart ...

  2. 纯CCS绘制三角形箭头图案

    用CSS绘制三角形箭头.使用纯CSS,你只需要很少的代码就可以创作出各种浏览器都兼容的三角形箭头! CSS代码: /* create an arrow that points up */ div.ar ...

  3. hadoop---前期准备---屌丝

    hadoop要求有多台机子进行后续的数据处理,作为屌丝一枚,怎么才能搭建一个合适的环境学习hadoop?这就是本篇将要介绍的----前期准备. 搭建环境没啥好说的,说一下搭建环境多需要的吧 硬件:电脑 ...

  4. Android 怎么退出整个应用程序?

    方法一: 我们在写android应用程序时,经常会遇到想退出当前Acitivity,或者直接退出应用程序.我之前的一般操作是按返回键,或者直接按home键直接返回,其实这两种操作都没有关闭当前应用程序 ...

  5. Oracle中的CHR()函数与ASCII()函数

    工作中经常会处理一些因特殊字符而导致的错误,如上周我就遇到了因为换行符和回车符导致的数据上报的错误,这种错误比较难以发现,通常是由于用户的输入习惯导致的,有可能数据极少,就那么几行错误从而导致整个数据 ...

  6. Java面向对象课程小结

    1.什么是对象?什么是类? 类和对象的关系 定义类的方法 方法五要素 new关键字 引用类型变量的赋值 null和nullException null大小写的区别 2.方法 重载和重写 构造 方法,带 ...

  7. 通过反射获取DLL的类实现加载窗体

    1.创建一个DLL 类库,并新建一个窗体类,这个直接在vs上操作就好 2. 建立一个Testassembly工程 新建一个测试类 namespace Testassembly { public par ...

  8. canvas绘制坐标轴

    效果图如下, var canvas = document.getElementById("canvas"), context = canvas.getContext("2 ...

  9. iOS中assign、copy 、retain等关键字的含义

    iOS中assign.copy .retain等关键字的含义  转自:http://my.oschina.net/majiage/blog/267409 assign: 简单赋值,不更改索引计数cop ...

  10. Python黑帽编程2.4 流程控制

    Python黑帽编程2.4  流程控制 本节要介绍的是Python编程中和流程控制有关的关键字和相关内容. 2.4.1 if …..else 先上一段代码: #!/usr/bin/python # - ...