【问题标题】:Different accuracies across different svm libraries with same parameters on same data在相同数据上具有相同参数的不同 svm 库的不同精度
【发布时间】:2014-06-03 14:18:02
【问题描述】:

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

我的一个朋友做了同样的实验,但使用的 SVM 分类器来自Statistics Toolbox。他还使用了 R 的 e1071 包。同样,使用的内核是线性内核,参数成本 C 等于 1,并且在 MATLAB 中使用一对一的方法对数据进行分类(一对一的方法是由我的朋友编写的)和 e1071 R 包。默认情况下,R 中的 MATLAB Statistics Toolbox 和 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 都使用线性核,具有相同的成本参数并使用相同的方法进行多类分类,结果不应该是一样的吗?

【问题讨论】:

标签: r matlab svm libsvm liblinear


【解决方案1】:

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

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


MATLAB 在svmtrainfitcsvm 中有自己的实现。它只支持二分类,所以你必须手动处理多分类问题(见here的例子)。

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


现在对于libsvmliblinear,你应该知道实现在目标函数的制定上略有不同:

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

  • 另一方面,带有 L2 正则化 L1 损失 SVC 求解器的 liblinear 的对偶形式是:

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

此外,关于 k 类的多类问题,libsvm 默认通过构造 k*(k-1)/2 二进制分类器实现 one-against-one 方法,而 liblinear 实现 one-通过构造k 二元分类器来实现 vs-the-rest 策略(它还有一个由 Crammer 和 Singer 提出的用于处理多类问题的替代方法)。我之前已经展示了如何使用 libsvm 执行 one-vs-rest 分类(参见 herehere)。

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

  • 应通过调用svm-train.exe -s 0 -t 0 将libsvm 设置为具有线性内核的C-SVM 分类器
  • liblinear 求解器类型应设置为 L2R_L1LOSS_DUAL,方法是调用 train.exe -s 3(L2 正则化 L1 损失支持向量分类器的双重形式)
  • 成本参数显然应该与两个训练函数的 -c 1 匹配
  • 终止标准的容差应该匹配(-e 参数的默认值在两个库之间有所不同,e=0.001 用于 libsvm,e=0.1 用于 liblinear)
  • 应该明确指示liblinear 添加一个偏置项,因为它默认是禁用的(通过添加train.exe -B 1)。

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

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

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

【讨论】:

  • 感谢您的回答,我很满意。但是让我问你另一个问题:你可以在上面的源代码中看到我正在使用线性内核缩放 LIBSVM 中的数据,但是,在我自己的 Matlab 中的一对一 svm 实现中也使用线性内核,我没有吨。我们知道缩放数据会产生更准确的分类器,但是 LIBSVM 的缩放精度低于 matlab 的二进制分类器的一对一实现。这两个分类器还有什么不同?
猜你喜欢
  • 2012-06-24
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-28
  • 2014-04-19
  • 2016-02-12
  • 2017-12-25
相关资源
最近更新 更多