LinearSVC和SVC(kernel="linear")有什么区别?

17

我发现sklearn.svm.LinearSVCsklearn.svm.SVC(kernel='linear')非常相似,但在Reuters上的结果却截然不同。

sklearn.svm.LinearSVC: 81.05% in   28.87s train /    9.71s test
sklearn.svm.SVC      : 33.55% in 6536.53s train / 2418.62s test

两者都有线性核。LinearSVC的容忍度比SVC高:

LinearSVC(C=1.0, tol=0.0001, max_iter=1000, penalty='l2', loss='squared_hinge', dual=True, multi_class='ovr', fit_intercept=True, intercept_scaling=1)
SVC      (C=1.0, tol=0.001,    max_iter=-1, shrinking=True, probability=False, cache_size=200, decision_function_shape=None)

两个函数除此之外还有什么不同?即使我将kernel='linear'tol=0.0001max_iter=1000decision_function_shape='ovr'设置为相同,SVC的运行时间仍比LinearSVC长得多。为什么?
我使用的是sklearn 0.18,并且两者都包含在OneVsRestClassifier中。我不确定这是否与multi_class='ovr' / decision_function_shape='ovr'相同。

你能否升级到0.18.2版本,看看结果是否仍然不同? - seralouk
我相信版本不是问题。sklearn 文档包含了拟合这些分类器的示例。由于模型所采用的方法不同,因此结果也有所不同。 - E.Z
已经有一些关于它的讨论了,或许可以去看看这些链接: https://dev59.com/YFsX5IYBdhLWcg3wau4r 以及 https://dev59.com/oFsW5IYBdhLWcg3wVmKV - phev8
文档说明它们使用不同的实现,甚至使用来自sklearn的方法或直接访问低级实现可能会导致不同的分数。 - phev8
2个回答

27

事实上,LinearSVCSVC(kernel='linear')产生不同的结果,即评估分数和决策边界,因为它们使用不同的方法。下面的玩具示例证明了这一点:

from sklearn.datasets import load_iris
from sklearn.svm import LinearSVC, SVC

X, y = load_iris(return_X_y=True)

clf_1 = LinearSVC().fit(X, y)  # possible to state loss='hinge'
clf_2 = SVC(kernel='linear').fit(X, y)

score_1 = clf_1.score(X, y)
score_2 = clf_2.score(X, y)

print('LinearSVC score %s' % score_1)
print('SVC score %s' % score_2)

--------------------------
>>>    0.96666666666666667
>>>    0.98666666666666669

这种差异的关键原则如下:

  • 通过默认缩放,LinearSVC 最小化平方铰链损失,而 SVC 最小化常规铰链损失。可以在 LinearSVCloss 参数中手动定义“铰链”字符串。
  • LinearSVC 使用 One-vs-All(也称为 一对多)多类别减少,而 SVC 使用 一对一 多类别减少。这也在这里提到。此外,在多类分类问题上,SVC 适配了 N * (N - 1) / 2 个模型,其中 N 是类别数量。相比之下,LinearSVC 只是简单地适配了 N 个模型。如果分类问题是二进制的,则两种情况下都只适配一个模型。multi_classdecision_function_shape 参数没有共同点。第二个参数是一个聚合器,将决策函数的结果转换为方便的形式 (n_features, n_samples)multi_class 是一种算法方法,用于确定解决方案。
  • LinearSVC 的基础估算器是 liblinear,它实际上对拦截进行惩罚。SVC 使用不会对其进行惩罚的 libsvm 估算器。liblinear 估算器针对线性(特殊)情况进行了优化,因此在大量数据上更快地收敛而 libsvm。这就是为什么 LinearSVC 解决问题所需的时间较短的原因。

实际上,就像在评论部分中所述,LinearSVC 在拦截缩放后并不是真正的线性。



在scikit-learn的官方文档中,似乎数学公式并没有表明截距被惩罚。或者是我理解有误? - John Smith

-1
它们之间的主要区别在于linearsvc只允许您选择线性分类器,而svc允许您从多种非线性分类器中进行选择。然而,不建议将svc用于非线性问题,因为它们速度非常慢。尝试导入其他库以进行非线性分类。
现在即使定义了kernel='linear',我们也无法获得相同的输出,这是因为linearsvc和svc在执行背景数学时采用了不同的方法。此外,linearsvc基于one-vs-rest原则工作,而svc基于one-vs-one原则工作。
希望这回答了您的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接