Можно ли добавить TransformedTargetRegressor в конвейер scikit-learn? - PullRequest
0 голосов
/ 26 апреля 2019

Я настраиваю конвейер прогнозной аналитики для некоторых данных, и я нахожусь в процессе выбора модели. Моя целевая переменная искажена, поэтому я хотел бы преобразовать ее, чтобы повысить производительность моих оценок линейной регрессии. Я столкнулся с относительно новым TransformedTargetRegressor scikit-learn и подумал, что смогу использовать его как часть конвейера. Я прилагаю свой код

Моей первоначальной попыткой было преобразовать y_train перед вызовом gs.fit(), приведя его к np.log1p(y_train). Это работает, и я могу выполнить вложенную перекрестную проверку и вернуть интересующие метрики для всех оценщиков. Однако я хотел бы иметь возможность получить R ^ 2 и RMSE для обученной модели по ранее невидимым данным (набор проверки), и я понимаю, что для этого мне нужно использовать (например) r2_score функцию на y_val, preds, где прогнозы необходимо преобразовать обратно в реальные значения, т. е. preds = np.expm1(gs.predict(X_val))

### Create a pipeline
pipe = Pipeline([
    # the transformer stage is populated by the param_grid
    ('transformer', TransformedTargetRegressor(func=np.log1p, inverse_func=np.expm1)),
    ('reg', DummyEstimator())  # Placeholder Estimator
])

### Candidate learning algorithms and their hyperparameters
alphas = [0.001, 0.01, 0.1, 1, 10, 100]
param_grid = [  
                {'transformer__regressor': Lasso(),
                 'reg': [Lasso()], # Actual Estimator
                 'reg__alpha': alphas},
                {'transformer__regressor': LassoLars(),
                 'reg': [LassoLars()], # Actual Estimator
                 'reg__alpha': alphas},
                {'transformer__regressor': Ridge(),
                 'reg': [Ridge()], # Actual Estimator
                 'reg__alpha': alphas},
                {'transformer__regressor': ElasticNet(),
                 'reg': [ElasticNet()], # Actual Estimator
                 'reg__alpha': alphas,
                 'reg__l1_ratio': [0.25, 0.5, 0.75]}]


### Create grid search (Inner CV)
gs = GridSearchCV(pipe, param_grid=param_grid, cv=5, verbose=2, n_jobs=-1,
                  scoring=scoring, refit='r2', return_train_score=True)


### Fit
best_model = gs.fit(X_train, y_train)

### scoring metrics for outer CV
scoring = ['neg_mean_absolute_error', 'r2', 'explained_variance', 'neg_mean_squared_error']

### Outer CV
linear_cv_results = cross_validate(gs, X_train, y_train_transformed,
                                   scoring=scoring, cv=5, verbose=3, return_train_score=True)

### Calculate mean metrics
train_r2 = (linear_cv_results['train_r2']).mean()
test_r2 = (linear_cv_results['test_r2']).mean()
train_mae = (-linear_cv_results['train_neg_mean_absolute_error']).mean()
test_mae = (-linear_cv_results['test_neg_mean_absolute_error']).mean()
train_exp_var = (linear_cv_results['train_explained_variance']).mean()
test_exp_var = (linear_cv_results['test_explained_variance']).mean()
train_rmse = (np.sqrt(-linear_cv_results['train_neg_mean_squared_error'])).mean()
test_rmse = (np.sqrt(-linear_cv_results['test_neg_mean_squared_error'])).mean()

Очевидно, что этот фрагмент кода не работает, потому что, очевидно, я не могу добавить TransformedTargetRegressor в свой конвейер, так как у него нет метода transform (я получаю TypeError: TypeError: Все промежуточные шаги должны быть трансформеры и осуществлять подгонку и преобразование ).

Есть ли "правильный" способ сделать это, или мне просто нужно принять преобразование журнала y_val на лету, когда я хочу вызвать r2_score функцию и т. Д.?

1 Ответ

2 голосов
/ 26 апреля 2019

Нет, потому что оригинал scikit-learn Pipeline не меняет y или количество выборок в X и y во время шагов.

Ваш вариант использования немного неясен. Вы поняли, как работает TransformedTargetRegressor? Зачем нужен шаг reg, если тот же reg уже добавлен к TransformedTargetRegressor?

Прослушивание в [документации TransformedTargetRegressor] ( https://scikit -learn.org / stable / modules / generate / sklearn.compose.TransformedTargetRegressor.html ), параметр regressor принимает регрессор (который также может быть конвейером с некоторыми операциями выбора функций) на X и регрессор на завершающей стадии). Рабочая TransformedTargetRegressor будет:

fit():

    regressor.fit(X, func(y))

predict():

    inverse_func(regressor.predict(X))

Так что нет необходимости добавлять этот же регрессор в качестве нового шага. Код выбора вашей модели теперь может быть:

pipe = TransformedTargetRegressor(regressos = DummyEstimator(),
                                  func=np.log1p, 
                                  inverse_func=np.expm1)),

### Candidate learning algorithms and their hyperparameters
alphas = [0.001, 0.01, 0.1, 1, 10, 100]
param_grid = [  
                {'transformer__regressor': Lasso(),
                 'transformer__regressor__alpha': alphas},
                {'transformer__regressor': LassoLars(),
                 'transformer__regressor__alpha': alphas},
                {'transformer__regressor': Ridge(),
                 'transformer__regressor__alpha': alphas},
                {'transformer__regressor': ElasticNet(),
                 'transformer__regressor__alpha': alphas,
                 'transformer__regressor__l1_ratio': [0.25, 0.5, 0.75]}
              ]
...