Примечание
Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере с помощью JupyterLite или Binder.
Обзор метаоценивателей для обучения в многоклассовой классификации
В этом примере мы рассмотрим задачу классификации, в которой целевая переменная состоит более чем из двух классов. Такая задача называется многоклассовой классификацией.
В scikit-learn все оцениватели поддерживают многоклассовую классификацию из коробки: для конечного пользователя реализована наиболее разумная стратегия. Модуль sklearn.multiclass реализует различные стратегии, которые можно использовать для экспериментов или разработки сторонних оценивателей, поддерживающих только бинарную классификацию.
sklearn.multiclass включает стратегии OvO/OvR, используемые для обучения многоклассового классификатора путём подгонки набора бинарных классификаторов (метаоцениватели OneVsOneClassifier и OneVsRestClassifier). В этом примере мы рассмотрим эти стратегии.
# Authors: The scikit-learn developers # SPDX-License-Identifier: BSD-3-Clause
Набор данных Yeast из репозитория UCI
В этом примере мы используем набор данных UCI [1], обычно называемый набором данных Yeast. Для загрузки набора данных из OpenML используется функция sklearn.datasets.fetch_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 классов. Следовательно, перед нами задача многоклассовой классификации.
Сравнение стратегий
В следующем эксперименте мы используем DecisionTreeClassifier и кросс-валидацию RepeatedStratifiedKFold с 3 разбиениями и 5 повторениями.
Мы сравним следующие стратегии:
-
DecisionTreeClassifierможет выполнять многоклассовую классификацию без специальных настроек. Он разбивает обучающие данные на небольшие подмножества и в каждом из них ориентируется на наиболее часто встречающийся класс. Повторяя этот процесс, модель может точно классифицировать входные данные по нескольким различным классам. -
OneVsOneClassifierобучает набор бинарных классификаторов, каждый из которых обучается различать два класса. -
OneVsRestClassifier: обучает набор бинарных классификаторов, каждый из которых обучается различать один класс и остальные классы. -
OutputCodeClassifier: обучает набор бинарных классификаторов, каждый из которых обучается различать заданное множество классов и остальные классы. Множество классов задаётся кодовой книгой, которая в scikit-learn генерируется случайным образом. Этот метод предоставляет параметрcode_sizeдля управления размером кодовой книги. Мы задаём для него значение больше единицы, поскольку не стремимся сжать представление классов.
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"
)

На первый взгляд видно, что встроенная стратегия классификатора на основе дерева решений работает довольно хорошо. Стратегии «один против одного» и кодирования выходов с коррекцией ошибок работают ещё лучше. Однако стратегия «один против остальных» показывает результат хуже, чем другие стратегии.
Действительно, эти результаты воспроизводят вывод, опубликованный в литературе, например в работе [2]. Однако всё не так просто, как кажется.
Важность поиска гиперпараметров
Позднее в работе [3] было показано, что многоклассовые стратегии демонстрируют схожие оценки, если сначала оптимизировать гиперпараметры базовых классификаторов.
Здесь мы попробуем воспроизвести этот результат, оптимизировав хотя бы глубину базового дерева решений.
from sklearn.model_selection import GridSearchCV
param_grid = {"max_depth": [3, 5, 8]}
tree_optimized = GridSearchCV(tree, param_grid=param_grid, cv=3)
ovo_tree = OneVsOneClassifier(tree_optimized)
ovr_tree = OneVsRestClassifier(tree_optimized)
ecoc = OutputCodeClassifier(tree_optimized, code_size=2)
cv_results_tree = cross_validate(tree_optimized, 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)
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"
)
plt.show()

Как видно, после оптимизации гиперпараметров все многоклассовые стратегии показывают схожую эффективность, как и обсуждается в работе [3].
Заключение
Эти результаты можно объяснить следующим образом.
Во-первых, причина, по которой стратегии «один против одного» и кодирования выходов с коррекцией ошибок превосходят дерево, когда гиперпараметры не оптимизированы, заключается в том, что они объединяют большее число классификаторов. Ансамблирование улучшает обобщающую способность. Это отчасти похоже на то, почему классификатор с бэггингом обычно работает лучше, чем отдельное дерево решений, если гиперпараметры не оптимизируются.
Далее, мы видим важность оптимизации гиперпараметров. Действительно, при разработке прогнозных моделей этот этап следует регулярно выполнять, даже если такие методы, как ансамблирование, помогают уменьшить влияние гиперпараметров.
Наконец, важно помнить, что оцениватели scikit-learn разработаны с использованием определённой стратегии, позволяющей им поддерживать многоклассовую классификацию из коробки. Поэтому для таких оценивателей нет необходимости использовать другие стратегии. Эти стратегии главным образом полезны для сторонних оценивателей, поддерживающих только бинарную классификацию. В любом случае мы также показываем, что гиперпараметры следует оптимизировать.
Литература
Общее время выполнения скрипта: (0 минут 27.760 секунд)
Связанные примеры
© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/multiclass/plot_multiclass_overview.html