Многоклассовые деревья решений с использованием AdaBoost

Beginner

This tutorial is from open-source community. Access the source code

Введение

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

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

Советы по работе с ВМ

После запуска ВМ кликните в левом верхнем углу, чтобы переключиться на вкладку Ноутбук и получить доступ к Jupyter Notebook для практики.

Иногда вам может потребоваться подождать несколько секунд, пока Jupyter Notebook загрузится. Валидация операций не может быть автоматизирована из-за ограничений Jupyter Notebook.

Если вы сталкиваетесь с проблемами во время обучения, не стесняйтесь обращаться к Labby. Оставьте отзыв после занятия, и мы оперативно решим проблему для вас.

Импортируем необходимые библиотеки

Начнём с импорта необходимых библиотек, включая make_gaussian_quantiles и accuracy_score из sklearn.datasets, AdaBoostClassifier, DecisionTreeClassifier из sklearn.ensemble и matplotlib.pyplot.

import matplotlib.pyplot as plt
from sklearn.datasets import make_gaussian_quantiles
from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import accuracy_score
from sklearn.tree import DecisionTreeClassifier

Загружаем датасет

Мы будем использовать функцию make_gaussian_quantiles из sklearn.datasets для генерации датасета. Эта функция генерирует изотропные Гауссовы распределения и добавляет разделение между классами, чтобы сделать задачу более сложной.

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

Разделяем датасет

Мы разделим датасет на тренировочный и тестовый наборы, используя первые 3000 выборок для обучения и оставшиеся выборки для тестирования.

n_split = 3000
X_train, X_test = X[:n_split], X[n_split:]
y_train, y_test = y[:n_split], y[n_split:]

Создаём и обучаем модели

Мы создадим две модели AdaBoost, одну с использованием SAMME и другую с использованием SAMME.R. обе модели будут использовать DecisionTreeClassifier с максимальной глубиной 2 и 300 оценщиками.

bdt_real = AdaBoostClassifier(
    DecisionTreeClassifier(max_depth=2), n_estimators=300, learning_rate=1
)

bdt_discrete = AdaBoostClassifier(
    DecisionTreeClassifier(max_depth=2),
    n_estimators=300,
    learning_rate=1.5,
    algorithm="SAMME",
)

bdt_real.fit(X_train, y_train)
bdt_discrete.fit(X_train, y_train)

Тестируем модели

Мы проверим модели и вычислим ошибку тестирования каждой модели после каждой итерации бустинга.

real_test_errors = []
discrete_test_errors = []

for real_test_predict, discrete_test_predict in zip(
    bdt_real.staged_predict(X_test), bdt_discrete.staged_predict(X_test)
):
    real_test_errors.append(1.0 - accuracy_score(real_test_predict, y_test))
    discrete_test_errors.append(1.0 - accuracy_score(discrete_test_predict, y_test))

Построим графики результатов

Мы построим графики ошибки тестирования, классификационной ошибки и веса бустинга для каждой модели.

n_trees_discrete = len(bdt_discrete)
n_trees_real = len(bdt_real)

## Boosting может прекратиться раньше, но следующие массивы всегда
## имеют длину n_estimators. Мы обрезаем их до фактического числа деревьев здесь:
discrete_estimator_errors = bdt_discrete.estimator_errors_[:n_trees_discrete]
real_estimator_errors = bdt_real.estimator_errors_[:n_trees_real]
discrete_estimator_weights = bdt_discrete.estimator_weights_[:n_trees_discrete]

plt.figure(figsize=(15, 5))

plt.subplot(131)
plt.plot(range(1, n_trees_discrete + 1), discrete_test_errors, c="black", label="SAMME")
plt.plot(
    range(1, n_trees_real + 1),
    real_test_errors,
    c="black",
    linestyle="dashed",
    label="SAMME.R",
)
plt.legend()
plt.ylim(0.18, 0.62)
plt.ylabel("Ошибка тестирования")
plt.xlabel("Число деревьев")

plt.subplot(132)
plt.plot(
    range(1, n_trees_discrete + 1),
    discrete_estimator_errors,
    "b",
    label="SAMME",
    alpha=0.5,
)
plt.plot(
    range(1, n_trees_real + 1), real_estimator_errors, "r", label="SAMME.R", alpha=0.5
)
plt.legend()
plt.ylabel("Ошибка")
plt.xlabel("Число деревьев")
plt.ylim((0.2, max(real_estimator_errors.max(), discrete_estimator_errors.max()) * 1.2))
plt.xlim((-20, len(bdt_discrete) + 20))

plt.subplot(133)
plt.plot(range(1, n_trees_discrete + 1), discrete_estimator_weights, "b", label="SAMME")
plt.legend()
plt.ylabel("Вес")
plt.xlabel("Число деревьев")
plt.ylim((0, discrete_estimator_weights.max() * 1.2))
plt.xlim((-20, n_trees_discrete + 20))

## предотвращаем перекрытие меток на оси y
plt.subplots_adjust(wspace=0.25)
plt.show()

Резюме

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