Добрый день, уважаемые читатели Otus на Хабре!

CatBoost – алгоритм, разработанный Yandex это это гармоничное сочетание инноваций и эффективности, особенно когда дело доходит до работы с категориальными данными.

Первые шаги CatBoost были сделаны в 2017 году, когда мир уже знал об XGBoost и LightGBM. В чем же заключается уникальность CatBoost? Его разработка была направлена на решение специфических проблем, связанных с категориальными данными – той самой головной боли многих специалистов в области машинного обучения. С тех пор CatBoost прошёл долгий путь развития и совершенствования, став не только эффективным инструментом, но и частью больших исследовательских проектов в различных сферах.

CatBoost выделяется на фоне других алгоритмов градиентного бустинга благодаря ряду ключевых особенностей:

  • Обработка категориальных данных "из коробки": В отличие от своих предшественников, CatBoost не требует предварительной обработки категориальных данных, что значительно упрощает жизнь аналитиков.

  • Минимизация переобучения: Алгоритмы CatBoost разработаны таким образом, чтобы снизить риск переобучения, что часто является проблемой в градиентном бустинге.

  • Высокая скорость и эффективность: Несмотря на свою сложность, CatBoost демонстрирует выдающуюся скорость обучения и предсказания, что делает его идеальным выбором для работы с большими наборами данных.

Принципы градиентного бустинга

Бустинг – это ансамблевый метод машинного обучения, целью которого является объединение нескольких слабых моделей предсказания для создания одной сильной. Слабая модель – это такая, которая выполняет предсказания немного лучше, чем наугад, в то время как сильная модель обладает высокой предсказательной способностью. Цель бустинга – улучшить точность предсказаний.

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

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

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

Несмотря на свою мощь, бустинг может быть склонен к переобучению, особенно если в ансамбле слишком много моделей или они слишком сложные. Для контроля переобучения к примеру ранняя остановка (early stopping).

Принцип построения ансамбля

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

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

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

Градиентный спуск

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

Градиент функции - это вектор, состоящий из частных производных, который указывает направление наискорейшего роста функции. В контексте оптимизации, мы интересуемся направлением наискорейшего убывания, то есть движемся в противоположном направлении градиента. Частные производные вычисляются для каждого параметра модели (например, весов в нейронной сети).

На каждой итерации алгоритма параметры модели обновляются в направлении, противоположном градиенту функции потерь. Размер шага, который делает алгоритм в этом направлении, определяется скоростью обучения (learning rate). Оптимальная скорость обучения - ключевой параметр, поскольку слишком большой шаг может привести к пропуску минимума, а слишком маленький делает процесс оптимизации медленным.

Формула для обновления параметра θ на каждой итерации выглядит следующим образом:

 \theta = \theta - \eta \cdot \nabla_\theta J(\theta)


где η - скорость обучения, а ∇θJ(θ) - градиент функции потерь J по параметру θ.

Виды градиентного спуска

  • Пакетный градиентный спуск (Batch Gradient Descent): вычисляет градиент функции потерь по всему обучающему набору данных. Это точно, но может быть очень медленным на больших наборах данных.

  • Стохастический градиентный спуск (Stochastic Gradient Descent, SGD): вычисляет градиент для каждого обучающего примера по отдельности и обновляет параметры. Это быстро, но изменения параметров могут быть очень "шумными".

  • Мини-пакетный градиентный спуск (Mini-batch Gradient Descent): компромисс между двумя предыдущими методами, вычисляет градиенты на небольших группах обучающих примеров.

Сравнительный анализ с другими алгоритмами бустинга (например, XGBoost, LightGBM)

Критерий/Алгоритм

CatBoost

XGBoost

LightGBM

Основное предназначение

Оптимизирован для работы с категориальными данными

Всецело фокусируется на производительности и эффективности

Ориентирован на скорость и эффективность при работе с большими объемами данных

Обработка категориальных данных

Встроенная обработка без предварительного кодирования

Требует предварительного кодирования (например, one-hot encoding)

Требует предварительного кодирования, но обладает оптимизациями для категориальных признаков

Скорость обучения

Высокая, с поддержкой GPU

Высокая, с поддержкой GPU

Очень высокая, эффективно обрабатывает большие наборы данных

Предотвращение переобучения

Использует ordered boosting и разнообразные стратегии регуляризации

Поддерживает L1 и L2 регуляризацию

Использует механизмы, такие как exclusive feature bundling (EFB)

Работа с большими данными

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

Хорошо масштабируется, но может быть неэффективен на очень больших наборах данных

Оптимизирован для обработки больших объемов данных с низкими требованиями к памяти

Поддержка языков программирования

Поддерживает основные языки, включая Python, R, Java

Широкая поддержка языков, включая Python, R, Java, Scala

Поддерживает Python, R, Java и другие языки

Сложность моделей

Генерирует более сложные модели, но с контролем переобучения

Позволяет настраивать сложность модели через гиперпараметры

Строит более легковесные модели с использованием гистограммного подхода

Интерпретируемость

Обеспечивает хорошую интерпретируемость, особенно при работе с категориальными данными

Обеспечивает средний уровень интерпретируемости

Интерпретируемость может быть затруднена из-за оптимизаций и более сложных структур

Резюмируя

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

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

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

Cat Boost

CatBoost использует решающие деревья глубины 1 или 2 в качестве базовых моделей. Эти неглубокие деревья, которые иногда называют "котэ", имеют следующие характеристики:

  • Каждый узел дерева делает бинарное разбиение на основе значения одной из признаков.

  • Эти короткие деревья обладают небольшой глубиной, что делает их более устойчивыми к переобучению.

К примеру мы решаем задачу классификации, где необходимо определить, будет ли клиент покупать продукт (1) или нет (0). Один из наших признаков - возраст клиента. Решающее дерево CatBoost может разделить клиентов на две группы: те, кто моложе 30 лет, и те, кто старше 30 лет.

Самая основная фича CatBoost это способность обрабатывать категориальные данные без предварительного кодирования. Другие алгоритмы требуют перевода категориальных данных в числовой формат (например, One-Hot Encoding), что может потребовать большого объема памяти и привести к потере информации.

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

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

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

Обработки категориальных данных может выглядеть так:

from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split

# Загрузка данных
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Создание и обучение модели с автоматической обработкой категориальных данных
model = CatBoostClassifier(iterations=1000, learning_rate=0.1, depth=6)
model.fit(X_train, y_train)

# Оценка производительности модели
accuracy = model.score(X_test, y_test)
print(f"Accuracy: {accuracy}")

CatBoost автоматически определяет категориальные признаки и обрабатывает их с использованием счетчиков. Это позволяет использовать категориальные данные напрямую при обучении модели, без необходимости кодирования их в числовой формат.

Пример использования с явным указанием категориальных признаков:

from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split

# Загрузка данных
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Явное указание категориальных признаков
cat_features = [0, 1, 3, 5]

# Создание и обучение модели с указанием категориальных признаков
model = CatBoostClassifier(iterations=1000, learning_rate=0.1, depth=6)
model.fit(X_train, y_train, cat_features=cat_features)

# Оценка производительности модели
accuracy = model.score(X_test, y_test)
print(f"Accuracy: {accuracy}")

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

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

L2\text{-регуляризация} = \lambda \sum_{i=1}^{n} w_i^2

где:

  • λ (лямбда) - это гиперпараметр, который контролирует силу регуляризации. Он выбирается заранее и может быть настроен в процессе обучения модели.

  • n - количество признаков в модели.

  • wi​ - вес (коэффициент) i-го признака.

Таким образом, L2-регуляризация добавляет к функции потерь сумму квадратов весов всех признаков, умноженную на гиперпараметр λ. Это вынуждает модель уменьшать веса признаков и предотвращает их чрезмерное увеличение в процессе обучения.

Когда λ равно нулю, L2-регуляризация отсутствует, и модель обучается без ограничений на веса признаков. Когда λ большое, L2-регуляризация становится более сильной, и веса признаков близки к нулю. L2-регуляризация штрафует большие значения весов, поощряя модель использовать только наиболее информативные признаки.

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

CatBoost автоматически выполняет отбор признаков путем оценки их важности для модели. Это позволяет модели сосредотачиваться на наиболее информативных признаках и уменьшить шум от менее значимых.

Если в задаче прогнозирования цены дома признак "цвет двери" оказывается малозначимым, CatBoost может исключить его из модели.

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

На каждой итерации градиентного бустинга добавляется новое решающее дерево, которое исправляет ошибки предыдущих деревьев.

Библиотека Cat Boost

CatBoost (Categorical Boosting) - это библиотека для машинного обучения с открытым исходным кодом, разработанная Яндексом.

CatBoost можно установить с помощью pip, стандартного инструмента для установки Python-пакетов:

pip install catboost

Библиотека CatBoost (Categorical Boosting) представляет собой мощный инструмент для машинного обучения с открытым исходным кодом, разработанный компанией Яндекс. Она специально оптимизирована для работы с категориальными данными и предоставляет высокую производительность и точность в задачах классификации и регрессии. Давайте рассмотрим основной синтаксис CatBoost для создания, обучения и оценки моделей.

Основной синтаксис CatBoost:

CatBoost использует специальный объект Pool для представления данных. Вы можете создать Pool, указав признаки и целевую переменную. Это делается следующим образом:

train_data = Pool(data=X_train, label=y_train, cat_features=cat_features)

Далее, вы создаете экземпляр модели (CatBoostClassifier для классификации или CatBoostRegressor для регрессии) и обучаете его на данных:

model = CatBoostClassifier(iterations=1000, learning_rate=0.1, depth=6)
model.fit(train_data)

Вы можете оценить производительность обученной модели на тестовых данных:

accuracy = model.score(X_test, y_test)
print(f"Accuracy: {accuracy}")

Для получения прогнозов на новых данных используйте метод predict:

predictions = model.predict(X_new)

CatBoost позволяет оценить важность признаков с помощью атрибута feature_importances_:

importances = model.feature_importances_

Для оценки производительности модели с помощью кросс-валидации используйте функцию cv:

from catboost import cv
cv_results = cv(train_data, model.get_params(), fold_count=5)

Вы можете настраивать гиперпараметры модели, чтобы достичь лучшей производительности. Важные параметры включают iterations, learning_rate, depth и другие.

Подробнее изучить библиотеку можно здесь.

Немного примеров

1. Классификация (Бинарная)

from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd

# Загрузка данных
df = pd.read_csv('your_data.csv')
X = df.drop('target', axis=1)
y = df['target']

# Разделение данных
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Создание и обучение модели
model = CatBoostClassifier(iterations=100, learning_rate=0.1)
model.fit(X_train, y_train, verbose=False)

# Оценка модели
predictions = model.predict(X_test)
accuracy = accuracy_score(y_test, predictions)
print(f'Точность: {accuracy}')

2. Регрессия

from catboost import CatBoostRegressor
import numpy as np

# Подготовка данных
X = np.random.rand(100, 10)
y = np.random.rand(100)

# Разделение данных
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# Создание и обучение модели
regressor = CatBoostRegressor(iterations=200, depth=4, learning_rate=0.01)
regressor.fit(X_train, y_train, verbose=False)

# Предсказание и оценка
predictions = regressor.predict(X_test)
print(predictions)

3. Работа с категориальными данными

from catboost import Pool, CatBoostClassifier

# Подготовка данных
cat_features = [0, 2, 5] # индексы категориальных признаков
data = Pool(data=X_train, label=y_train, cat_features=cat_features)

# Создание и обучение модели
model = CatBoostClassifier(iterations=300, learning_rate=0.05)
model.fit(data, verbose=False)

4. Использование предварительно обученной модели для предсказания

# Загрузка сохранённой модели
model = CatBoostClassifier()
model.load_model('catboost_model.dump')

# Делаем предсказания
predictions = model.predict(X_test)
print(predictions)

5. Перекрёстная проверка (Cross-Validation)

from catboost import cv, Pool

# Подготовка данных
cv_data = Pool(data=X, label=y, cat_features=cat_features)

# Параметры для CV
params = {'iterations': 100, 'depth': 4, 'loss_function': 'Logloss', 'verbose': False}

# Выполнение перекрестной проверки
cv_results = cv(cv_data, params, fold_count=5, plot=True)
print(cv_results)

Заключение

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

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

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

Комментарии (1)


  1. DryLips
    08.12.2023 05:30
    +1

    А про фичи ембеддингов и текстовые фичи не написали