Ответ
В алгоритмах градиентного бустинга (Gradient Boosting), таких как XGBoost, LightGBM или CatBoost, каждое новое дерево обучается не на исходной целевой переменной y, а на антиградиенте функции потерь (negative gradient), который часто называют псевдо-остатками.
Математическая суть:
На шаге m ансамбль уже делает предсказание F_{m-1}(x). Мы хотим обучить новое дерево h_m(x), которое лучше всего приблизит разницу между истинным значением и текущим предсказанием. Эта разница вычисляется как градиент функции потерь L(y, F) по текущему предсказанию F_{m-1}(x).
Для бинарной классификации с лог-лоссом (logloss):
- Текущее предсказание — это вероятность
p_i = sigmoid(F_{m-1}(x_i)). - Псевдо-остаток (антиградиент) для объекта
iвычисляется как:r_{im} = y_i - p_iгдеy_i ∈ {0, 1}— истинная метка класса. - Новое дерево
h_m(x)обучается именно на этих остаткахr_{im}как на целевых значениях.
Практический пример с XGBoost:
import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# Генерация данных
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# Обучение модели
# Параметр 'objective' определяет функцию потерь, градиент которой вычисляется
model = xgb.XGBClassifier(
objective='binary:logistic', # Используется лог-лосс
n_estimators=100,
learning_rate=0.1
)
model.fit(X_train, y_train)
# Каждое дерево внутри model обучалось на градиентах лог-лосса
Таким образом, бустинг последовательно строит деревья, каждое из которых корректирует ошибки, сделанные предыдущими моделями ансамбля.
Ответ 18+ 🔞
А, ну это классика, ёпта! Слушай, сейчас объясню на пальцах, как эти ваши градиентные бустинги работают, а то народ путается, как будто в тёмной комнате хуй с горы ищет.
Вот представь: у тесть есть куча алгоритмов-деревьев, которые друг за другом учатся, как мартышлюшки в цирке. Так вот, каждое новое дерево — это не просто так, блядь, оно учится не на исходных ответах, а на антиградиенте, или, проще говоря, на псевдо-остатках. Это типа как разница между тем, что мы наговорили, и правдой, понимаешь?
Если по-простому, без зауми:
Допустим, на шаге m наш ансамбль уже строит какие-то предсказания F_{m-1}(x). И мы хотим добавить новое деревце h_m(x), которое будет исправлять наши косяки. А косяки эти — это как раз градиент функции потерь, или, если ещё проще, насколько мы обосрались на предыдущем шаге.
Вот смотри на примере бинарной классификации с лог-лоссом:
- Текущее предсказание — это вероятность
p_i = sigmoid(F_{m-1}(x_i)). Типа, насколько мы уверены, что объект относится к классу 1. - А псевдо-остаток для объекта
i— это простоr_{im} = y_i - p_i. Гдеy_i— это истинная метка (0 или 1), ёпта. - И вот это самое новое дерево
h_m(x)мы и обучаем на этих самых остаткахr_{im}, как на целевых значениях. Оно типа говорит: "Окей, предыдущие ребята тут накосячили вот на столько, давайте я это исправлю".
Практика, блядь, чтобы совсем понятно было: Смотри, вот кусок кода, тут всё как есть:
import xgboost as xgb
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
# Нагенерим данных, чтоб было на чём работать
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# А вот и обучение модели, внимание на параметр 'objective'
model = xgb.XGBClassifier(
objective='binary:logistic', # Вот тут как раз и говорим, что лосс у нас лог-лосс, от него градиенты и считаются
n_estimators=100,
learning_rate=0.1
)
model.fit(X_train, y_train)
# И каждое дерево внутри этой model училось именно на градиентах, которые мы обсудили!
Короче, вся фишка в том, что бустинг — это такая хитрая жопа, которая последовательно строит деревья, где каждое следующее пытается залатать дыры, которые наделали предыдущие. Получается этакий интеллектуальный пазл, где каждый кусочек исправляет ошибки прошлого. Удивление пиздец, но работает-то как!