首页 > 解决方案 > scikit-learn 在多类分类中是否默认使用 One-Vs-Rest?

问题描述

我正在处理一个多类问题(4 个类),我正在尝试用 Python 中的 scikit-learn 来解决它。

我看到我有三个选择:

  1. 我只是简单地实例化一个分类器,然后我适合训练并用测试评估;

    classifier = sv.LinearSVC(random_state=123)
    classifier.fit(Xtrain, ytrain)
    classifier.score(Xtest, ytest)
    
  2. 我将实例化的分类器“封装”在 OneVsRest 对象中,生成一个用于训练和测试的新分类器;

    classifier = OneVsRestClassifier(svm.LinearSVC(random_state=123))
    classifier.fit(Xtrain, ytrain)
    classifier.score(Xtest, ytest)
    
  3. 我将实例化的分类器“封装”在 OneVsOne 对象中,生成一个用于训练和测试的新分类器。

    classifier = OneVsOneClassifier(svm.LinearSVC(random_state=123))
    classifier.fit(Xtrain, ytrain)
    classifier.score(Xtest, ytest)
    

我了解 OneVsRest 和 OneVsOne 之间的区别,但我无法理解在第一种情况下我在做什么,我没有明确选择这两个选项中的任何一个。在这种情况下 scikit-learn 会做什么?它是否隐式使用 OneVsRest?

对此事的任何澄清将不胜感激。

最好的,先生

编辑:为了清楚起见,我对 SVM 的情况并不特别感兴趣。例如,RandomForest 呢?

标签: pythonmachine-learningscikit-learnmulticlass-classification

解决方案


更新的答案:正如评论和编辑中所阐明的那样,问题更多的是关于 sklearn 的一般设置,而不是关于LinearSVC下面解释的具体情况。

这里的主要区别是您可以使用的一些分类器具有“内置多类分类支持”,即默认情况下该算法可以区分两个以上的类。例如,一个示例是随机森林,或具有多个输出节点的多层感知器 (MLP)。

在这些情况下,OneVs根本不需要拥有一个对象,因为您已经在解决您的任务。事实上,使用这样的策略甚至可能会降低您的性能,因为您通过让算法仅在单个二进制实例之间做出决定,从而“隐藏”了算法的潜在相关性。

另一方面,算法喜欢SVCLinearSVC只支持二进制分类。因此,为了扩展这些(性能良好的)算法类别,我们不得不依赖从最初的多类分类任务到二元分类任务的简化。

据我所知,最完整的概述可以在这里找到:如果向下滚动一点,您可以看到其中一种算法本质上是多类的,或者默认使用其中一种策略。
请注意,OVO 下列出的所有算法实际上现在默认采用 OVR 策略!在这方面,这似乎是稍微过时的信息。

初步答案

这个问题可以通过查看相关的 scikit-learn 文档轻松回答。
通常,对 Stackoverflow 的期望是您至少自己完成了某种形式的研究,因此请考虑先查看现有文档。

multi_class : string, 'ovr' 或 'crammer_singer' (default='ovr')

如果 y 包含两个以上的类,则确定多类策略。"ovr"训练 n_classes one-vs-rest 分类器,同时 "crammer_singer"优化所有类的联合目标。虽然从理论的角度来看,crammer_singer 很有趣,因为它是一致的,但它很少在实践中使用,因为它很少能带来更好的准确性并且计算成本更高。如果"crammer_singer"选择,选项损失、惩罚和对偶将被忽略。

所以,很明显,它使用一对一休息。

顺便说一句,“常规” SVC也是如此。


推荐阅读