我正在使用sklearn
并mlxtend.regressor.StackingRegressor
构建一个堆叠回归模型。例如,假设我想要以下小管道:
- 具有两个回归量的堆叠回归量:
- 一个管道,它:
- 执行数据插补
- 1-hot 编码分类特征
- 执行线性回归
- 一个管道,它:
- 执行数据插补
- 使用决策树执行回归
- 一个管道,它:
不幸的是,这是不可能的,因为StackingRegressor
不接受NaN
其输入数据。即使它的回归器知道如何处理NaN
也是如此,因为在我的情况下,回归器实际上是执行数据插补的管道。
但是,这不是问题:我可以将数据插补移到堆叠回归器之外。现在我的管道看起来像这样:
- 执行数据插补
- 应用具有两个回归量的堆叠回归量:
- 一个管道,它:
- 1-hot 编码分类特征
- 标准化数字特征
- 执行线性回归
- 一个
sklearn.tree.DecisionTreeRegressor
。
- 一个管道,它:
可以尝试按如下方式实现它(本要点中的整个最小工作示例,带有注释):
sr_linear = Pipeline(steps=[
('preprocessing', ColumnTransformer(transformers=[
('categorical',
make_pipeline(OneHotEncoder(), StandardScaler()),
make_column_selector(dtype_include='category')),
('numerical',
StandardScaler(),
make_column_selector(dtype_include=np.number))
])),
('model', LinearRegression())
])
sr_tree = DecisionTreeRegressor()
ct_imputation = ColumnTransformer(transformers=[
('categorical',
SimpleImputer(strategy='constant', fill_value='None'),
make_column_selector(dtype_include='category')),
('numerical',
SimpleImputer(strategy='median'),
make_column_selector(dtype_include=np.number))
])
stacked_regressor = Pipeline(steps=[
('imputation', ct_imputation),
('back_to_pandas', FunctionTransformer(
func=lambda values: pd.DataFrame(values, columns=ct_imputation.get_feature_names_out())
)),
('model', StackingRegressor(
regressors=[sr_linear, sr_tree],
meta_regressor=DecisionTreeRegressor(),
use_features_in_secondary=True
))
])
请注意,“外部” ColumnTransformer
(in stacked_regressor
)返回一个numpy
矩阵。但是“内部” ColumnTransformer
(in sr_linear
)需要 a pandas.DataFrame
,所以我不得不使用 step 将矩阵转换回数据框back_to_pandas
。(要使用get_feature_names_out
我必须使用 sklearn 的 nightly 版本,因为当前稳定的 1.0.2 版本还不支持它。幸运的是它可以通过一个简单的命令安装。)
上面的代码在调用时失败stacked_regressor.fit()
,出现以下错误(整个堆栈跟踪再次在gist中):
ValueError: make_column_selector can only be applied to pandas dataframes
但是,因为我在back_to_pandas
外部管道中添加了该步骤,所以内部管道应该得到一个 pandas 数据框!事实上,如果我只是fit_transform()
我的ct_imputation
对象,我清楚地获得了一个熊猫数据框。我无法理解传递的数据究竟在何时何地不再是数据框。为什么我的代码失败了?