LIBSVM 是台湾大学林智仁 (Chih-Jen Lin) 博士等开发设计的一个操作简单、易于使用、快速有效的通用 SVM 软件包,可以解决分类问题(包括 C- SVC 、n - SVC )、回归问题(包括 e - SVR 、 n - SVR )以及分布估计(one-class-SVM )等问题,提供了线性、多项式、径向基和 S 形函数四种常用的核函数供选择,可以有效地解决多类问题、交叉验证选择参数、对不平衡样本加权、多类问题的概率估计等。 LIBSVM 是一个开源的软件包,需要者都可以免费的从作者的个人主页 http://www.csie.ntu.edu.tw/~cjlin/ 处获得。他不仅提供了 LIBSVM 的 C++ 语言的算法源代码,还提供了 Python 、 Java 、 R 、 MATLAB 、 Perl 、 Ruby 、 LabVIEW以及 C#.net 等各种语言的接口,可以方便的在 Windows 或 UNIX 平台下使用,也便于科研工作者根据自己的需要进行改进(譬如设计使用符合自己特定问题需要的核函数等)。另外还提供了 WINDOWS 平台下的可视化操作工具 SVM-toy ,并且在进行模型参数选择时可以绘制出交叉验证精度的等高线图。
SVM进行函数估计是有监督学习,进行概率密度估计是非监督学习
自从版本2.8以后 libsvm采用SMO算法
将编译好的文件4个文件放在windows文件下(从台湾人网站上下载的文件中有个windows文件将其复制到D:盘),改名windowssvm然后把heart_scale文件拷贝到windowssvm,如下图
heart_scale文件台湾人为我们准备的一些数据,用于测试,以后我们用自己的测试数据
切换到字符目录下:
一二行出现不能打开heart_scale是没有将文件拷贝到与svm-train.exe所在目录。
其中, #iter 为迭代次数, nu 与前面的操作参数 -n n (-n n :设置 n - SVC 、 one-class-SVM 与 n - SVR 中参数 n ,默认值 0.5 ;)相同, obj 为 SVM 文件
转换为的二次规划求解得到的最小值, rho 为判决函数的常数项 b , nSV 为支持
向量个数, nBSV 为边界上的支持向量个数, Total nSV 为支持向量总个数。
注释2:
obj 是对偶SVM问题的最优目标值. rho 是判决函数sgn(w^Tx - rho)的偏项. nSV 和 nBSV 分别代表支持向量和边界支持向量 (即alpha_i = C)的个数. nu-svm 在某中程度上可以看作 C-SVM的等价形式,不过其中的C被替换为 nu. nu 仅表明了相应的参数.
训练后的模型保存为文件 heart_scale.model:
可以看到多出了heart_scale.model文件,用写字板打开
用记事本等文本浏览器打开
可以看到其内容如下(其后“ % ”后内容为笔者所加注释):
svm_type c_svc % 训练所采用的 svm 类型,此处为 C- SVC
kernel_type rbf % 训练采用的核函数类型,此处为 RBF 核
gamma 0.0769231 % 与操作参数设置中的 g 含义相同
nr_class 2 % 分类时的类别数,此处为两分类问题
total_sv 132 % 总共的支持向量个数
rho -0.424462 % 决策函数中的常数项 b
label 0 1 % 类别标签
nr_sv 64 68 % 各类别标签对应的支持向量个数
SV % 以下为支持向量
test_file 就是我们要 predict 的数据。它的格式跟 svmtrain 的输入,也就是 training_set_file 是一样的!不过每行最前面的 label 可以省略 ( 因为 predict 就是要 predict 那个 label) 。 但如果 test_file 有 label 的值的话, predict 完会顺便拿 predict 出来的值跟 test_file 里面写的值去做比对,这代表: test_file 写的 label 是真正的分类结果,拿来跟我们 predict 的结果比对就可以 知道 predict 有没有猜对了。
也所以,我们可以拿原 training set 当做 test_file 再丢给 svmpredict 去 predict ( 因为格式一样 ) ,看看正确率有多高, 方便后面调参数。
输入如下内容:
As you can see ,我们把原输入丢回去 predict , Accuracy 就是预测的正确率了。 如果输入没有 label 的话,那就是真的 predict 了。
为什么正确率是86。6667%主要是相关的参数我们没有设置(使用的程序默认的参数)。下一步我们为了追求正确率更高,研究如何设置参数的问题。
我们首先删除D:/windowssvm/目录下的heart_scale.model,heart_scale.out文件
在输入如下内容:屏幕显示(此时文件目录下生成新的heart_scale.model)
我们重新在预测一下以前的文件:
我们可以看到正确率提高了。
一般而言, SVM 使用的方式 ( 在决定参数时 ) 常是这样:
1. 先有已分好类的一堆资料
2. 随机数拆成好几组 training set
3. 用某组参数去 train 并 predict 别组看正确率
4. 正确率不够的话,换参数再重复 train/predict
说明白点就是自己去测试,等找到一组不错的参数后,就拿这组参数来建 model 并用来做最后对未知数据的predict 。 这整个过程叫 cross validation , 也就是交叉比对。
在我们找参数的过程中,可以利用 svmtrain 的内建 cross validation 功能来帮忙:
-v n: n-fold cross validation
n 就是要拆成几组,像 n=3 就会拆成三组,然后先拿 1 跟 2 来 train model 并 predict 3 以得到正确率; 再来拿 2跟 3 train 并 predict 1 ,最后 1,3 train 并 predict 2 。其它以此类推。
如果没有交叉比对的话,很容易找到只在特定输入时好的参数。像前面我们 c=10 得到 92.2% ,不过拿 -v 5 来看看:
Cross Validation Accuracy = 76.6667% ,比一开始的 86 还差。
通常而言,比较重要的参数是 gamma (-g) 跟 cost (-c) 。而 cross validation (-v) 参数常用 5
cost 默认值是 1, gamma 默认值是 1/k , k 等于输入 数据笔数。 那我们怎么知道要用多少来当参数呢?
就是 Try 参数找比较好的值。(后面我将会介绍使用工具得到参数)
Try 参数的过程常用 exponential 指数成长的方式来增加与减少参数的数值,也就是 2^n (2 的 n 次方 ) 。
因为有两组参数,所以等于要 try n*n=n^2 次。 这个过程是不连续的成长,所以可以想成我们在一个 X-Y 平面上指定的范围内找一群格子点 ( grid , 如果你不太明白,想成方格纸或我们把平面上所有 整数交点都打个点,就是那样 ) ,每个格子点的 X 跟 Y 经过换算 ( 如 2^x, 2^y) 就拿去当 cost 跟 gamma 的值来 cross validation 。
所以现在你应该懂得 libsvm 的 python 子目录下面 有个 grid.py 是做啥的了: 它把上面的过程自动化, 在你给定的范围内呼叫 svm-train 去 try 所有的参数值。 python 是一种语言,在这里我不做介绍,因为我会了 :P (just a joke,真正原因是 -- 这是 libsvm 的 tutorial) 。 grid.py 还会把结果 plot 出来,方便你寻找参数。 libsvm 有很多跟python 结合的部份,由此可见 python 是强大方便的工具。很多神奇的功能,像自动登入多台 机器去平行跑 grid等等都是 python 帮忙的。不过 SVM 本身可以完全不需要 python ,只是会比较方便。
交叉验证,寻找合适的参数(guide.pdf文件的翻译)
此段内容要补充。。。。。。。。。。
主要是确定两个参数 C 和r,使用默认的参数并不能保证准确率,因此我门要使用模型来求出好的参数,保证训练准确率
在v重交叉验证,我们首先将训练集分为v个子集,用v-1个子集测试剩下来的一个子集
全部训练集的每个子集都会被预测,交叉验证的准确率就是正确分类的百分率。
交叉验证能阻止溢出问题,我们使用图一来说明这个问题,实心的圆和实心的三角形是训练数据。空心的代表测试数据,测试的正确率在1(a),1(b)中不是很好。另一方面在1(c),1(d)
没有溢出训练数据我们得到更好的测试准确率。
我们推荐“grid-search”on C和r,
这种方法很直接看起来很愚蠢,事实上他能节省计算代价通过
Grid-search有两个目的:
我们感觉不是很安全去使用近似法和启发式的方法去穷尽所有的参数。
发现好的参数的计算时间不比先进的算法少。
原始的使用方法:
libsvm的一些工具还是非常有用的
1.可以调用subset.py将你的样本集合按你所想要的比例进行抽样出两个子样本集合
2.还可以调用grid.py做关于(C,gamma)的交叉验证参数选择,可以轻松的搜索到最好的参数对(C,gamma).
3.还可以调用easy.ph一步到位完成svm的整个挖掘过程,最后得出交叉验证精度,最有参数对和测试集上的测试精度.
4.还可以调用checkdata进行检查你的数据格式是否有错误.
结果如下:
安装python工具编译环境,因为在前一段时间安装了ARCGIS自带了一个python24版本默认安装在D:/Python24目录下,设置路径在系统变量Path后加路径即可。
如果成功的话可以在控制台输入python 回车验证
另一个工具就是gnuplot.exe,下载不是安装文件:
安装完上面的软件还不能运行,还要修改easy.py,grid.py的设置.将他们对应的代码" gnuplot_exe = r"c:/tmp/gnuplot/bin/pgnuplot.exe""都改为你的pgnuplot.exe所在的路径,
比如我的文件在当前目录的上一级目录,就是和tools文件夹在同一级目录,那么我的设置应该为" gnuplot_exe = r"../gnuplot/bin/pgnuplot.exe"".
本人使用的上边一种方法,事实上也符合下面的方式,为了保险起见。
这样设置就完成了,我们只需要到控制台下运行上面相应的四个程序即可.
注意:下面的python命令中,我们默认所有需要处理的样本数据集都是放在在tools目录下,如果数据文件不在tools目录下则我们需要用绝对路径指定数据的位置.
如下目录结构:
Tools 和windows是直接从下载的libsvm2.88文件复制过来,只是在tools 中加入了guide.pdf的几个数据集,gnuplot直接下载后将gnuplot拷贝过来
只要简单输入,就可以完成svm挖掘的所有步骤,即:
1. Conduct simple scaling on the data
2.Consider the RBF kernel K(x; y)
3.Use cross-validation to nd the best parameter C and
4.Use the best parameter C and to train the whole training set
5.Test
对于初学者而言这个文件无非是他们的救命稻草,可以简单看看他的语法:
在控制台下走到easy.py所在的目录下:
(大体数据如下)
Scaling training data...归一化数据
Cross validation...在训练集上做交叉验证
Best c=128.0, g=0.125 CV rate=88.9186 (通过网格搜索法对每个参数对做交叉验证,选择交叉验证精度最高所对应的参数.)
Training...( 将上面得到的参数对在训练集合上做模型训练)
Output model: crttrain.model (保存模型到文件)
Scaling testing data... (归一化数据)
Testing...(用训练得出的模型对测试集进行测试)
Accuracy = 87.8049% (36/41) (classification)(测试的精度)
Output prediction: crttest.predict (输出预测结果)
(在交叉验证过程中,会有一个图形界面显示参数选择的情况,這就是gnuplot.exe的作用了)
在控制台下走到grid.py所在的目录下:
。。。。。。。。。。。
(c=32768.0,gamma=3.0517578125e-005 96.9893 交叉验证精度96.9893)
在控制台下走到subset.py所在的目录下:
$python subset.py train.1 100 train.2 test.2
参数说明:
crt:样本集合;
100:训练集样本个数;
crttrain:存储100个训练样本;
crttest:存储剩下的样本集做为测试集;
checkdata.py检测样本集存储格式是否正确
在控制台下走到subset.py所在的目录下:
$python checkdata.py crt
No error. (表示没有错)
不知什么缘故 我测试总是显示无用的组合。
详细的使用请参考tools下的README文件.
Grid-search 任就是花费很多时间的,我们推荐使用a coarse(粗糙) grid
(这个就是一个简单的演示,没有什么用的。)
在SVM-TOY上点击出现小点,在点击“run”,后面选择参数
最后单击“save”,用记事本打开查看
关于libsvm的数据格式:
a. FormatSplitBat.m是一个批量将以Tab或者空格分隔的数据转换为libsvm格式,并且分成占全部数据比例为p的训练集和1-p的测试集,然后调用easy.py的例子。
b. 手工转换数据格式,可以通过excel文件FormatDataLibsvm.xls打开包含数据的文本文件,然后用宏将数据转换为libsvm格式。也可以用宏将libsvm格式的数据转换回来。