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

В этой статье мы увидим, как ансамбль деревьев решений, обученный с использованием библиотек Gradient Boosting, таких как XGBoost, LightGBM и CatBoost, выполняет мультиклассовую классификацию.

Действительно, ансамбль деревьев решений связывает реальное значение с набором признаков, поэтому возникает вопрос: как ансамбли деревьев решений преобразуют скалярное значение в мультиклассовую метку?

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

Мы будем постепенно углубляться в тему, следуя приведенному ниже плану:

  • Напоминание и игрушечный пример бинарной классификации в Python
  • Первая бинарная классификация с использованием XGBoost в качестве регрессора
  • Вторая бинарная классификация с использованием XGBoost в качестве классификатора
  • Мультиклассовая классификация с использованием XGBoost

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

XGBoost, LightGBM или CatBoost — это библиотеки, которые используют (по умолчанию) одну и ту же базовую модель: деревья решений.

Эти деревья решений комбинируются итеративно с использованием Gradient Boosting. Т.е. добавление новых узлов к текущему дереву выполняется для оптимизации нелинейной цели, обычно квадрата ошибки. Чтобы справиться с нелинейностью, цель линеаризуется с использованием ее градиента и гессиана.

Отсюда и название Gradient Boosting. Подробнее в моей предыдущей статье:



Прогнозирование с помощью ансамбля деревьев решений

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

В зависимости от значения признаков каждое дерево затем связывает уникальное значение, прикрепленное к последнему листу.

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

Рисунок ниже иллюстрирует это на простом примере, где ансамбль деревьев решений моделирует функцию идентичности для целого числа от 1 до 4:

Например, когда на входе 1, первое дерево генерирует 8, второе дерево -6, а последнее -1. Суммирование этих трех значений дает 1, что является ожидаемым результатом.

Этот пример взят из моей книги Практическое повышение градиента по повышению градиента:



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

Двоичная классификация без XGBoost

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

Задача, которую мы здесь пытаемся решить, проста: мы хотим установить вероятность успеха учащегося в зависимости от количества часов, которое он тратит на изучение своего предмета.

На рисунке ниже показаны собранные данные, т. е. количество часов работы и результаты: пройдено или не пройдено .

Стандартной моделью, используемой для классификации, является логистическая функция. Эта функция похожа на линейную регрессию, за исключением того, что вместо получения значения в диапазоне ℝ она генерирует только значения в диапазоне [0, 1]. Его формулу стоит знать:

Как всегда в машинном обучении, поиск наилучших параметров модели, в данном случае логистической функции, осуществляется путем минимизации ошибки. Столкнувшись с бинарной проблемой, где положительный вывод может быть смоделирован 1, а отрицательный вывод — 0, можно объединить обе ошибки в одном выражении:

Где y_k — это наблюдаемые выборки, тогда как f(x_k) — это прогноз, сделанный моделью f.

Трудность с этой основной ошибкой состоит в том, что в соответствии с бинарным характером логистической функции, которая в основном принимает только два значения: ноль и единицу, ошибка по параметру модели m также будет принимать в основном два значения. Следовательно, за пределами оптимальных параметров ошибка будет плоской.

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

Нам нужен способ обработки вывода ошибок, который ограничен диапазоном [0, 1] для данной выборки до ℝ+, чтобы больше не было насыщения.

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

Хитрость заключается в том, чтобы понять, что log(1) равен нулю, тогда как log(0) равен -∞.

Поэтому используется логарифмическая потеря:

Где y_k — это наблюдаемые выборки, тогда как f(x_k) — это прогноз, сделанный моделью f. Обратите внимание на знак минус перед оператором сложения и инверсию 1-f(x_k) с f(x_k). Это потому, что log(1)=0.

Используя потерю журнала, ошибка больше не насыщена:

Самый простой способ минимизировать эту ошибку — использовать метод наискорейшего спуска, который требует только вычисления градиента ошибки. Для этого возможно множество вариантов. Здесь мы собираемся использовать символическое дифференцирование с помощью sympy:

Алгоритм нашел ожидаемое значение 14,77, что очень близко к теоретическому.

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

Двоичная классификация с XGBoost

Давайте начнем с простого примера, используя Cleveland Heart Disease Dataset (CC BY 4.0), где классификация выполняется с использованием регрессии. Поскольку мы выполняем бинарную классификацию, можно использовать простую регрессию, поскольку мы можем присвоить положительное значение 1,0 положительным меткам и отрицательное значение -1 отрицательным меткам:

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

Аналогичного результата можно добиться, используя непосредственно классификатор XGBoost:

В этом случае нет необходимости округлять прогнозы для получения соответствующего класса. Вся работа выполняется изначально XGBClassifier. Давайте посмотрим, как с этим справится XGBoost.

XGBClassifier обучает несколько моделей

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

Фрагмент кода ниже показывает, как лучше понять внутреннее устройство XGBoost.

В частности, метод predict_proba позволяет получить доступ к необработанным данным, сгенерированным внутренними моделями. Это ясно показывает, что при выполнении классификации XGBoost делает прогноз вероятности для каждого класса.

Тогда прогнозируемый класс является классом с наибольшей вероятностью.

Глядя на код, выполненный для интеграции XGBoost в sklearn, мы получаем подтверждение того, что XGBoost делает несколько прогнозов:

Как видно, строка 25, argmax используется для получения индекса класса с наибольшей вероятностью при использовании softprob. В случае, когда используется цель softmax, прогноз просто преобразуется в целые числа.

Как XGBoost выполняет мультиклассовую классификацию?

Обычно в объяснениях того, как XGBoost обрабатывает многоклассовую классификацию, говорится, что он обучает несколько деревьев, по одному для каждого класса.

Это не совсем так. Фактически все деревья строятся одновременно, с использованием векторной целевой функции вместо скалярной. Т.е. у каждого класса есть цель.

В документации XGBoost приводится пример такой цели:

В этом фрагменте кода есть две очень интересные вещи:

  1. Имя цели — multi:softprob при использовании интегрированной цели в XGBoost. Это довольно запутанно, так как цель на самом деле не softprob , а потеря журнала softmax. Это ясно видно в коде, так как градиент — это непосредственно softmax. Но softmax — это не градиент softmax, а градиент его потерь в журнале:

2. Другой момент заключается в том, что в коде используется переменная hess, обозначающая гессиан. Однако на самом деле это не гессиан, который используется математически, а вторая производная. Следовательно, правильное название для этого было бы лапласианом.

Заключение

В этой статье мы показали, как XGBoost обрабатывает классификацию.

Крайне важно понимать, что классификация n классов порождает деревья в n раз более сложные.

Также важно отметить, что имена целевых функций, представленных в XGBoost API, не всегда очень явны. Например, при классификации оптимизируемой целью является не softmax или softprob, а их логарифмическая потеря.

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