支持向量机libsvm的使用指南

最近一项目需要对采样的数据进行拟合建模,正常情况下,需要预先建立函数模型,然后再根据样本利用类似最小二乘的办法解算函数模型系数,然而考虑到被采样数据函数模型难以建立,所以需要一种通用函数逼近器。本欲使用小波神经网络来做此事,后来通过IRC好友d0048交流得知,支持向量机(Support Vector Machines,SVM)是一种更经典的通用函数逼近器,而更是得知,台湾大学林智仁(Chih-Jen Lin)开发了一个操作简单、易于使用、快速有效的SVM软件包,使得问题得到了有效解决。然而SVM软件其实对于机器学习零基础的人入门依旧存难,故本文提供一种更为直接的使用指南。

一、LIBSVM介绍

支持向量机是机器学习的一种,所以如果想要理解支持向量机的原理及方案,那么需要从头开始学习机器学习,而这也不在本文的范筹之内。下面我也只是讲讲如何使用LIBSVM。

LIBSVM可以解决的问题:

  1. 分类问题: 多样本数据进行分类(C-SVC,n-SVC)
  2. 回归问题: 通用函数逼近器,线形拟合(epsilon-SVR,nu-SVR)
  3. 分布估计: 一类支持向量机(one-class SVM)

同时也提供了四种常用的核函数提供选择:

  1. 线性
  2. 多项式
  3. 径向基
  4. S形函数

LIBSVM是一个开源的软件包,主页地址如下:http://www.csie.ntu.edu.tw/~cjlin/libsvm,软件包内部提供了多个语言的接口,如python,c++,R,matlab等,可以方便的在多个平台上面使用,另外还提供了可视化的操作工具 svm-toy 以及基于grid方法最优参数选择等。

二、LIBSVM使用方法

LIBSVM采用的是命令行方法,通过读取指定格式的文件,然后生成模型文件,然后根据模型文件再进行预测分类情况或获取回归效果。

2.1 命令行使用方法

打开压缩包,主目录下必然存在下面几个文件:

heart_scale
Makefile
svm-predict.c
svm-scale.c
svm-train.c

其中heart_scale是自带的测试程序,也是指定格式的文件。再接下来执行make进行编译,即可获取三个可执行文件:svm-train,svm-predict,svm-scale. 三个程序的功能如下:

  1. svm-scale: 用于缩放样本数据的工具。
  2. svm-train: 读取指定的样本数据,然后生成模型文件。
  3. svm-predict: 根据模型预测结果。

下面逐一说明用法。

2.1.1 svm-scale

svm-scale 可以对原始样本的数据进行缩放,范围可以自行定制,一般情况下选择[0,1]或[-1,1]即可,缩放的目的主要有两个1:

  1. 防止某个特证过大或过小,从而在训练过中作用不平衡;
  2. 提高计算速度,不平衡的数据会影响可能会引起计算困难。

svm-scale一是很有重要的,可能会对结果造成较大的影响。其原理如下2

y' = lower + (upper - lower)\frac{y-min}{max-min}

式中,y 为缩放前的数据,y’ 为缩放后的数据;lower 为参数中指定的数据下界,upper 为参数中指定的数据上界;min 为全部训练数据中的最小值,max 为全部训练数据中的最大值。

使用方法如下:

Usage: svm-scale [options] data_filename
options:
-l lower : x scaling lower limit (default -1)
-u upper : x scaling upper limit (default +1)
-y y_lower y_upper : 缩放后的数据范围(类别标签 y),默认不对 y 进行缩放
-s save_filename : 将缩放的规则保存为文件save_filename
-r restore_filename : 按照restore_filename中的规则缩放数据

在此处我们使用-soption保存规则,运行下面的命令:

$ ./svm-scale -s train.range ./heart_scale > ./heart_scale_t

则可获取类似如下的数据在train.range里面:

x
-1 1
1 -1 1
2 -1 1

第一行表示是对 x 进行的缩放;第二行表示缩放的上下界分别是 1 和 -1;第三行表示特征向量x的第一个分量x1在训练数据中的范围是 -1~1,以此类推。(此例中由于heart_scale已经过缩放了,故范围没有什么变化)。另外缩放后的数据已经放到./heart_scale_t中去了(此例中应没有什么变化)。

2.1.2 svm-train

svm-train就是训练模形的函数了,参数相对较多,没有基础的人想要直接理解加以使用较难,如何较好调整参数从而获取相应的模型可以参考第三大节的SVM选择策略与方法。下面说一说使用方法:

基本使用方法如下:

Usage: svm-train [options] training_set_file [model_file]
    training_set_file: 训练样本
    model_file:        生成的模型文件
options:
-s svm_type : set type of SVM (default 0)
    0 -- C-SVC
    1 -- nu-SVC
    2 -- one-class SVM
    3 -- epsilon-SVR
    4 -- nu-SVR
-t kernel_type : set type of kernel function (default 2)
    0 -- linear: u'*v
    1 -- polynomial: (gamma*u'*v + coef0)^degree
    2 -- radial basis function: exp(-gamma*|u-v|^2)
    3 -- sigmoid: tanh(gamma*u'*v + coef0)
-d degree : set degree in kernel function (default 3)
-g gamma : set gamma in kernel function (default 1/num_features)
-r coef0 : set coef0 in kernel function (default 0)
-c cost : set the parameter C of C-SVC, epsilon-SVR, and nu-SVR (default 1)
-n nu : set the parameter nu of nu-SVC, one-class SVM, and nu-SVR (default 0.5)
-p epsilon : set the epsilon in loss function of epsilon-SVR (default 0.1)
-m cachesize : set cache memory size in MB (default 100)
-e epsilon : set tolerance of termination criterion (default 0.001)
-h shrinking: whether to use the shrinking heuristics, 0 or 1 (default 1)
-b probability_estimates: whether to train a SVC or SVR model for probability estimates, 0 or 1 (default 0)
-wi weight: set the parameter C of class i to weight*C, for C-SVC (default 1)

我们必须得注意的是参数之间的关系。其中-d -g -r三个选项均用于设置核参数的,而这些核参数可以查看kernel_type中的公式,从而确定那些参数是有效的。如-d参数所确定的degree就只能对多项式核有效。而-c参数就不能用于nu-SVC之类的。

使用范例:

$ ./svm-train -s 0 -t 2 -g 1 -c 1 heart_scale

在不指定文件名的情况下,该程序会生成一个heart_scale.model的模型文件,同时也会有如下的输出:

optimization finished, #iter = 404
nu = 0.612883
obj = -97.103458, rho = 0.027523
nSV = 231, nBSV = 63
Total nSV = 231

其中代表的含义如下:

  1. obj is the optimal objective value of the dual SVM problem.
  2. rho is the bias term in the decision function sgn(w^Tx – rho).
  3. nSV and nBSV are number of support vectors and bounded support vectors (i.e., alpha_i = C).

而生成的模型文件内容大约如此(//后而内容为注释内容)

svm_type c_svc  //所选择的svm类型,默认为c_svc
kernel_type rbf //训练采用的核函数类型,此处为RBF核
gamma 1         //RBF核的参数γ
nr_class 2      //类别数,此处为两分类问题
total_sv 231    //支持向量总个数
rho 0.0275231   //判决函数的偏置项b
label 1 -1      //原始文件中的类别标识
nr_sv 109 122   //每个类的支持向量机的个数
SV              //以下为各个类的权系数及相应的支持向量
0.9572802954069508 1:0.708333 2:1 3:1 4:-0.320755 5:-0.105023 6:-1 7:1 8:-0.419847 9:-1 10:-0.225806 12:1 13:-1•

2.1.3 svm-predict

svm-predict自然是利用模型计算结果,并将结果与“实测结果”进行比对。使用方法非常简单:

Usage: svm-predict test_file model_file output_file
    test_file:  用于预测的数据文件,格式和train所需文件一样
    model_file: 由svm-train生成的model文件
    out_file:   预测结果

其中开始比较难以理解的就是为何用于预测的数据文件格式和用于训练的格式是一样的,一般认为,test_file中不应当包含分类结果/回归结果,实际上由于smv-predict做了一次将预测结果和(分类/回归) 结果的对比,并获得了(分类正确率/回归方差)。使用训练用的文件可以当作预测文件来用,本次试验的结果如下所示:

./svm-predict heart_scale heart_scale.model heart_scale_out
Accuracy = 96.2963% (260/270) (classification)

2.2 LIBSVM数据格式

在完成上述的命令的使用方法之后,我们非常有必要了解livsvm的数据文件结构,从而实现自己的数据分类与回归。其数据格式如下所示:

Label1 index1:value11 index2:value12 ...
Label2 index1:value21 index2:value22 ...
...

其中 Label 在分类问题中指的是分类结果,一般情况下使用正整数,而在回归问题中则是指目标值,自然可以是任意结果了。
index:value 则分别指属性和该属性对应的值。例如,我要给木块大小进行分类,分成两大类: 大木块和小木块。现有三个木块,其长宽高的测量结果均已知,则此时我们可以将该分类写成下面:

1 1:0.1 2:0.2 3:0.5
1 1:0.5 2:0.2 3:0.5
2 1:2.2 2:2.1 3:0.5

该文件中即使用Lable区的1和2分别代表小木块和大木块,而用index区的1,2,3分别代表长宽高三个属性,而后而的值代表其测量值。

而在回归问题中,label变成目标值,是任意实数,而index:value也自然变成了自变量及自变量对应的值。

2.3 LIBSVM扩展工具

libsvm也提供一些小工具方便使用,主要是python的脚本,功用基本如下:

  1. checkdata.py: 用于检查数据的格式正确性与否
  2. easy.py: 一种将libsvm三个工具串起来使用的脚本
  3. gird.py: 用grid方法来搜寻最佳C能数与gamma参数
  4. subset.py: 用于提取子样本数据的脚本

另外提供了简单的svm-toy这样的图形界面以供使用(仅仅只能是用试样的),内部也包含了gtk,qt,windows下的三大可编译版本。

matlab可以使用libsvm,但是需要进行预编译,将libsvm的结果编译成mex文件,matlab即可进行调用。在libsvm/matlab目录下打开matlab,然后执行make命令,即可编译完毕,完成之后就可以当成函数来用了。

三、SVM选择策略与方法

3.1 两个重要参数C与gamma

SVM模型有两个非常重要的参数C与gamma。其中 C是惩罚系数,即对误差的宽容度。c越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。C过大或过小,泛化能力变差。

gamma是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度,同时也会拟合效果造成影响,一般来说,gamma值越大,平滑效果越差,容易出现过拟合,反之则反3

我们必须注意gamma的物理意义,也就是RBF的幅宽

3.2 C-SVC与nu-SVC

nu-SVC是基于C-SVC改进的算法,目的是降低C的选取难度,两者的最优解相同(换句话,这两个是相同的)。在libsvm中使用-u来设置nu-SVC,范围是[0,1],而使用-C来设置C-SVC,可选值范围为0到无穷大.

nu参数最大优点就是该参数和样本错误率与支持向量个数与样本总数的比例有如下关系:

nu是错误样本的个数所占总样本点数份额的上界
nu是支持向量个数据所占总样本点位份客的下界

也就是这说,nu这个参数相对来说,要有意义的多,相对容易确定。

3.3 epsilon-SVR与nu-SVR

epsilon-SVR/nu-SVR 的关系如C-SVC/nu-SVC 关系一致,由于epsilon-SVR(\epsilon -SVR)的不敏感损失函数中的系数\epsilon需要事先进行确认,想要确认较为困,故使用nu-SVR使用nu([0,1范围)来加以确认。在libsvm中表现也就是系数不同,分别使用-u-p进行控制。

3.4 一类支持向量机

说到分类,一般均指的是将事物分成两类及以上,然而一类支持向量则有点不太一样,可以按照下面两个方面理解:

  1. 把事物分成两类,其中一类符合特征,另外一类不符合特征,和分类的差别在于,一类支持向量机只有符合特征的样本数据。
  2. 从形像的角度来说,一类支持向量机就是构造一个高维超球,尽可能的把符合特征的数据包起来,同时又不受不符合特征数据的影响。

3.5 四种核函数的选择

  1. 一般情况下推荐使用RBF的核。
  2. RBF的核可以模拟线性核,故线性核一般情况不作考虑,除非在数据量较大的情况下。
  3. sigmoid的核矩阵有时候并非正定矩阵,精度一般也比不上RBF;
  4. 多项式也不错,但是阶数太高可能会导致运算困难。

四、几个参考文件

  1. 官方的说明文档: LIBSVM:A Library for Support Vector Machines.pdf
  2. SVM使用指南:A Practical Guide to Support Vector Classification
  3. [LIBSVM FAQ]](https://www.csie.ntu.edu.tw/~cjlin/libsvm/faq.html#f506)

基本上常见的问题都可以找到答案。

Reference

此条目发表在GNSS, 软件安装分类目录,贴了标签。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。