Ответ
Главная задача — избежать утечки данных из целевой переменной (y) в мета-признаки. Для этого используется двухуровневая процедура, часто реализуемая через k-фолдовую кросс-валидацию.
Схема корректной валидации для стекинга:
- Исходный набор данных делится на обучающую (Train) и финальную тестовую (Hold-out) выборки. Hold-out откладывается до самого конца и не участвует в создании мета-признаков.
- На обучающей выборке (Train) выполняется
k-фолдовая кросс-валидация для каждой базовой модели (например, RandomForest, XGBoost, SVM). - На каждом шаге CV модель обучается на
k-1фолдах, а ее предсказания для оставшегося фолда (out-of-fold predictions, OOF) сохраняются. В итоге получается полный вектор OOF-предсказаний по всем объектам Train. - Эти OOF-предсказания от всех базовых моделей становятся мета-признаками для обучения мета-модели (например, линейной регрессии или логистической регрессии).
- Мета-модель обучается на этих мета-признаках и истинных значениях
y_train. - Для получения финальных предсказаний на Hold-out или новых данных:
- Каждая базовая модель, обученная на всем Train, делает предсказание.
- Эти предсказания подаются как входные признаки в обученную мета-модель.
Пример кода для создания OOF-признаков:
import numpy as np
from sklearn.model_selection import KFold
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
# Исходные данные (без Hold-out)
X_train, y_train = ...
kf = KFold(n_splits=5, shuffle=True, random_state=42)
oof_predictions = np.zeros((X_train.shape[0], len(base_models)))
# Для каждой базовой модели
for model_idx, base_model in enumerate(base_models):
col_oof = np.zeros(X_train.shape[0])
for fold, (train_idx, val_idx) in enumerate(kf.split(X_train, y_train)):
X_tr, X_val = X_train[train_idx], X_train[val_idx]
y_tr = y_train[train_idx]
# Обучаем базовую модель на фолде
model = clone(base_model)
model.fit(X_tr, y_tr)
# Предсказываем на валидационном фолде
col_oof[val_idx] = model.predict(X_val)
oof_predictions[:, model_idx] = col_oof
# OOF-предсказания — это мета-признаки для Train
meta_features_train = oof_predictions
# Обучаем мета-модель на этих признаках
meta_model = LinearRegression()
meta_model.fit(meta_features_train, y_train)
Блендинг — это упрощенная версия стекинга, где мета-признаки создаются путем предсказания базовых моделей на одной отдельной валидационной выборке (обычно 10-20% от Train), а не на всех фолдах. Метод проще, но менее устойчив, чем стекинг с кросс-валидацией.