多类和多输出算法

scikit-learn 如何完成多类和多输出算法?

什么是多类分类?

  • 多类分类是一个有两个以上类别的分类任务。每个样本只能被标记为一个类别
  • 实现多类分类的方法有: OneVsRestClassifier 、OneVsOneClassifier
  • 输出标签格式
    1
    2
    3
    4
    5
    # 4个样本,分类为3个标签的一个
    >>> import numpy as np
    >>> y = np.array(['apple', 'pear', 'apple', 'orange'])
    >>> print(y)
    ['apple' 'pear' 'apple' 'orange']

什么是 OneVsRestClassifier

  • 在多类分类任务 (n 类) 中,为每个类别创建一个分类器,共计 n 个,这是最常见的多分类措施,原因是可解释性强
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     >>> 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])

什么是 OneVsOneClassifier?

  • 在多类分类任务 (n 类) 中,为每对标签创建分类器,共计 n*(n+1)/2 个,预测是,按分类器最多票类别判定,票数相等,按分类置信度判定
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     >>> 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])

增加训练数据时, OneVsRestClassifier 和 OneVsOneClassifier 有什么不同?

  • OneVsRestClassifier:需要更新所有的模型
  • OneVsOneClassifier:根据数据,更新若干模型即可

scikit-learn 如何进行多标签分类 (MultiOutputClassifier)?

  • 这可以被认为是对样本的属性进行预测,而这些属性并不是相互排斥的。从形式上看,每个样本的每个类别都有一个二进制输出。阳性类用 1 表示,阴性类用 0 或 - 1 表示。因此,它与运行 n_classes 二元分类任务相当,例如使用 MultiOutputClassifier。这种方法独立处理每个标签,而多标签分类器可以同时处理多个类,并考虑到它们之间的相关行为
  • 输出标签格式
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    # 3个样本,每个样本4个标签
    >>> 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]]
    >>> 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=-1)
    >>> 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]])

scikit-learn 如何进行多类多输出分类?

  • 多类多输出分类(也称为多任务分类)是一项分类任务,它用一组非二进制属性来标记每个样本。属性的数量和每个属性的类的数量都大于 2。因此,一个估计器可以处理几个联合分类任务
  • 标签输出格式
    1
    2
    3
    4
    5
    6
    # 多输出y的有效表示是一个密集的形状(n_samples, n_classes)的类标签矩阵
    >>> y = np.array([['apple', 'green'], ['orange', 'orange'], ['pear', 'green']])
    >>> print(y)
    [['apple' 'green']
    ['orange' 'orange']
    ['pear' 'green']]

scikit-learn 如何进行多输出回归?

  • 多输出回归对每个样本的多个数字属性进行预测。每个属性都是一个数字变量,每个样本要预测的属性数量大于或等于 2
  • 多输出回归支持可以通过 MultiOutputRegressor 添加到任何回归器中。这种策略包括为每个目标拟合一个回归器。由于每个目标正好由一个回归器表示,因此有可能通过检查其相应的回归器来获得关于目标的知识
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     >>> 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]])