Spec-Zone.ru › scikit-learn

Примечание

Перейти в конец, чтобы скачать полный код примера или запустить этот пример в браузере через JupyterLite или Binder.

Деревья решений с многоклассовым AdaBoost

В этом примере показано, как бустинг может повысить точность предсказаний в задаче многометочной классификации. Он воспроизводит эксперимент, аналогичный представленному на рисунке 1 в работе Zhu et al [1].

Основной принцип AdaBoost (адаптивного бустинга) заключается в последовательном обучении слабых моделей (например, деревьев решений) на многократно пересэмплированных версиях данных. Каждому образцу назначается вес, который корректируется после каждого этапа обучения, так что неправильно классифицированные образцы получают более высокие веса. При пересэмплировании с возвращением учитываются веса, назначенные каждому образцу. Образцы с более высокими весами имеют больше шансов быть выбранными несколько раз в новый набор данных, а образцы с более низкими весами выбираются реже. Это гарантирует, что на последующих итерациях алгоритм сосредоточится на образцах, которые трудно классифицировать.

Список литературы

[1]

J. Zhu, H. Zou, S. Rosset, T. Hastie, «Многоклассовый AdaBoost». Statistics and its Interface 2.3 (2009): 349–360.

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

Создание набора данных

Набор данных для классификации создаётся на основе десятимерного стандартного нормального распределения (\(x\) в \(R^{10}\)) и определения трёх классов, разделённых вложенными концентрическими десяти мерными сферами, так что в каждом классе оказывается примерно одинаковое число образцов (квантили распределения \(\chi^2\)).

from sklearn.datasets import make_gaussian_quantiles

X, y = make_gaussian_quantiles(
    n_samples=2_000, n_features=10, n_classes=3, random_state=1
)

Мы разделяем набор данных на 2 части: 70 процентов образцов используются для обучения, а оставшиеся 30 процентов — для тестирования.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, train_size=0.7, random_state=42
)

Обучение AdaBoostClassifier

Мы обучаем AdaBoostClassifier. Оцениватель использует бустинг для повышения точности классификации. Бустинг — это метод обучения слабых моделей (то есть estimator), которые учатся на ошибках предыдущих моделей.

Здесь в качестве слабой модели мы определяем DecisionTreeClassifier и задаём максимальное число листьев равным 8. В реальных условиях этот параметр следует настраивать. Мы задаём довольно низкое значение, чтобы сократить время выполнения примера.

Затем встроенный в алгоритм SAMME AdaBoostClassifier использует правильные или неправильные предсказания текущей слабой модели для обновления весов образцов, применяемых при обучении следующих слабых моделей. Вес самой слабой модели также рассчитывается на основе точности классификации обучающих примеров. Вес слабой модели определяет её влияние на итоговое предсказание ансамбля.

from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier

weak_learner = DecisionTreeClassifier(max_leaf_nodes=8)
n_estimators = 300

adaboost_clf = AdaBoostClassifier(
    estimator=weak_learner,
    n_estimators=n_estimators,
    random_state=42,
).fit(X_train, y_train)

Анализ

Сходимость AdaBoostClassifier

Чтобы продемонстрировать эффективность бустинга в повышении точности, мы оцениваем ошибку классификации бустированных деревьев и сравниваем её с двумя базовыми оценками. Первая базовая оценка — это misclassification_error, полученная с помощью одной слабой модели (то есть DecisionTreeClassifier), которая служит точкой отсчёта. Вторая базовая оценка получена с помощью DummyClassifier, который предсказывает наиболее часто встречающийся класс в наборе данных.

from sklearn.dummy import DummyClassifier
from sklearn.metrics import accuracy_score

dummy_clf = DummyClassifier()


def misclassification_error(y_true, y_pred):
    return 1 - accuracy_score(y_true, y_pred)


weak_learners_misclassification_error = misclassification_error(
    y_test, weak_learner.fit(X_train, y_train).predict(X_test)
)

dummy_classifiers_misclassification_error = misclassification_error(
    y_test, dummy_clf.fit(X_train, y_train).predict(X_test)
)

print(
    "DecisionTreeClassifier's misclassification_error: "
    f"{weak_learners_misclassification_error:.3f}"
)
print(
    "DummyClassifier's misclassification_error: "
    f"{dummy_classifiers_misclassification_error:.3f}"
)
DecisionTreeClassifier's misclassification_error: 0.475
DummyClassifier's misclassification_error: 0.692

После обучения модели DecisionTreeClassifier достигнутая ошибка оказывается ниже ожидаемого значения, которое было бы получено при угадывании метки наиболее часто встречающегося класса, как это делает DummyClassifier.

Теперь мы вычислим misclassification_error, то есть 1 - accuracy аддитивной модели (DecisionTreeClassifier) на каждой итерации бустинга на тестовом наборе, чтобы оценить её качество.

Мы используем staged_predict, которая выполняет столько итераций, сколько обучено оценивателей (то есть соответствует n_estimators). На итерации n при предсказании AdaBoost использует только n первые слабые модели. Мы сравниваем эти предсказания с истинными метками y_test и таким образом определяем, полезно ли добавлять в последовательность новую слабую модель.

Построим график ошибки классификации для разных этапов:

import matplotlib.pyplot as plt
import pandas as pd

boosting_errors = pd.DataFrame(
    {
        "Number of trees": range(1, n_estimators + 1),
        "AdaBoost": [
            misclassification_error(y_test, y_pred)
            for y_pred in adaboost_clf.staged_predict(X_test)
        ],
    }
).set_index("Number of trees")
ax = boosting_errors.plot()
ax.set_ylabel("Misclassification error on test set")
ax.set_title("Convergence of AdaBoost algorithm")

plt.plot(
    [boosting_errors.index.min(), boosting_errors.index.max()],
    [weak_learners_misclassification_error, weak_learners_misclassification_error],
    color="tab:orange",
    linestyle="dashed",
)
plt.plot(
    [boosting_errors.index.min(), boosting_errors.index.max()],
    [
        dummy_classifiers_misclassification_error,
        dummy_classifiers_misclassification_error,
    ],
    color="c",
    linestyle="dotted",
)
plt.legend(["AdaBoost", "DecisionTreeClassifier", "DummyClassifier"], loc=1)
plt.show()
Convergence of AdaBoost algorithm

На графике показана ошибка классификации на тестовом наборе после каждой итерации бустинга. Видно, что после 50 итераций ошибка бустированных деревьев сходится примерно к 0,3, что указывает на существенно более высокую точность по сравнению с одним деревом, как показано пунктирной линией на графике.

Ошибка классификации колеблется, потому что алгоритм SAMME использует дискретные выходы слабых моделей для обучения бустированной модели.

На сходимость AdaBoostClassifier в основном влияют скорость обучения (то есть learning_rate), число используемых слабых моделей (n_estimators) и выразительная способность слабых моделей (например, max_leaf_nodes).

Ошибки и веса слабых моделей

Как упоминалось ранее, AdaBoost — это аддитивная модель с прямым пошаговым построением. Теперь мы рассмотрим взаимосвязь между назначенными слабым моделям весами и их статистическими характеристиками.

Для изучения этой взаимосвязи мы используем атрибуты estimator_errors_ и estimator_weights_ обученного AdaBoostClassifier.

weak_learners_info = pd.DataFrame(
    {
        "Number of trees": range(1, n_estimators + 1),
        "Errors": adaboost_clf.estimator_errors_,
        "Weights": adaboost_clf.estimator_weights_,
    }
).set_index("Number of trees")

axs = weak_learners_info.plot(
    subplots=True, layout=(1, 2), figsize=(10, 4), legend=False, color="tab:blue"
)
axs[0, 0].set_ylabel("Train error")
axs[0, 0].set_title("Weak learner's training error")
axs[0, 1].set_ylabel("Weight")
axs[0, 1].set_title("Weak learner's weight")
fig = axs[0, 0].get_figure()
fig.suptitle("Weak learner's errors and weights for the AdaBoostClassifier")
fig.tight_layout()
Weak learner's errors and weights for the AdaBoostClassifier, Weak learner's training error, Weak learner's weight

На левом графике показана взвешенная ошибка каждой слабой модели на перевзвешенном обучающем наборе на каждой итерации бустинга. На правом графике показаны веса, присвоенные каждой слабой модели и используемые впоследствии для предсказаний итоговой аддитивной модели.

Мы видим, что ошибка слабой модели обратно пропорциональна её весу. Это означает, что аддитивная модель больше доверяет слабой модели с меньшей ошибкой (на обучающем наборе), увеличивая её влияние на итоговое решение. Именно так в AdaBoost после каждой итерации обновляются веса базовых оценивателей.

Математические подробности

Вес слабой модели, обученной на этапе \(m\), обратно пропорционален её ошибке классификации:

\[\alpha^{(m)} = \log \frac{1 - err^{(m)}}{err^{(m)}} + \log (K - 1),\]

где \(\alpha^{(m)}\) и \(err^{(m)}\) — соответственно вес и ошибка \(m\)-й слабой модели, а \(K\) — число классов в задаче классификации.

Ещё одно интересное наблюдение состоит в том, что первые слабые модели в последовательности допускают меньше ошибок, чем последующие.

Это можно объяснить следующим образом: из-за перевзвешивания образцов последующие классификаторы вынуждены пытаться классифицировать более сложные или зашумлённые образцы и игнорировать уже правильно классифицированные. Поэтому общая ошибка на обучающем наборе возрастает. Именно поэтому веса слабых моделей рассчитаны так, чтобы компенсировать более низкую эффективность слабых моделей.

Общее время выполнения скрипта: (0 минут 3.605 секунды)

Launch binder
Launch JupyterLite

Download Jupyter notebook: plot_adaboost_multiclass.ipynb

Download Python source code: plot_adaboost_multiclass.py

Download zipped: plot_adaboost_multiclass.zip

Похожие примеры

Регрессия деревьев решений с AdaBoost

Поверхности решений ансамблей деревьев на наборе данных ирисов

Объединение предикторов с помощью стекинга

Ранняя остановка градиентного бустинга

© 2007–2026 The scikit-learn developers
Licensed under the 3-clause BSD License.
https://scikit-learn.org/1.9/auto_examples/ensemble/plot_adaboost_multiclass.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API