1.12. 多类和多输出算法#

用户指南的这一部分涵盖与多重学习问题相关的功能,包括 multiclass , multilabel ,而且 multioutput 分类和回归。

本节中的模块实现 meta-estimators ,需要在其构造函数中提供基本估计器。元估计器扩展了基本估计器的功能以支持多学习问题,这是通过将多学习问题转换为一组更简单的问题,然后为每个问题适应一个估计器来实现的。

本节涵盖两个模块: sklearn.multiclasssklearn.multioutput .下图展示了每个模块负责的问题类型以及每个模块提供的相应元估计器。

../_images/multi_org_chart.png

下表提供了有关问题类型之间差异的快速参考。更详细的解释请参阅本指南的后续部分。

目标数

目标基数

有效 type_of_target

多类分类

1

>2个

“多类”

多标签分类

>1

2(0或1)

“多标签指示器”

多类多输出分类

>1

>2个

“多类多输出”

多输出回归

>1

连续

“连续多输出”

下面是scikit-learn估计器的总结,这些估计器内置了多学习支持,按策略分组。如果您正在使用这些估计器之一,则不需要本节提供的元估计器。然而,元估计器可以提供内置之外的其他策略:

1.12.1. 多类分类#

警告

scikit-learn中的所有分类器都能进行开箱即用的多类分类。您不需要使用 sklearn.multiclass 模块,除非您想尝试不同的多类策略。

Multiclass classification 是具有两个以上类别的分类任务。每个样本只能标记为一个类别。

例如,使用从一组水果图像中提取的特征进行分类,其中每个图像可能是橙子、苹果或梨。每张图像都是一个样本,并被标记为3个可能的类别之一。多类分类假设每个样本被分配给一个且仅一个标签-例如,一个样本不能同时是梨和苹果。

虽然所有scikit-learn分类器都能够进行多类分类,但 sklearn.multiclass 允许改变处理两个以上类的方式,因为这可能会对分类器性能产生影响(无论是在概括误差方面还是所需的计算资源方面)。

1.12.1.1. 目标格式#

Valid multiclass representations for type_of_target (y) are:

  • 包含两个以上离散值的一维或列载体。载体的示例 y 对于4个样本:

    >>> import numpy as np
    >>> y = np.array(['apple', 'pear', 'apple', 'orange'])
    >>> print(y)
    ['apple' 'pear' 'apple' 'orange']
    
  • 密集或稀疏 binary 形状矩阵 (n_samples, n_classes) 每行有一个样本,其中每列代表一个类别。密集和稀疏的例子 binary 矩阵 y 对于4个样本,其中列按顺序为苹果、橙子和梨:

    >>> import numpy as np
    >>> from sklearn.preprocessing import LabelBinarizer
    >>> y = np.array(['apple', 'pear', 'apple', 'orange'])
    >>> y_dense = LabelBinarizer().fit_transform(y)
    >>> print(y_dense)
    [[1 0 0]
     [0 0 1]
     [1 0 0]
     [0 1 0]]
    >>> from scipy import sparse
    >>> y_sparse = sparse.csr_matrix(y_dense)
    >>> print(y_sparse)
    <Compressed Sparse Row sparse matrix of dtype 'int64'
      with 4 stored elements and shape (4, 3)>
      Coords Values
      (0, 0) 1
      (1, 2) 1
      (2, 0) 1
      (3, 1) 1
    

的更多信息 LabelBinarizer ,参考 转换预测目标 (y ) .

1.12.1.2. OneVsRestClassifier#

one-vs-rest 策略,也称为 one-vs-all ,实施于 OneVsRestClassifier . 该策略包括每个类拟合一个分类器。对于每个分类器,该类别与所有其他类别进行拟合。除了计算效率(仅 n_classes 需要分类器),这种方法的一个优点是它的可解释性。由于每个类由一个且仅一个分类器表示,因此可以通过检查其相应的分类器来获得有关该类的知识。这是最常用的策略,也是一个公平的默认选择。

以下是使用OvR的多类学习示例::

>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsRestClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> OneVsRestClassifier(LinearSVC(random_state=0)).fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

OneVsRestClassifier 还支持多标签分类。要使用此功能,请向分类器提供指示矩阵,其中单元格 [i, j] 指示样本i中存在标签j。

../_images/sphx_glr_plot_multilabel_001.png

示例

1.12.1.3. OneVsOneClassifier#

OneVsOneClassifier 每对类构造一个分类器。在预测时,选择获得最多选票的班级。如果平局(在具有相同票数的两个类别之间),它会通过对基础二进制分类器计算的成对分类置信度水平进行相加来选择具有最高总分类置信度的类别。

因为它需要合身 n_classes * (n_classes - 1) / 2 分类器中,由于其复杂性为O(n_classes#2),这种方法通常比一对其余方法慢。然而,这种方法对于诸如内核算法等无法很好地扩展的算法可能是有利的 n_samples .这是因为每个单独的学习问题只涉及数据的一小部分,而在一对一的情况下,使用的是完整的数据集 n_classes 次决策函数是一对一分类单调变换的结果。

以下是使用OvO的多类学习示例::

>>> from sklearn import datasets
>>> from sklearn.multiclass import OneVsOneClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> OneVsOneClassifier(LinearSVC(random_state=0)).fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

引用

  • “模式识别和机器学习。施普林格”,克里斯托弗·M。毕肖普,第183页,(第一版)

1.12.1.4. OutputCodeClassifier#

基于错误纠正输出代码的策略与一对一和一对一有很大不同。通过这些策略,每个类都在欧几里得空间中表示,其中每个维度只能为0或1。另一种说法是,每个类都由二进制代码(0和1的数组)表示。跟踪每个类的位置/代码的矩阵称为代码本。代码大小是上述空间的维度。直观地说,每个类都应该用尽可能唯一的代码来表示,并且应该设计一个好的代码簿来优化分类准确性。在这个实现中,我们简单地使用随机生成的代码本,正如中所提倡的那样 [3] 尽管将来可能会添加更复杂的方法。

在匹配时,代码本中的每个比特都匹配一个二进制分类器。在预测时,使用分类器在类空间中投影新点,并选择最接近这些点的类。

OutputCodeClassifiercode_size 属性允许用户控制将使用的分类器的数量。占班级总数的百分比。

0和1之间的数字需要的分类器比1和其余数字更少。理论上, log2(n_classes) / n_classes 足以明确地表示每个类。然而,在实践中,它可能不会带来良好的准确性,因为 log2(n_classes) 远小于 n_classes .

大于1的数字将需要比1更多的分类器。在这种情况下,一些分类器理论上会纠正其他分类器犯的错误,因此得名“错误纠正”。然而,在实践中,这可能不会发生,因为分类器错误通常是相互关联的。错误纠正输出代码具有与bagging类似的效果。

以下是使用Output-Codes的多类学习示例::

>>> from sklearn import datasets
>>> from sklearn.multiclass import OutputCodeClassifier
>>> from sklearn.svm import LinearSVC
>>> X, y = datasets.load_iris(return_X_y=True)
>>> clf = OutputCodeClassifier(LinearSVC(random_state=0), code_size=2, random_state=0)
>>> clf.fit(X, y).predict(X)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1,
       1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
       2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2,
       2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2])

引用

  • “通过错误纠正输出代码解决多类学习问题”,Dietterich T.,巴基里G.,人工智能研究杂志2,1995年。

  • “统计学习的要素”,Hastie T.,蒂布希拉尼河,弗里德曼·J,第606页(第二版),2008年。

1.12.2. 多标签分类#

Multilabel classification (closely related to multioutput classification) is a classification task labeling each sample with m labels from n_classes possible classes, where m can be 0 to n_classes inclusive. This can be thought of as predicting properties of a sample that are not mutually exclusive. Formally, a binary output is assigned to each class, for every sample. Positive classes are indicated with 1 and negative classes with 0 or -1. It is thus comparable to running n_classes binary classification tasks, for example with MultiOutputClassifier. This approach treats each label independently whereas multilabel classifiers may treat the multiple classes simultaneously, accounting for correlated behavior among them.

例如,预测与文本文档或视频相关的主题。该文档或视频可能是关于“宗教”、“政治”、“金融”或“教育”之一、几个主题课程或所有主题课程。

1.12.2.1. 目标格式#

的有效表示 multilabel y 要么密集要么稀疏 binary 形状矩阵 (n_samples, n_classes) .每列代表一个类。的 1 每一行中的' s表示样本已标记的阳性类别。密集矩阵的示例 y 对于3个样本:

>>> y = np.array([[1, 0, 0, 1], [0, 0, 1, 1], [0, 0, 0, 0]])
>>> print(y)
[[1 0 0 1]
 [0 0 1 1]
 [0 0 0 0]]

也可以使用创建密集二进制矩阵 MultiLabelBinarizer .详情参考 转换预测目标 (y ) .

同样的例子 y 以稀疏矩阵形式:

>>> y_sparse = sparse.csr_matrix(y)
>>> print(y_sparse)
<Compressed Sparse Row sparse matrix of dtype 'int64'
  with 4 stored elements and shape (3, 4)>
  Coords Values
  (0, 0) 1
  (0, 3) 1
  (1, 2) 1
  (1, 3) 1

1.12.2.2. MultiOutputClassifier#

多标签分类支持可以添加到任何分类器 MultiOutputClassifier .该策略包括为每个目标匹配一个分类器。 这允许进行多个目标变量分类。本类的目的是扩展估计器,使其能够估计一系列目标函数(f1,f2,f3.,fn),其在单个X预测器矩阵上训练以预测一系列响应(y1,y2,y3.,yn)。

您可以找到以下的使用示例 MultiOutputClassifier 作为有关部分的一部分 多类多输出分类 因为它是多标签分类对多类输出而不是二进制输出的概括。

1.12.2.3. ClassifierChain#

分类器链(请参阅 ClassifierChain )是一种将许多二进制分类器组合到单个多标签模型中的方法,该模型能够利用目标之间的相关性。

对于具有N个类的多标签分类问题,N个二进制分类器被分配一个介于0和N-1之间的整数。这些数字定义了链中模型的顺序。然后,每个分类器都根据可用的训练数据以及模型被分配较低数字的类别的真实标签进行匹配。

预测时,真实的标签将无法获得。相反,每个模型的预测都会传递给链中的后续模型,以用作特征。

显然,链条的顺序很重要。链中的第一个模型没有关于其他标签的信息,而链中的最后一个模型具有指示所有其他标签存在的特征。一般来说,人们不知道链中模型的最佳排序,因此通常会拟合许多随机排序的链,并将它们的预测平均在一起。

引用

  • Jesse Read、Bernhard Pfahringer、Geoff Holmes、Eibe Frank,“多标签分类的分类器链”,2009年。

1.12.3. 多类多输出分类#

Multiclass-multioutput classification (also称为 multitask classification )是一项分类任务,用一组 non-binary 特性.属性数量和每个属性的类别数量都大于2。因此,单个估计器可以处理多个联合分类任务。这既是多元的概括 label 分类任务,仅考虑二进制属性,以及多属性的概括 class 分类任务,其中仅考虑一个属性。

例如,对一组水果图像的属性“水果类型”和“颜色”进行分类。属性“水果类型”有可能的类别:“苹果”、“梨”和“橙子”。属性“colour”有可能的类别:“green”、“red”、“yellow”和“orange”。每个样本都是水果的图像,为两个属性输出一个标签,并且每个标签都是相应属性的可能类别之一。

请注意,所有处理多类多输出(也称为多任务分类)任务的分类器都支持多标签分类任务作为特例。多任务分类类似于具有不同模型公式的多输出分类任务。有关更多信息,请参阅相关的估计器文档。

下面是一个多类多输出分类的例子:

>>> from sklearn.datasets import make_classification
>>> from sklearn.multioutput import MultiOutputClassifier
>>> from sklearn.ensemble import RandomForestClassifier
>>> from sklearn.utils import shuffle
>>> import numpy as np
>>> X, y1 = make_classification(n_samples=10, n_features=100,
...                             n_informative=30, n_classes=3,
...                             random_state=1)
>>> y2 = shuffle(y1, random_state=1)
>>> y3 = shuffle(y1, random_state=2)
>>> Y = np.vstack((y1, y2, y3)).T
>>> n_samples, n_features = X.shape # 10,100
>>> n_outputs = Y.shape[1] # 3
>>> n_classes = 3
>>> forest = RandomForestClassifier(random_state=1)
>>> multi_target_forest = MultiOutputClassifier(forest, n_jobs=2)
>>> multi_target_forest.fit(X, Y).predict(X)
array([[2, 2, 0],
       [1, 2, 1],
       [2, 1, 0],
       [0, 0, 2],
       [0, 2, 1],
       [0, 0, 2],
       [1, 1, 0],
       [1, 1, 1],
       [0, 0, 2],
       [2, 0, 0]])

警告

目前,没有指标 sklearn.metrics 支持多类多输出分类任务。

1.12.3.1. 目标格式#

的有效表示 multioutput y 是密集的形状矩阵 (n_samples, n_classes) 阶级标签。1d的逐列级联 multiclass 变量的示例 y 对于3个样本:

>>> y = np.array([['apple', 'green'], ['orange', 'orange'], ['pear', 'green']])
>>> print(y)
[['apple' 'green']
 ['orange' 'orange']
 ['pear' 'green']]

1.12.4. 多输出回归#

Multioutput regression 预测每个样本的多个数字属性。每个属性都是一个数字变量,并且每个样本要预测的属性数量大于或等于2。一些支持多输出回归的估计器比仅仅运行更快 n_output 估计器。

例如,使用在某个位置获得的数据预测风速和风向(以度为单位)。每个样本将是在一个位置获得的数据,每个样本将输出风速和风向。

以下回归器本身支持多输出回归:

1.12.4.1. 目标格式#

的有效表示 multioutput y 是密集的形状矩阵 (n_samples, n_output) 漂浮物。按列串联 continuous 变量的示例 y 对于3个样本:

>>> y = np.array([[31.4, 94], [40.5, 109], [25.0, 30]])
>>> print(y)
[[ 31.4  94. ]
 [ 40.5 109. ]
 [ 25.   30. ]]

1.12.4.2. MultiOutputRegressor#

多输出回归支持可以添加到任何回归量 MultiOutputRegressor . 该策略包括为每个目标匹配一个回归量。由于每个目标都由一个回归量表示,因此可以通过检查其相应的回归量来获得有关目标的知识。作为 MultiOutputRegressor 每个目标适合一个回归量,它无法利用目标之间的相关性。

以下是多输出回归的一个示例:

>>> from sklearn.datasets import make_regression
>>> from sklearn.multioutput import MultiOutputRegressor
>>> from sklearn.ensemble import GradientBoostingRegressor
>>> X, y = make_regression(n_samples=10, n_targets=3, random_state=1)
>>> MultiOutputRegressor(GradientBoostingRegressor(random_state=0)).fit(X, y).predict(X)
array([[-154.75474165, -147.03498585,  -50.03812219],
       [   7.12165031,    5.12914884,  -81.46081961],
       [-187.8948621 , -100.44373091,   13.88978285],
       [-141.62745778,   95.02891072, -191.48204257],
       [  97.03260883,  165.34867495,  139.52003279],
       [ 123.92529176,   21.25719016,   -7.84253   ],
       [-122.25193977,  -85.16443186, -107.12274212],
       [ -30.170388  ,  -94.80956739,   12.16979946],
       [ 140.72667194,  176.50941682,  -17.50447799],
       [ 149.37967282,  -81.15699552,   -5.72850319]])

1.12.4.3. RegressorChain#

回归链(请参阅 RegressorChain )类似于 ClassifierChain 作为将许多回归组合到单个多目标模型中的一种方式,该模型能够利用目标之间的相关性。