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