scikit 学习中的 OneVsRestClassifier 和 MultiOutputClassifier 有什么区别?
What is the difference between OneVsRestClassifier and MultiOutputClassifier in scikit learn?
有人可以解释一下(也许可以举个例子)在 scikit-learn 中 OneVsRestClassifier and MultiOutputClassifier 之间的 区别 是什么?
我已阅读文档并且我知道我们使用:
- OneVsRestClassifier - 当我们想要进行多class或多标签class化时,它的策略包括为每个 class 安装一个 classifier。对于每个 classifier,class 与所有其他 classes 相匹配。 (这很清楚,这意味着 multiclass/multilabel classification 问题被分解为多个二进制 classification 问题)。
- MultiOutputClassifier - 当我们想要进行多目标 class化时(这是什么?)它的策略包括 为每个目标安装一个 classifier(目标是什么意思?)
我已经将 OneVsRestClassifier 用于多标签 classification,我可以理解它是如何工作的,但后来我发现了 MultiOutputClassifier,但无法理解它与 OneVsRestClassifier 的工作方式有何不同。
多class class化
为了更好地说明差异,让我们假设您的目标是 class将 SO 问题转化为 n_classes
不同的、互斥的 classes。在这个例子中为了简单起见,我们将只考虑四个 class,即 'Python'
、'Java'
、'C++'
和 'Other language'
。让我们假设您有一个仅由六个 SO 问题组成的数据集,并且这些问题的 class 标签存储在数组 y
中,如下所示:
import numpy as np
y = np.asarray(['Java', 'C++', 'Other language', 'Python', 'C++', 'Python'])
上述情况通常被称为multiclass classification(也称为多项式classification)。为了通过 scikit-learn 库拟合 classifier 并验证模型,您需要将文本 class 标签转换为数字标签。为此,您可以使用 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')
一个重要的特殊情况是只有两个 class,即 n_classes = 2
。这个通常叫做binary classification.
多标签class化
现在让我们假设您希望使用 n_classes
个二进制 class 化器池执行这样的多class class化,即 n_classes
不同 classes 的数量。这些二进制 class 中的每一个都会决定一个项目是否属于特定的 class 。在这种情况下,您不能将 class 标签编码为从 0
到 n_classes - 1
的整数,您需要创建一个二维指标矩阵。考虑样本 n
属于 class k
。那么,指标矩阵的 [n, k]
条目是 1
,行 n
中的其余元素是 0
。重要的是要注意,如果 classes 不是互斥的,则可以连续出现多个 1
。这种方法被命名为 multilabel classification 并且可以通过 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)
多输出class化
如果您想class同时根据两个不同的标准(例如语言和应用程序)确定一个特定的 SO 问题怎么办?在这种情况下,您打算执行 multioutput classification。为了简单起见,我将只考虑三个应用程序 classes,即 'Computer Vision'
、'Speech Processing
' 和 'Other application
'。数据集的标签数组应该是二维的:
y2 = np.asarray([['Java', 'Computer Vision'],
['C++', 'Speech Recognition'],
['Other language', 'Computer Vision'],
['Python', 'Other Application'],
['C++', 'Speech Recognition'],
['Python', 'Computer Vision']])
同样,我们需要将文本 class 标签转换为数字标签。据我所知,此功能尚未在 scikit-learn 中实现,因此您需要编写自己的代码。 This thread 描述了一些聪明的方法来做到这一点,但为了这个 post 的目的,以下一行就足够了:
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')
这是对@tonechas 回答的扩展。在阅读本文之前阅读该答案。只有当每个标签是二进制标签/class(也称为二进制多标签)时,OVR 才支持多标签,即样本属于该标签或不属于该标签。当目标是多输出(也称为多 class 多标签)时,即当每个样本可以属于标签内的任何一个 class 时,它将不起作用。对于后一种情况,您需要使用 sklearn Multioutput classifier.
换句话说,当你的目标变量看起来像这样时,sklearn OVR 不起作用,
y_true = np.arr([[2, 1, 0],
[0, 2, 1],
[1, 2, 4]])
其中 label1 有 4 个 classes [0, 1, 2, 3]; label2 有 3 classes [0, 1, 2]; label3 有 5 classes [0, 1, 2, 3, 4]。例如:第一个样本在label1中属于class 2,在label2中属于class 1,在label3中属于class 0。 将其视为标签不互斥,而每个标签中的 classes 是互斥的。
Sklearn OVR 将在
y_true = np.arr([[0, 1, 1],
[0, 0, 1],
[1, 1, 0]])
其中 label1 labe2、label3 各只有 2 个 class。因此,样本要么属于该标签,要么不属于该标签。例:第一个样本属于label1和label2.
很抱歉,我找不到此类用例的真实示例。
Any answers on this? The accepted answer simply describes the concepts
but actually do not explicitly address OP's question of "What is the
difference between sklearn's OneVsRestClassifier and MultiOutputClassifier classes
我认为问题的作者自己回答了
MultiOutputClassifier - when we want to do multi target classification
(what is this?) and it's strategy consists of fitting one classifier
per target (what does target mean there?)
目标是 Y(相关变量)
P.S。
MultiClass 或 MultiLabel - 意思是“多”-标称 features - 被认为是 X 是独立的变量...(无论是多行或 feature_columns.count>1 分别 )
p.p.s。
我想在 sklearn 库内部对每个目标都有一个单独的训练(拟合)——关于作者的引用
有人可以解释一下(也许可以举个例子)在 scikit-learn 中 OneVsRestClassifier and MultiOutputClassifier 之间的 区别 是什么?
我已阅读文档并且我知道我们使用:
- OneVsRestClassifier - 当我们想要进行多class或多标签class化时,它的策略包括为每个 class 安装一个 classifier。对于每个 classifier,class 与所有其他 classes 相匹配。 (这很清楚,这意味着 multiclass/multilabel classification 问题被分解为多个二进制 classification 问题)。
- MultiOutputClassifier - 当我们想要进行多目标 class化时(这是什么?)它的策略包括 为每个目标安装一个 classifier(目标是什么意思?)
我已经将 OneVsRestClassifier 用于多标签 classification,我可以理解它是如何工作的,但后来我发现了 MultiOutputClassifier,但无法理解它与 OneVsRestClassifier 的工作方式有何不同。
多class class化
为了更好地说明差异,让我们假设您的目标是 class将 SO 问题转化为 n_classes
不同的、互斥的 classes。在这个例子中为了简单起见,我们将只考虑四个 class,即 'Python'
、'Java'
、'C++'
和 'Other language'
。让我们假设您有一个仅由六个 SO 问题组成的数据集,并且这些问题的 class 标签存储在数组 y
中,如下所示:
import numpy as np
y = np.asarray(['Java', 'C++', 'Other language', 'Python', 'C++', 'Python'])
上述情况通常被称为multiclass classification(也称为多项式classification)。为了通过 scikit-learn 库拟合 classifier 并验证模型,您需要将文本 class 标签转换为数字标签。为此,您可以使用 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')
一个重要的特殊情况是只有两个 class,即 n_classes = 2
。这个通常叫做binary classification.
多标签class化
现在让我们假设您希望使用 n_classes
个二进制 class 化器池执行这样的多class class化,即 n_classes
不同 classes 的数量。这些二进制 class 中的每一个都会决定一个项目是否属于特定的 class 。在这种情况下,您不能将 class 标签编码为从 0
到 n_classes - 1
的整数,您需要创建一个二维指标矩阵。考虑样本 n
属于 class k
。那么,指标矩阵的 [n, k]
条目是 1
,行 n
中的其余元素是 0
。重要的是要注意,如果 classes 不是互斥的,则可以连续出现多个 1
。这种方法被命名为 multilabel classification 并且可以通过 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)
多输出class化
如果您想class同时根据两个不同的标准(例如语言和应用程序)确定一个特定的 SO 问题怎么办?在这种情况下,您打算执行 multioutput classification。为了简单起见,我将只考虑三个应用程序 classes,即 'Computer Vision'
、'Speech Processing
' 和 'Other application
'。数据集的标签数组应该是二维的:
y2 = np.asarray([['Java', 'Computer Vision'],
['C++', 'Speech Recognition'],
['Other language', 'Computer Vision'],
['Python', 'Other Application'],
['C++', 'Speech Recognition'],
['Python', 'Computer Vision']])
同样,我们需要将文本 class 标签转换为数字标签。据我所知,此功能尚未在 scikit-learn 中实现,因此您需要编写自己的代码。 This thread 描述了一些聪明的方法来做到这一点,但为了这个 post 的目的,以下一行就足够了:
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')
这是对@tonechas 回答的扩展。在阅读本文之前阅读该答案。只有当每个标签是二进制标签/class(也称为二进制多标签)时,OVR 才支持多标签,即样本属于该标签或不属于该标签。当目标是多输出(也称为多 class 多标签)时,即当每个样本可以属于标签内的任何一个 class 时,它将不起作用。对于后一种情况,您需要使用 sklearn Multioutput classifier.
换句话说,当你的目标变量看起来像这样时,sklearn OVR 不起作用,
y_true = np.arr([[2, 1, 0],
[0, 2, 1],
[1, 2, 4]])
其中 label1 有 4 个 classes [0, 1, 2, 3]; label2 有 3 classes [0, 1, 2]; label3 有 5 classes [0, 1, 2, 3, 4]。例如:第一个样本在label1中属于class 2,在label2中属于class 1,在label3中属于class 0。 将其视为标签不互斥,而每个标签中的 classes 是互斥的。
Sklearn OVR 将在
y_true = np.arr([[0, 1, 1],
[0, 0, 1],
[1, 1, 0]])
其中 label1 labe2、label3 各只有 2 个 class。因此,样本要么属于该标签,要么不属于该标签。例:第一个样本属于label1和label2.
很抱歉,我找不到此类用例的真实示例。
Any answers on this? The accepted answer simply describes the concepts but actually do not explicitly address OP's question of "What is the difference between sklearn's OneVsRestClassifier and MultiOutputClassifier classes
我认为问题的作者自己回答了
MultiOutputClassifier - when we want to do multi target classification (what is this?) and it's strategy consists of fitting one classifier per target (what does target mean there?)
目标是 Y(相关变量)
P.S。 MultiClass 或 MultiLabel - 意思是“多”-标称 features - 被认为是 X 是独立的变量...(无论是多行或 feature_columns.count>1 分别 )
p.p.s。 我想在 sklearn 库内部对每个目标都有一个单独的训练(拟合)——关于作者的引用