首先我们要下载libsvm jar包,然后我把svm_train,svm_scale,svm_predict三个类文件复制了出来,主要是了解一下内部实现。接着准备好训练数据集合测试数据集。数据文件格式如下,label是类别,index是feature即特征或者维,value是对应特征值。
[label] [index1]:[value1] [index2]:[value2] ... [label] [index1]:[value1] [index2]:[value2] ...
接下来就要开始对数据进行归一化处理,用到svm_scale类。
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 scaling limits (default: no y scaling) -s save_filename : save scaling parameters to save_filename -r restore_filename : restore scaling parameters from restore_filename
这里特别解释下-s -r参数,-s参数指定保存svm_scale扫描过后的归一化scale标准,-r表示读入的标准。我们因为同时要考虑训练集和测试集,所以这里需要两个参数。libsvm这里采用的是最大最小值归一化,默认的归一化范围是[-1,1],可以用参数-l和-u分别调整上界和下界,java代码如下。
String[] testArgs = {"-l","0", "-u","1","-s","chao-test-scale","UCI-breast-cancer-tra"}; svm_scale.main(testArgs); String[] argvScaleTest ={"-r","chao-test-scale","UCI-breast-cancer-test"}; svm_scale.main(testArgs);
执行完之后生成的chao-test-scale文件里面就是最后的scale标准,文件内容如下:
x 0.000000000000000 1.000000000000000 1 63375.00000000000 13454352.00000000 2 1.000000000000000 10.00000000000000 3 1.000000000000000 10.00000000000000 4 1.000000000000000 10.00000000000000 5 1.000000000000000 10.00000000000000 6 1.000000000000000 10.00000000000000 7 1.000000000000000 10.00000000000000 8 1.000000000000000 10.00000000000000 9 1.000000000000000 10.00000000000000 10 1.000000000000000 10.00000000000000
文件里面列出了归一化的区间0-1,每个feature的最大最小值,便于后面对整个集合做scale处理。有的遗憾的是svm_scale类没有直接提供参数指定生成scale的文件,不过它在执行过程中会输出整个scale后的文件,我们可以通过控制台直接重定向到新文件里面。
java svm_scale -s chao-test-scale train>train.scale java svm_scale -s chao-test-scale test>test.scale
这样就将train训练集和test测试集全部scale成功,我们就可以开始训练和检测了,分别使用svm_train和svm_predict。
String[] trainArgs = {"train.scale"}; String modelFile = svm_train.main(trainArgs); String[] testArgs = {"test.scale", modelFile, "result"}; Double accuracy = svm_predict.main(testArgs); System.out.println("SVM Classification is done! The accuracy is " + accuracy);
另外从网上看到的使用libsvm的步骤如下:
1)按照LIBSVM软件包所要求的格式准备数据集; 2)对数据进行简单的缩放操作; 3)首要考虑选用RBF 核函数; 4)采用交叉验证选择最佳参数C与g ; 5)采用最佳参数C与g 对整个训练集进行训练获取支持向量机模型; 6)利用获取的模型进行测试与预测。
对应第4和5步,目前正在研究阶段,了解到的只能使用grid.py来查找最佳参数,这里偷懒贴个链接LibSVM学习(六)——easy.py和grid.py的使用 http://blog.csdn.net/flydreamgg/article/details/4470477。 需要重点说明的是,用grid.py找到的
最佳参数c和g是使得训练集在交叉验证思想下达到最高准确率的,不能保证使用这个参数训练之后的模型就能让测试集也能达到对应的正确率。我经过测试找到的0.5 0.125代入之后训练,准确率没有发生变化,依然是0.8974358974358975。
归一化处理可以加快运算速度,提高预测准确率==(这里加个疑问:有说法是看具体情况,有的情况归一化之后反而正确率下降。)。下面贴一下数据归一化之前的运行结果。
optimization finished, #iter = 1223 nu = 0.6996186233933985 obj = -271.992875483972, rho = 0.4257786283326366 nSV = 639, nBSV = 222 Total nSV = 639 Accuracy = 69.23076923076923% (27/39) (classification) SVM Classification is done! The accuracy is 0.6923076923076923
归一之后的运行结果
optimization finished, #iter = 68 nu = 0.08154427324315143 obj = -44.22486456942005, rho = -0.8163705353889562 nSV = 61, nBSV = 48 Total nSV = 61 Accuracy = 89.74358974358975% (35/39) (classification) SVM Classification is done! The accuracy is 0.8974358974358975
后续:
后面接着实践,发现了所谓的归一化之后文件增大,运算速度和准确率下降的情况,但是这个情况最后可以通过修改归一化的方式或者参数来解决,其实就是归一化的方式不正确导致的正确率下降的问题。