Spec-Zone.ru › scikit-learn

Примечание

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

Многоклассовые решающие деревья, усиленные AdaBoost

Этот пример демонстрирует, как усиление может повысить точность предсказания в задаче многоклассовой классификации. Он воспроизводит аналогичный эксперимент, как показано на рисунке 1 в статье Жу и др. [1].

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

Ссылки

[1]

J. Zhu, H. Zou, S. Rosset, T. Hastie, «Многоклассовый AdaBoost». Статистический и его интерфейс 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

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

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

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

Ошибки и веса слабых обучающих элементов

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

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

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 минут 4.601 секунды)

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

Графики поверхностей решений ансамблей деревьев для набора данных ирисов

Раннее прекращение в Gradient Boosting

Регрессия с использованием Gradient Boosting

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

Spec-Zone.ru

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