通过嵌套的RFECV和GridSearchCV传递Pipeline时遇到的问题

3
我正在尝试在sklearn的嵌套CV内部循环中执行特征选择和网格搜索。虽然我可以将管道作为估计器传递给RFECV,但当我将RFECV作为估计器传递给GridSearchCV时,在拟合时会收到错误信息。
我发现将管道中模型的名称更改为"estimator"会将错误移动到带有"regression an invalid parameter"的Pipeline中,而不是在RFECV中,无论我用什么名称指定模型都是无效参数。
我已经使用rfcv.get_params().keys()和pipeline.get_params().keys()进行验证,调用的参数确实存在。
如果我直接将SGDRegressor()命名为"estimator"并忽略管道,则不会出现此错误,但该模型需要对Y变量进行特征缩放和对数转换。
from sklearn.compose import TransformedTargetRegressor
from sklearn.pipeline import Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.feature_selection import RFECV
from sklearn.preprocessing import MinMaxScaler
from sklearn.linear_model import SGDRegressor

import numpy as np
# random sample data
X = np.random.rand(100,2)
y = np.random.rand(100)

#passing coef amd importance through pipe and TransformedTargetRegressor
class MyPipeline(Pipeline):
    @property
    def coef_(self):
        return self._final_estimator.coef_
    @property
    def feature_importances_(self):
        return self._final_estimator.feature_importances_

class MyTransformedTargetRegressor(TransformedTargetRegressor):
    @property
    def feature_importances_(self):
        return self.regressor_.feature_importances_

    @property
    def coef_(self):
        return self.regressor_.coef_

# build pipeline
pipeline = MyPipeline([ ('scaler', MinMaxScaler()),
                     ('estimator', MyTransformedTargetRegressor(regressor=SGDRegressor(), func=np.log1p, inverse_func=np.expm1))]) 

# define tuning grid
parameters = {"estimator__regressor__alpha": [1e-5,1e-4,1e-3,1e-2,1e-1], 
              "estimator__regressor__l1_ratio": [0.001,0.25,0.5,0.75,0.999]} 

# instantiate inner cv
inner_kv = KFold(n_splits=5, shuffle=True, random_state=42)
rfcv = RFECV(estimator=pipeline, step=1, cv=inner_kv, scoring="neg_mean_squared_error")

cv = GridSearchCV(estimator=rfcv, param_grid=parameters, cv=inner_kv, iid=True,
                  scoring= "neg_mean_squared_error", n_jobs=-1, verbose=True)
cv.fit(X,y)

我收到了以下错误信息,并确认regressor是管道估算器的一个参数:

ValueError: Invalid parameter regressor for estimator MyPipeline(memory=None,
           steps=[('scaler', MinMaxScaler(copy=True, feature_range=(0, 1))),
                  ('estimator',
                   MyTransformedTargetRegressor(check_inverse=True,
                                                func=<ufunc 'log1p'>,
                                                inverse_func=<ufunc 'expm1'>,
                                                regressor=SGDRegressor(alpha=0.0001,
                                                                       average=False,
                                                                       early_stopping=False,
                                                                       epsilon=0.1,
                                                                       eta0=0.01,
                                                                       fit_intercept=True,
                                                                       l1_ratio=0.15,
                                                                       learning_rate='invscaling',
                                                                       loss='squared_loss',
                                                                       max_iter=1000,
                                                                       n_iter_no_change=5,
                                                                       penalty='l2',
                                                                       power_t=0.25,
                                                                       random_state=None,
                                                                       shuffle=True,
                                                                       tol=0.001,
                                                                       validation_fraction=0.1,
                                                                       verbose=0,
                                                                       warm_start=False),
                                                transformer=None))],
           verbose=False). Check the list of available parameters with `estimator.get_params().keys()`.

谢谢

1个回答

2
必须使用estimator__estimator__regressor,因为你在rfecv内部使用了管道。
试试这个!
parameters = {"estimator__estimator__regressor__alpha": [1e-5,1e-4,1e-3,1e-2,1e-1], 
              "estimator__estimator__regressor__l1_ratio": [0.001,0.25,0.5,0.75,0.999]} 

注意:使用嵌套的CV不是正确的方法。也许您可以分别进行特征选择,然后进行模型训练。

谢谢!我使用的数据集非常小,所以希望将这两个嵌套的CV作为内部训练/验证循环,以便从外部CV中获得可推广的误差。如果我将特征选择从嵌套的CV中取出,有没有好的方法来实现这一点?我受到了这种方法的启发: https://stats.stackexchange.com/a/224171 - SlingJay
2
同时找到理想的模型超参数和特征选择总是代价高昂的。我建议先使用相对简单的模型进行特征选择,然后再为模型进行超参数调整。 - Venkatachalam
我一直在使用这个答案,但无法保存(pickle)结果:有没有办法使“class MyPipeline(Pipeline)”可序列化(“pickleable”)? - RamsesII

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接