多类训练元估计器概述#

在这个例子中,我们讨论了当目标变量由两个以上的类组成时的分类问题。这被称为多类分类。

在scikit-learn中,所有估计器都支持开箱即用的多类分类:为最终用户实施了最明智的策略。的 sklearn.multiclass 模块实现了各种策略,可以用于实验或开发仅支持二元分类的第三方估计器。

sklearn.multiclass 包括OvO/OvR策略,用于通过匹配一组二进制分类器( OneVsOneClassifierOneVsRestClassifier 元估计器)。这个例子将回顾它们。

# Authors: The scikit-learn developers
# SPDX-License-Identifier: BSD-3-Clause

酵母UCI数据集#

在本示例中,我们使用UCI数据集 [1], 通常称为酵母数据集。公司现采用国际 sklearn.datasets.fetch_openml 函数从OpenML加载数据集。

from sklearn.datasets import fetch_openml

X, y = fetch_openml(data_id=181, as_frame=True, return_X_y=True)

要了解我们正在处理的数据科学问题的类型,我们可以检查我们想要为其构建预测模型的目标。

y.value_counts().sort_index()
class_protein_localization
CYT    463
ERL      5
EXC     35
ME1     44
ME2     51
ME3    163
MIT    244
NUC    429
POX     20
VAC     30
Name: count, dtype: int64

我们看到目标是离散的,由10个类组成。因此,我们处理多类分类问题。

策略比较#

在下面的实验中,我们使用 DecisionTreeClassifierRepeatedStratifiedKFold 交叉验证,3次分割和5次重复。

我们比较以下策略:

  • DecisionTreeClassifier 可以处理多类分类,无需任何特殊调整。它的工作原理是将训练数据分解为更小的子集,并专注于每个子集中最常见的类。通过重复此过程,该模型可以准确地将输入数据分类为多个不同的类别。

  • OneVsOneClassifier 训练一组二进制分类器,其中每个分类器都经过训练以区分两个类别。

  • OneVsRestClassifier :训练一组二进制分类器,其中每个分类器都经过训练以区分一个类和其余类。

  • OutputCodeClassifier :训练一组二进制分类器,其中每个分类器都经过训练以区分一组类与其余类。类别集由码本定义,该码本在scikit-learn中随机生成。此方法公开参数 code_size 以控制码本的大小。我们将其设置在1以上,因为我们对压缩类表示不感兴趣。

import pandas as pd

from sklearn.model_selection import RepeatedStratifiedKFold, cross_validate
from sklearn.multiclass import (
    OneVsOneClassifier,
    OneVsRestClassifier,
    OutputCodeClassifier,
)
from sklearn.tree import DecisionTreeClassifier

cv = RepeatedStratifiedKFold(n_splits=3, n_repeats=5, random_state=0)

tree = DecisionTreeClassifier(random_state=0)
ovo_tree = OneVsOneClassifier(tree)
ovr_tree = OneVsRestClassifier(tree)
ecoc = OutputCodeClassifier(tree, code_size=2)

cv_results_tree = cross_validate(tree, X, y, cv=cv, n_jobs=2)
cv_results_ovo = cross_validate(ovo_tree, X, y, cv=cv, n_jobs=2)
cv_results_ovr = cross_validate(ovr_tree, X, y, cv=cv, n_jobs=2)
cv_results_ecoc = cross_validate(ecoc, X, y, cv=cv, n_jobs=2)

我们现在可以比较不同策略的统计性能。我们绘制了不同策略的得分分布。

from matplotlib import pyplot as plt

scores = pd.DataFrame(
    {
        "DecisionTreeClassifier": cv_results_tree["test_score"],
        "OneVsOneClassifier": cv_results_ovo["test_score"],
        "OneVsRestClassifier": cv_results_ovr["test_score"],
        "OutputCodeClassifier": cv_results_ecoc["test_score"],
    }
)
ax = scores.plot.kde(legend=True)
ax.set_xlabel("Accuracy score")
ax.set_xlim([0, 0.7])
_ = ax.set_title(
    "Density of the accuracy scores for the different multiclass strategies"
)
Density of the accuracy scores for the different multiclass strategies

乍一看,我们可以看到决策树分类器的内置策略运行得相当好。一对一和错误纠正输出代码策略效果更好。然而,“一对休息”策略的效果不如其他策略。

事实上,这些结果重现了文献中报道的内容,例如 [2]. 然而,故事并不像看起来那么简单。

结论#

我们可以从这些结果背后得到一些直觉。

首先,当超参数未优化时,一对一和错误纠正输出代码优于树的原因取决于它们集成了大量分类器这一事实。集成提高了概括性能。这有点相似,为什么如果不小心优化超参数,Bagging分类器通常比单个决策树表现更好。

然后,我们看到了优化超参数的重要性。事实上,即使集成等技术有助于减少这种影响,在开发预测模型时也应该定期探索它。

最后,重要的是要记住,scikit-learn中的估计器是通过特定策略开发的,以开箱即用地处理多类分类。因此对于这些估计器来说,这意味着不需要使用不同的策略。这些策略主要对于仅支持二元分类的第三方估计器有用。在所有情况下,我们还表明应该优化超参数。

引用#

Total running time of the script: (0分25.248秒)

相关实例

嵌套与非嵌套交叉验证

Nested versus non-nested cross-validation

多项和一对二回归的决策边界

Decision Boundaries of Multinomial and One-vs-Rest Logistic Regression

事后调整决策函数的截止点

Post-hoc tuning the cut-off point of decision function

使用分类器链的多标签分类

Multilabel classification using a classifier chain

Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io> _