分享

LIBSVM入门解读

 桑枯海 2015-07-12

一、入门介绍

LIBSVM 是台湾大学林智仁(Chih-Jen Lin)博士等开发设计的一个操作简单、易于使用、快速有效的通用SVM软件包,可以解决分类问题(包括C- SVC、n - SVC )、回归问题(包括e - SVR、n - SVR )以及分布估计(one-class-SVM )等问题,提供了线性、多项式、径向基和S形函数四种常用的核函数供选择(也可以自定义核函数),可以有效地解决多类问题、交叉验证选择参数、对不平衡样本加权、多类问题的概率估计等。

二、LIBSVM工具使用说明

由于libsvm程序小,运用灵活,输入参数较少,并且是开源的,易于扩展,目前已经成为国内应用最多的SVM库。LIBSVM可以从林智仁博士的个人主页http://www.csie./~cjlin/免费获得,目前已经发展到3.17版。下载.zip格式的版本,解压后可以看到,主要有6个文件夹和一些c++源码文件。

Java——主要是应用于java平台;

matlab——应用于matlab平台;

Python——是用来参数优选的工具,稍后介绍;

svm-toy——可视化的工具,用来展示训练数据和分类界面,里面是源码,其编译后的程序在windows文件夹下;

tools——主要包含四个python文件,用来数据集抽样(subset),参数优选(grid),集成测试(easy),数据检查(checkdata);

windows——包含libSVM四个exe程序包,我们所用的库就是他们。

其他.h和.cpp文件都是程序的源码,可以编译出相应的.exe文件。其中,最重要的是svm.h和svm.cpp文件,svm-predict.c、svm-scale.c和svm-train.c(还有一个svm-toy.c在svm-toy文件夹中)都是调用的这个文件中的接口函数,编译后就是windows下相应的四个exe程序。还有个heart_scale,是一个样本文件,可以用记事本打开,用来测试用的。另外,里面的 README 跟 FAQ也是很好的文件,可以看英文试试不算太难。

如果仅仅是使用libsvm库中的工具来说,windows下的四个.exe文件就足够用了的。

1)用libsvm-3.17\windows文件夹下的exe文件执行

以windows平台为例,双击打开svm-toy.exe文件,点击“Run”按钮部分,在黑色区域的部分用鼠标随机点下点,代表第一类的数据分布情况;然后点击“Change”按钮,在黑色区域的另一部分点上点,这代表这选择第二类的数据分布;最后点击“Run”按钮,该工具就能将这两类数据分出两类,并用不同的颜色区域来表示不同的类别。如下图所示:

图中左上方绿色的区域,是第一类模式所在的区域,右下方的黄色区域,是你选择的第二类模式所在的的区域,而两者的分界面,也就是SVM的最优分类面。当然,SVM是通过核函数将原始数据映射到高维空间,在高维空间进行线性分类。换句话说,在高维空间,这两类数据应该是线性可分的,即:最优分类面应该是一条直线,而这里看到的,是将高维空间分类的结果又映射回原始空间所呈现的分类结果,即:非线性的分类面。细心的朋友可能已经发现,在上述界面的右下角,有一个编辑框,里面写着“-t 2 -c 100”,显然,这是libSVM的一些参数,你也可以试着更改这些参数,来选择不同的核函数、不同的SVM类型等来达到最好的分类效果

以下简单介绍一下libsvm中的小工具:

libSVM中包含以下可执行程序文件(小工具):

(1)svm-scale.exe:一个用于对输入数据进行归一化的简易工具

(2)svm-toy.exe:一个带有图形界面的交互式SVM二分类功能演示小工具;

(3)svm-train.exe:对用户输入的数据进行SVM训练。其中,训练数据是按照以下格式输入的:

<类别号> <索引1>:<特征值1> <索引2>:<特征值2>...

(4)svm-predict.exe:根据SVM训练得到的模型,对输入数据进行预测,即分类。测试数据的格式与训练数据格式相同,但要给定一个label值(这里必须得设定一个label值,任意label值都行)。

2)在myeclipse中建工程执行

上述表述都是直接在dos环境下用命令行运行的,下面给出在myeclipse中调用libsvm API的简单示例。

(1)准备训练样本和测试样本,直接从http://www.csie./~cjlin/libsvmtools/datasets/上下载即可,本实验采用的UCI的breast-cancer数据集。

如果想自己定义核函数,那么属于precompute kernel values and input them as training and testing files.

       此时训练样本和测试样本变成如下格式:

       New training instance for xi:  <label>   0:i   1:K(xi,x1) ... L:K(xi,xL) 
       New testing instance for any x:  <label>    0:?   1:K(x,x1) ... L:K(x,xL) 

       That is, in the training file the first column must be the "ID" of xi. In testing, ? can be any value.

(2)建立Java工程,导入libsvm.jar包,还需要导入java文件下的svm_train.java和svm_predict.java这两个文件,这两个文件其实主要是在LibSVM的基础上进一步封装,把命令行参数转换成String[]类型的函数参数,方便API调用。至于svm_toy(图形界面)和svm_scale(数据压缩)文件,可以选择性导入,不是必要文件。

(3)把训练数据和测试数据放在工程文件下或自定义数据存放目录。

(4)编写Java调用LibSVM API分类代码如下:

  1. public static void main(String[] args) throws Exception{  
  2.         String filepath = "E:\\CCDM2014-DATA\\data\\task2\\";  
  3.         //param:   -v:设置10折交叉验证   
  4.         //param:   train1.txt文件是训练数据    
  5.         //param:   trainfile\\modle_r.txt是存储训练出来的模型的文件  
  6.         String[] arg = {"-v","10",filepath+"train1.txt","trainfile\\model_r.txt"};  
  7.         String[] parg = {filepath+"train2.txt","trainfile\\model_r.txt",  
  8.                 "trainfile\\out_r.txt"};  
  9.         System.out.println("----------------SVM运行开始-----------------");  
  10.   
  11. //      String[] arg = {"-s","0","-c","5","-t","2","-g","0.5","-e","0.1","model.txt"};  
  12. //      svm_train.main(arg);  
  13.           
  14.         svm_train.main(arg);//训练  
  15.         svm_predict.main(parg);//预测或分类  
  16.     }  

(5)运行程序,可以得到分类准确率。对训练样本采用10折交叉验证法测试SVM分类性能,其结果如下:


其中,#iter为迭代次数nu是你选择的核函数类型的参数objSVM文件转换为的二次规划求解得到的最小值rho为判决函数的偏置项bnSV为标准支持向量个数(0<a[i]<c)nBSV为边界上的支持向量个数(a[i]=c)Total nSV为支持向量总个数(对于两类来说,因为只有一个分类模型Total nSV = nSV,但是对于多类,这个是各个分类模型的nSV之和)。

在trainfile目录下多了个model_r.txt文件,这个文件是记录的训练模型的情况

svm_type c_svc //所选择的svm类型,默认为c_svc
kernel_type rbf //训练采用的核函数类型,此处为RBF
gamma 0.0024390243902439024 //RBF核的参数γ
nr_class 3 //类别数,此处为三分类问题
total_sv 3699 //支持向量总个数
rho -0.9634570935162986 -0.46454612570491943 0.4202147803894908 //判决函数的偏置项b
label 1 0 2 //原始文件中的类别标识
nr_sv 2191 856 652 //每个类的支持向量机的个数
SV //以下为各个类的权系数及相应的支持向量

2.96599026228955 1.2311237005827835 1:0.13953 2:2.0 3:1.0 4:5.0 5:2.0 6:2.0 8:1.0 9:1.0 11:1.0 12:-0.3305 ........


补充:libsvm使用规范说明

1. libSVM的数据格式

Label 1:value 2:value ….

Label:是类别的标识,比如上节train.model中提到的1 -1,你可以自己随意定,比如-10,0,15。当然,如果是回归,这是目标值,就要实事求是了。

Value:就是要训练的数据,从分类的角度来说就是特征值,数据之间用空格隔开

比如: -15 1:0.708 2:1056 3:-0.3333

需要注意的是,如果特征值为0,特征冒号前面的(姑且称做序号)可以不连续。如:

-15 1:0.708 3:-0.3333

表明第2个特征值为0,从编程的角度来说,这样做可以减少内存的使用,并提高做矩阵内积时的运算速度。我们平时在matlab中产生的数据都是没有序号的常规矩阵,所以为了方便最好编一个程序进行转化。

 2. svm-scale的用法

svm-scale是用来对原始样本进行缩放的,范围可以自己定,一般是[0,1]或[-1,1]。缩放的目的主要是

1)防止某个特征过大或过小,从而在训练中起的作用不平衡;

2)为了计算速度。因为在核计算中,会用到内积运算或exp运算,不平衡的数据可能造成计算困难。

通俗的说,也就是因为原始数据的范围可能过大或过小,svmscale可以将数据重新缩放到适当范围使训练与预测速度更快。

用法:svmscale [-l lower] [-u upper][-y y_lower y_upper][-s save_filename][-r restore_filename] filename其中,[]中都是可选项

      -l:设定数据下限;lower:设定的数据下限值,缺省为-1

     -u:设定数据上限;upper:设定的数据上限值,缺省为 1

     -y:是否对目标值同时进行缩放;y_lower为下限值,y_upper为上限值;

     -s save_filename:表示将缩放的规则保存为文件save_filename;

     -r restore_filename:表示将按照已经存在的规则文件restore_filename进行缩放;

      filename:待缩放的数据文件,文件格式按照libsvm格式。

默认情况下,只需要输入要缩放的文件名就可以了:比如(已经存在的文件为test.txt)      svm-scale test.txt

这时,test.txt中的数据已经变成[-1,1]之间的数据了。但是,这样原来的数据就被覆盖了,为了让规划好的数据另存为其他的文件,我们用一个dos的重定向符 > 来另存为(假设为out.txt):      svmscale test.txt > out.txt

运行后,我们就可以看到目录下多了一个out.txt文件,那就是规范后的数据。假如,我们想设定数据范围[0,1],并把规则保存为test.range文件:

svmscale –l 0 –u 1 –s test.range test.txt > out.txt

这时,目录下又多了一个test.range文件,可以用记事本打开,下次就可以用-r test.range来载入了。

3. svm-train的用法

svm-train我们在前面已经接触过,主要实现对训练数据集的训练,并可以获得SVM模型。

用法: svmtrain [options] training_set_file [model_file]

其中,options为操作参数,可用的选项即表示的涵义如下所示:

-s 设置svm类型:默认值为0

0 – C-SVC

1 – v-SVC

2 – one-class-SVM

3 –ε-SVR

4 – n - SVR

-t 设置核函数类型,默认值为2

0 --线性核:u'*v

1 --多项式核:(g*u'*v+coef0)degree

2 -- RBF核:exp(-γ*||u-v||2)

3 -- sigmoid核:tanh(γ*u'*v+coef0)

-d degree:设置多项式核中degree的值,默认为3

-gγ:设置核函数中γ的值,默认为1/k,k为特征(或者说是属性)数;

-r coef 0:设置核函数中的coef 0,默认值为0;

-c cost:设置C-SVC、ε-SVR、n - SVR中从惩罚系数C,默认值为1;

-n v:设置v-SVC、one-class-SVM与n - SVR中参数n,默认值0.5;

-pε:设置v-SVR的损失函数中的e,默认值为0.1;

-m cachesize:设置cache内存大小,以MB为单位,默认值为40;

-eε:设置终止准则中的可容忍偏差,默认值为0.001;

-h shrinking:是否使用启发式,可选值为0或1,默认值为1;

-b概率估计:是否计算SVC或SVR的概率估计,可选值0或1,默认0;

-wi weight:对各类样本的惩罚系数C加权,默认值为1;

-v n:n折交叉验证模式;

model_file:可选项,为要保存的结果文件,称为模型文件,以便在预测时使用。

默认情况下,只需要给函数提供一个样本文件名就可以了,但为了能保存结果,还是要提供一个结果文件名,比如:test.model,则命令为:

svm-train test.txt test.model

svm-train -s 0 -c 10 -t 2 -g 0.5 -e 0.1 test.model

4. svm-predict的用法

svm-predict是根据训练获得的模型,对数据集合进行预测。

用法:svmpredict [options] test_file model_file output_file

其中,options为操作参数,可用的选项即表示的涵义如下所示:

-b probability_estimates——是否需要进行概率估计预测,可选值为0或者1,默认值为0。

model_file ——是由svmtrain产生的模型文件;

test_file——是要进行预测的数据文件,格式也要符合libsvm格式,即使不知道label的值,也要任意填一个,svmpredict会在output_file中给出正确的label结果,如果知道label的值,就会输出正确率;

output_file ——是svmpredict的输出文件,表示预测的结果值。

至此,主要的几个接口已经讲完了,满足一般的应用不成问题。


摘自:http://blog.sina.com.cn/s/blog_4c38701d01011ept.html

实际应用的小贴士
=======================

* 缩放数据。例如,缩放每个属性为 [0,1] 或 [-1,+1]。
* 对于 C-SVC,可以考虑用 ‘tools’ 文件夹下的模型选择工具。
* nu-SVC/one-class-SVM/nu-SVR 中的 nu 参数近似为训练误差和支持向量的比率。
* 如果要分类的数据是不平衡的(如,大正集和小负集),用 -wi 尝试不同的惩罚因子(参见下述例子)。
* 对于复杂问题,指定更大的缓存(即,larger -m)。

例子
=======================

> svm-scale -l -1 -u 1 -s range train > train.scale
> svm-scale -r range test > test.scale
缩放训练数据的每个特征值在 [-1,1] 内(训练数据文件为 train,缩放后的数据为 train.scale),缩放因子(就是一些参数)被存储在 range 文件中然后被用于缩放测试数据(测试数据文件为test,缩放后的数据为test.scale)。

> svm-train -s 0 -c 5 -t 2 -g 0.5 -e 0.1 data_file
用 RBF核函数 exp(-0.5|u-v|^2) 训练(data_file文件)得到一个分类器,C=10,终止允差为0.1。

> svm-train -s 3 -p 0.1 -t 0 data_file
用线性核函数 u'v 解决 SVM 回归(问题),损失函数中 epsilon=0.1。

> svm-train -c 10 -w1 1 -w2 5 -w4 2 data_file
训练一个分类器,对于 ‘1’ 类 惩罚因子为 10= 1 * 10,对于 ‘2’ 类 惩罚因子为 50 = 5 * 10,对于 ‘4’ 类 惩罚因子为 20 = 2 * 10。

> svm-train -s 0 -c 100 -g 0.1 -v 5 data_file
对分类器用参数 C=100,gamma=0.1 做五折交叉验证。

> svm-train -s 0 -b 1 data_file
> svm-predict -b 1 test_file data_file.model output_file
用概率信息得到一个模型。用概率估计来预测测试数据。

自定义核函数
=======================

用户可以自定义核函数的值并输入它们作为训练和测试文件。之后 libsvm 不需要原始的训练和测试集。
假定有 L 个训练实体 x1, ..., xL。以 K(x, y) 做核函数中两个实体 x,y 的值,输入格式如下:

新训练实例 xi:
<label> 0:i 1:K(xi,x1) ... L:K(xi,xL)
新测试实例 任意 x:
<label> 0:? 1:K(x,x1) ... L:K(x,xL)

即,在训练文件中,第一列必须是 xi 的‘ID’。在测试中,用  作为任意值。

所有核函数值包括 ZEROs 必须是明确提供的。训练和测试文件中任何随机的或排列的子集也有效(见下例)。

注意:格式与以前在 libsvmtools(文件夹)中发布的预定义核函数略有不同

例子:
        假定最初的训练数据有三个 4-feature 的实例,测试数据有一个实例:

        15  1:1 2:1 3:1 4:1
        45        2:3       4:3
        25              3:1

        15  1:1       3:1

        如果用线性核函数,我们将得到如下新的训练和测试子集:

        15  0:1 1:4 2:6   3:1
        45  0:2 1:6 2:18 3:0
        25  0:3 1:1 2:0   3:1

        15  0:? 1:2 2:0  3:1

         可为任何值。

        上面的训练文件的任何子集也是有效的。如,

        25  0:3 1:1 2:0  3:1
        45  0:2 1:6 2:18 3:0

        意味着核矩阵为:

                [K(2,2) K(2,3)] = [18 0]
                [K(3,2) K(3,3)] = [ 0  1]


推荐博客:

http://blog.csdn.net/zhzhl202/article/details/7583464(数据倾斜 松弛变量+惩罚因子, 说明很详细)

http://blog.sina.com.cn/s/blog_72995dcc0100pflx.html(简单全面介绍LibSVM)

http://blog.csdn.net/chl033/article/details/4645544(介绍很详细)

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多