是否可以将 TransformedTargetRegressor 添加到 scikit-learn 管道中?

Posted

技术标签:

【中文标题】是否可以将 TransformedTargetRegressor 添加到 scikit-learn 管道中?【英文标题】:Is it possible to add TransformedTargetRegressor into a scikit-learn pipeline? 【发布时间】:2019-09-15 10:43:47 【问题描述】:

我正在对一些数据建立预测分析管道,并且正在选择模型。我的目标变量是倾斜的,所以我想对它进行对数转换,以提高我的线性回归估计器的性能。我遇到了 scikit-learn 相对较新的TransformedTargetRegressor,我认为我可以将它用作管道的一部分。我附上我的代码

我最初的尝试是在调用gs.fit() 之前转换y_train,将其转换为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()

显然这段代码 sn-p 不起作用,因为显然我无法将 TransformedTargetRegressor 添加到我的管道中,因为它没有 transform 方法(我得到这个 TypeError: TypeError: All中间步骤应该是转换器并实现拟合和转换)。

是否有“正确”的方式来执行此操作,或者当我想调用 r2_score 函数等时,我是否只需要即时进行 y_val 的日志转换?

【问题讨论】:

【参考方案1】:

不,因为 scikit-learn 原始 Pipeline 在步骤期间不会更改 yXy 中的样本数。

您的用例不太清楚。如果相同的reg 已经添加到TransformedTargetRegressor,那么reg 步骤的需要是什么?

查看documentation of TransformedTargetRegressor,参数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]
              ]

【讨论】:

以上是关于是否可以将 TransformedTargetRegressor 添加到 scikit-learn 管道中?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以将 MPMoviePlayerController 静音?

是否可以将数据传递给css文件?

是否可以将 Lua 脚本修改为要求?

是否可以将 iOS MultipeerConnectivity 与 android 连接?

是否可以将 FastAPI 与 Django 一起使用?

是否可以将 TypeScript 编译成缩小代码?