2025, Sep 30 03:16
Как сравнивать преобразования признаков и цели в регрессии с Pipeline и GridSearchCV
Пошагово сравниваем преобразования признаков и целевой переменной в регрессии с помощью scikit-learn: Pipeline, GridSearchCV, TransformedTargetRegressor.
Оценка разных вариантов преобразований признаков и целевой переменной в одной и той же регрессионной постановке — частая задача. Самый простой путь — накидать несколько конвейеров, обучить их по очереди и сравнить метрики. Это работает, но как только пространство вариантов расширяется, хочется чего‑то в духе GridSearchCV: одного унифицированного механизма, который перебирает допустимые комбинации и выбирает лучший вариант.
Базовый подход: ручной цикл по заранее заданным конвейерам
Шаблон ниже создаёт несколько конвейеров, обучает каждый на одинаковых обучающих данных и записывает MSE и R2, чтобы понять, какая версия показывает лучший результат.
import numpy as np
import pandas as pd
from sklearn.preprocessing import FunctionTransformer, PowerTransformer
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline
from sklearn.metrics import mean_squared_error
from sklearn.compose import TransformedTargetRegressor
model_space = {
'linear': LinearRegression(),
'power': make_pipeline(PowerTransformer(), LinearRegression()),
'log': make_pipeline(FunctionTransformer(np.log, np.exp), LinearRegression()),
'log_sqrt': TransformedTargetRegressor(
regressor=make_pipeline(FunctionTransformer(np.log, np.exp), LinearRegression()),
func=np.sqrt,
inverse_func=np.square
)
}
scores_df = pd.DataFrame()
for label, algo in model_space.items():
algo.fit(X_train, y_train)
y_pred_eval = algo.predict(X_eval)
y_pred_train = algo.predict(X_train)
r2_val = algo.score(X_train, y_train)
scores_df.at[label, 'MSE'] = mean_squared_error(y_train, y_pred_train)
scores_df.at[label, 'R2'] = r2_val
best_key = scores_df['R2'].idxmax()
Подход простой и прозрачный: вы точно знаете, какие конвейеры пробовали, можете обратиться к любому обученному объекту по его ключу и сохранить любые нужные диагностики.
Ограничения подхода
Стоит захотеть более систематический перебор преобразований — и ручной цикл начинает мешать. Вы можете захотеть исключить конкретные сочетания, применять преобразование цели только с некоторыми преобразованиями признаков и при этом сохранить единые настройки оценки. Ровно под такой сценарий и создан GridSearchCV в scikit-learn: он позволяет перечислить допустимые варианты и выбрать из этого пространства лучший оцениватель.
Переход к GridSearchCV с несколькими сетками параметров
Удобнее всего организовать поиск так: задать обобщённый Pipeline из двух шагов и передать список сеток параметров. Несколько сеток позволяют легко исключать «лишние» или некорректные сочетания — достаточно их не указывать. Такой подход также без проблем вмещает TransformedTargetRegressor, когда требуется преобразовать целевую переменную.
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import FunctionTransformer, PowerTransformer
from sklearn.linear_model import LinearRegression
from sklearn.compose import TransformedTargetRegressor
import numpy as np
base_flow = Pipeline([
('transformer', None),
('estimator', LinearRegression())
])
param_maps = [
{'transformer': [FunctionTransformer(np.log, np.exp), PowerTransformer()]},
{
'transformer': [FunctionTransformer(np.log, np.exp)],
'estimator': [
TransformedTargetRegressor(
regressor=LinearRegression(),
func=np.sqrt,
inverse_func=np.square
)
]
}
]
searcher = GridSearchCV(base_flow, param_maps, cv=5)
searcher.fit(X_mat, y_vec)
chosen = searcher.best_estimator_
В этой конфигурации оцениваются только те комбинации, которые вы явно разрешили. Первая сетка перебирает преобразования признаков, которые сразу подаются в LinearRegression. Вторая добавляет путь, где признаки логарифмируются, а целевая преобразуется через TransformedTargetRegressor. За счёт такой структуры нежелательные сочетания не возникают, а пространство поиска остаётся наглядным.
Минус по сравнению с «ручным» словарём — доступ к отдельным обученным вариантам. В цикле каждая модель у вас под рукой. В GridSearchCV вы получаете best_estimator_ и можете изучать cv_results_, но отдельные обученные модели так явно не выдаются.
Зачем всё это
Последовательное сравнение преобразований снижает долю ситуативных решений и держит конфигурацию под контролем. Один объект поиска объединяет логику оценки, задаёт единые настройки кросс‑валидации и позволяет рассматривать преобразование цели наравне с конвейерами признаков.
Итоги
Если вы проверяете несколько преобразований для регрессии, начните с общего Pipeline с именованными шагами и перечислите в списке сеток только те комбинации, которые реально хотите рассматривать. Обучите через GridSearchCV и заберите победивший оцениватель из best_estimator_. Если важно сохранить все обученные варианты для ручного анализа, схема «словарь + цикл» остаётся рабочей альтернативой. Выбирайте путь, который соответствует нужному уровню контроля и автоматизации на этапе оценки.