不同svm库的不同精度在相同数据上具有相同参数

时间:2014-04-19 01:43:33

标签: r matlab svm libsvm liblinear

我正在使用libsvm,我做了一个非常简单的实验,训练10k向量并仅用22进行测试。我正在使用参数成本为C=1的线性内核。我的问题是多类。所以Libsvm将使用一对一的方法对我的数据进行分类。 Libsvm使用SMO来查找分离超平面。

我的一位朋友做了同样的实验,但使用的SVM分类器来自Statistics Toolbox。他还使用了来自R的e1071包。再次,使用的内核是线性内核,参数cost C等于1,并且使用一对一方法对数据进行分类在MATLAB(一对一的方法由我的朋友编码)和e1071 R包。 MATLAB统计工具箱和R的e1071都默认使用SMO方法查找分离超平面。

我还尝试了最新的LIBLINEAR库。同样,使用了相同的配置。


以下是使用的代码:

libsvm 3.18(命令行)

./svm-scale -s train.range train.libsvm > train.scale 
./svm-scale -r train.range test.libsvm > test.scale
./svm-train -t 0 -c 1 train.scale train.model
./svm-predict test.scale train.model test.predict

liblinear 1.94(命令行)

./svm-scale -s train.range train.libsvm > train.scale 
./svm-scale -r train.range test.libsvm > test.scale
./train train.scale train.model
./predict test.scale train.model test.predict

- [R

rm(list = ls())
cat("\014")
library(e1071)

cat("Training model\n")
Traindata = read.csv("train.csv", header=FALSE)
SVM_model = svm(Traindata[,2:ncol(Traindata)], Traindata[,1], kernel="linear",     tolerance=0.1, type="C-classification")
print(SVM_model)

cat("Testing model\n")
Testdata = read.csv("test.csv", header=FALSE)
Preddata = predict(SVM_model, Testdata[,2:ncol(Testdata)])

ConfMat = table(pred=Preddata, true=Testdata[,1])
print(ConfMat)

accuracy = 0
for (i in 1 : nrow(ConfMat)) {
   for (j in 1 : ncol(ConfMat)) {
       if (i == j) {
          accuracy = accuracy + ConfMat[i, i]
       }
   }
 }
 accuracy = (accuracy / sum(ConfMat)) * 100
 cat("Test vectors:", dim(Testdata), ", Accuracy =", accuracy, "%\n")

有一些准确性差异:

  • Libsvm正确分类了22个测试特征向量中的11个
  • Liblinear正确分类了22个测试特征向量中的18个
  • R正确分类了22个测试特征向量中的17个
  • 我的朋友的一对一MATLAB实现正确地分类了22个特征向量中的19个。

为什么预测会有所不同?我的意思是,如果所有SVM使用线性内核,使用相同的成本参数并使用相同的方法进行多类分类,那么结果是否应该相同?

1 个答案:

答案 0 :(得分:8)

首先让我解决R解决方案;据我所知,e1071包只是libsvm库的包装器。因此,假设您在两者中使用相同的设置和步骤,您应该得到相同的结果。

我自己不是普通的R用户,但我可以告诉你,你没有在R代码中执行数据规范化(为了将功能扩展到[-1,1]范围)。我们知道SVM不是尺度不变的,所以这个省略应该解释与其他结果的区别。


MATLAB在svmtrainfitcsvm中有自己的实现。它只支持二进制分类,因此您必须手动处理多类问题(例如,请参阅here)。

documentation解释说它使用标准SMO算法(实际上是为解决quadratic-programming优化问题而提供的三种可能算法之一)。文档列出了底部的几本书和论文作为参考。原则上,您应该获得与libsvm类似的预测(假设您复制使用的参数并对数据应用相同类型的预处理)。


至于libsvmliblinear,你应该知道在实现目标函数时,实现有所不同:

  • libsvm解决了以下双重问题: libsvm dual problem

  • 另一方面,具有L2正则化L1损失SVC求解器的双线形liblinear是: liblinear dual problem

...更不用说算法在编写时考虑了不同的目标:libsvm以允许在不同内核函数之间切换的方式编写,而liblinear被优化为始终是线性的,根本没有内核概念。这就是为什么libsvm不容易适用于大规模问题(即使使用线性内核),并且当你有大量实例时,通常建议使用liblinear。

此外,关于k类的多类问题,libsvm默认通过构造k*(k-1)/2二元分类器实现一对一方法,而liblinear实现<通过构建k二元分类器(它还有一个Crammer和Singer用于处理多类问题的替代方法),强大的“一对一策略”。我之前已经展示了如何使用libsvm执行one-rest-rest分类(请参阅herehere)。

您还必须确保匹配传递给每个参数的参数(尽可能接近):

  • 应通过调用svm-train.exe -s 0 -t 0
  • 将libsvm设置为带线性内核的C-SVM分类器
  • 通过调用L2R_L1LOSS_DUAL(L2正则化L1损失支持向量分类器的双重形式),应将liblinear解算器类型设置为train.exe -s 3
  • 对于两个培训功能
  • ,费用参数显然应与-c 1匹配
  • 终止条件的容差应该匹配(-e参数的默认值在两个库之间不同,libsvm为e=0.001,liblinear为e=0.1
  • 应明确指示liblinear添加偏见词,因为默认情况下它被禁用(通过添加train.exe -B 1)。

即便如此,我也不确定你们两者会得到完全相同的结果,但是预测应该足够接近...

其他考虑因素包括库如何处理分类功能。例如,我知道libsvm将具有m个可能值的分类特征转换为m数字0-1特征,这些特征被编码为二进制指示符属性(即,其中只有一个是一个,其余为零)。我不确定liblinear对离散特征的作用。

另一个问题是特定实现是否具有确定性,并且在使用相同设置对相同数据重复时始终返回相同的结果。我已经读过liblinear内部在其工作期间生成随机数的地方,但请不要在没有实际检查源代码的情况下接受我的话:)