scikit learn中的OneVsRestClassifier和MultiOutputClassifier有什么区别?

40
请问有人能解释一下(最好附上示例),scikit-learn中OneVsRestClassifierMultiOutputClassifier之间的区别是什么?
我已经阅读了文档并理解了:
- 当我们想进行多类别或多标签分类时,使用 OneVsRestClassifier ,其策略是每个类别拟合一个分类器。对于每个分类器,该类别被拟合到所有其他类别上。(这很清楚,意味着多类别/多标签分类问题被分解为多个二元分类问题)。 - 当我们想进行多目标分类时,使用 MultiOutputClassifier ,其策略是每个目标拟合一个分类器(那里的目标是什么?)。

我已经使用了OneVsRestClassifier进行多标签分类,并且我可以理解它的工作原理,但是后来我发现了MultiOutputClassifier,无法理解它与OneVsRestClassifier有何不同。

3个回答

39

多类分类

为了更好地说明差异,假设您的目标是将SO问题分类为n_classes个不同的互斥类。在本例中,为了简单起见,我们只考虑四个类,即'Python''Java''C++''Other language'。假设您有一个由六个SO问题组成的数据集,并且这些问题的类标签存储在数组y中,如下所示:

import numpy as np
y = np.asarray(['Java', 'C++', 'Other language', 'Python', 'C++', 'Python'])

上述情况通常被称为多类分类(也称为多项式分类)。为了适应分类器并通过scikit-learn库验证模型,您需要将文本类标签转换为数字标签。为此,您可以使用LabelEncoder
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y_numeric = le.fit_transform(y)

这是数据集标签的编码方式:
In [220]: y_numeric
Out[220]: array([1, 0, 2, 3, 0, 3], dtype=int64)

这些数字表示以下数组的索引:

In [221]: le.classes_
Out[221]: 
array(['C++', 'Java', 'Other language', 'Python'], 
      dtype='|S14')

重要的一个特殊情况是只有两个类,即 n_classes = 2。这通常被称为二元分类

多标签分类

现在假设您希望使用一组 n_classes 个二元分类器进行多类分类,其中 n_classes 是不同类别的数量。每个二元分类器都会决定一个项目是否属于特定的类别。在这种情况下,您不能将类标签编码为从 0n_classes-1 的整数,而需要创建一个二维指示矩阵。考虑样本 n 属于类别 k。然后,指示矩阵的 [n,k] 条目为 1,行 n 中其余元素为 0。需要注意的是,如果类别不是相互排斥的,则行中可以有多个 1。此方法称为多标签分类,可以通过 MultiLabelBinarizer 轻松实现:

from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
y_indicator = mlb.fit_transform(y[:, None])

指示器长这样:
In [225]: y_indicator
Out[225]: 
array([[0, 1, 0, 0],
       [1, 0, 0, 0],
       [0, 0, 1, 0],
       [0, 0, 0, 1],
       [1, 0, 0, 0],
       [0, 0, 0, 1]])

而“1”所在的列数实际上是该数组的索引:

In [226]: mlb.classes_
Out[226]: array(['C++', 'Java', 'Other language', 'Python'], dtype=object)

多输出分类

如果你想根据两个不同的标准同时对一个特定的SO问题进行分类,比如语言和应用程序,那么你就需要进行多输出分类。为了简单起见,我将只考虑三个应用程序类别,分别是'计算机视觉''语音处理''其他应用程序'。你的数据集的标签数组应该是二维的:

y2 = np.asarray([['Java', 'Computer Vision'],
                 ['C++', 'Speech Recognition'],
                 ['Other language', 'Computer Vision'],
                 ['Python', 'Other Application'],
                 ['C++', 'Speech Recognition'],
                 ['Python', 'Computer Vision']])

再次,我们需要将文本类标签转换为数字标签。据我所知,scikit-learn尚未实现此功能,因此您需要编写自己的代码。这个帖子描述了一些聪明的方法来完成这个任务,但是为了本文的目的,以下一行代码就足够了:

y_multi = np.vstack((le.fit_transform(y2[:, i]) for i in range(y2.shape[1]))).T

编码后的标签看起来像这样:
In [229]: y_multi
Out[229]: 
array([[1, 0],
       [0, 2],
       [2, 0],
       [3, 1],
       [0, 2],
       [3, 0]], dtype=int64)

每列数值的含义可以从以下数组中推断出来:
In [230]: le.fit(y2[:, 0]).classes_
Out[230]: 
array(['C++', 'Java', 'Other language', 'Python'], 
      dtype='|S18')

In [231]: le.fit(y2[:, 1]).classes_
Out[231]: 
array(['Computer Vision', 'Other Application', 'Speech Recognition'], 
      dtype='|S18')

43
这个回答虽然有启发性,但实际上并没有回答 OP 的问题:“sklearn 的 OneVsRestClassifier 和 MultiOutputClassifier 类之间的 区别是什么。” - Austin A
1
这可能会导致编辑,但OneVsRestClassifier适用于多标签分类(如果Y是矩阵)或多类分类(如果y是1d数组),而MultiOutputClassifier专门针对多输出分类。此外,据我所知,多输出分类仅适用于不同的多类分类。 - Edgar
有关此问题的任何答案吗?被接受的答案仅描述了概念,实际上并没有明确回答OP的问题:“sklearn的OneVsRestClassifier和MultiOutputClassifier类之间有什么区别?” - Soyol

6

这是对@tonechas答案的扩展。在阅读本文之前,请先阅读那个答案。当每个标签都是二进制标签/类别(也称为二进制多标签),即样本属于该标签或不属于该标签时,OVR支持Multilabel。当目标是multi-output(也称为multi-class multi-label)时,即每个样本可以属于标签内的任何一个类别时,它将无法正常工作。对于后一种情况,您需要使用sklearn Multioutput分类器。

换句话说,当您的目标变量如下所示时,sklearn OVR无法正常工作:

y_true = np.arr([[2, 1, 0],
                 [0, 2, 1],
                 [1, 2, 4]])
有4个类[0、1、2、3]; 有3个类[0、1、2]; 有5个类[0、1、2、3、4]。例如:第一个样本属于标签中的2类,属于中的1类,属于中的0类。将其视为标签不是相互独立的,而每个标签内的类是相互独立的。

当标签之间不相互排斥而每个标签内的类别相互排斥时,Sklearn OVR可用。

y_true = np.arr([[0, 1, 1],
                 [0, 0, 1],
                 [1, 1, 0]])

其中label1、label2和label3只有2个类别。因此,一个样本要么属于该标签,要么不属于。例如:第一个样本属于label1和label2。

很抱歉我找不到这种用例的现实世界示例。


一个玩具示例可能是你正在尝试将乐高积木分类为形状 - 矩形、正方形等,并且对于每种形状,你想知道该积木有哪些不同的颜色;例如:粉色、红色、绿色等。 - Bikash Gyawali

0
有任何解答吗?被采纳的答案仅仅描述了相关的概念,并没有明确回答 OP 的问题,即“sklearn 中 OneVsRestClassifier 和 MultiOutputClassifier 类之间的区别是什么?”我认为提问者自己已经回答了。
MultiOutputClassifier - 当我们需要进行多目标分类时(这是什么?),它的策略是为每个目标拟合一个分类器(目标在这里指什么?)。 目标是 Y(因变量)。
附注: MultiClass 或 MultiLabel 表示多重-名义特征-正在考虑作为独立变量 X(无论是在行中还是在 feature_columns.count > 1 中)。
再附注: 我想 sklearn 库内部对每个目标分别进行独立的训练(拟合),这是作者引语中涉及到的。

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