Примечание
Перейти к концу, чтобы скачать полный пример кода. или запустить этот пример в вашем браузере через JupyterLite или Binder
Многоклассовые решающие деревья, усиленные AdaBoost
Этот пример демонстрирует, как усиление может повысить точность предсказания в задаче многоклассовой классификации. Он воспроизводит аналогичный эксперимент, как показано на рисунке 1 в статье Жу и др. [1].
Основной принцип AdaBoost (адаптивного усиления) заключается в подборе последовательности слабых классификаторов (например, решающих деревьев) на повторно ресемплированных версиях данных. Каждый образец имеет вес, который корректируется после каждого шага обучения, таким образом, что неправильно классифицированные образцы будут получать более высокие веса. Процесс ресемплирования с заменой учитывает веса, назначенные каждому образцу. Образцы с более высокими весами имеют больше шансов быть отобраны несколько раз в новом наборе данных, в то время как образцы с более низкими весами менее вероятно будут выбраны. Это гарантирует, что последующие итерации алгоритма будут сосредоточены на трудно классифицируемых образцах.
Ссылки
# 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()

График показывает ошибку неправильной классификации на тестовом наборе после каждой итерации бустинга. Мы видим, что ошибка усиленных деревьев сходится к ошибке около 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()

На графике слева показана взвешенная ошибка каждого слабого обучающего элемента на повторно взвешенном обучающем наборе на каждой итерации бустинга. На правом графике показаны веса, связанные с каждым слабым обучающим элементом, позже используемые для создания прогнозов окончательной аддитивной модели.
Мы видим, что ошибка слабого обучающего элемента является обратной величиной весов. Это означает, что наша аддитивная модель будет больше доверять слабому обучающему элементу, который делает меньшие ошибки (на обучающем наборе), увеличивая его влияние на окончательное решение. Действительно, это и есть формулировка обновления весов базовых оценок после каждой итерации в AdaBoost.
Математические подробности
Вес, связанный со слабым обучающим элементом, обученным на этапе \(m\), обратно пропорционален ошибке неправильной классификации, так что:
где \(\alpha^{(m)}\) и \(err^{(m)}\) — вес и ошибка \(m\)-го слабого обучающего элемента соответственно, а \(K\) — количество классов в нашей задаче классификации.
Еще одна интересная наблюдение сводится к тому, что первые слабые обучающие элементы модели делают меньше ошибок, чем последующие слабые обучающие элементы цепочки бустинга.
Интуиция, стоящая за этим наблюдением, заключается в следующем: из-за повторного взвешивания выборок последующие классификаторы вынуждены пытаться классифицировать более сложные или шумные образцы и игнорировать уже хорошо классифицированные образцы. Поэтому общая ошибка на обучающем наборе будет увеличиваться. Вот почему веса слабых обучающих элементов построены для противодействия слабым обучающим элементам с худшей производительностью.
Общее время выполнения сценария: (0 минут 4.601 секунды)
Примеры по теме
© 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