SKLEARN // 将GridsearchCV与列转换和管道组合

4

我正在处理一个机器学习项目,尝试将以下内容结合起来:

  • 使用sklearn列变换对我的数字和类别特征应用不同的转换器
  • 使用管道对我的不同转换器和评估器进行应用
  • 使用GridSearchCV搜索最佳参数。

只要我在管道中手动填写不同转换器的参数,代码就能完美运行。但是,一旦我尝试传递列表比较网格搜索参数中的不同值,我就会收到各种无效参数错误消息。

下面是我的代码:

首先将我的特征分为数字和类别两个部分

from sklearn.compose import make_column_selector
from sklearn.pipeline import make_pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.impute import KNNImputer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder


numerical_features=make_column_selector(dtype_include=np.number)
cat_features=make_column_selector(dtype_exclude=np.number)

然后我为数值特征和分类特征创建两个不同的预处理管道:

numerical_pipeline= make_pipeline(KNNImputer())
cat_pipeline=make_pipeline(SimpleImputer(strategy='most_frequent'),OneHotEncoder(handle_unknown='ignore'))

我将两者结合到另一个管道中,设置参数,然后运行我的 GridSearchCV 代码。

model=make_pipeline(preprocessor, LinearRegression() )

params={
    'columntransformer__numerical_pipeline__knnimputer__n_neighbors':[1,2,3,4,5,6,7]
}

grid=GridSearchCV(model, param_grid=params,scoring = 'r2',cv=10)
cv = KFold(n_splits=5)
all_accuracies = cross_val_score(grid, X, y, cv=cv,scoring='r2')

我尝试了不同的参数声明方式,但从未找到正确的方法。我总是收到“无效参数”错误消息。
请帮助我理解出了什么问题?
非常感谢您的支持,保重!

你忘记定义 preprocessor 了。尝试使用 grid.get_params() - Ben Reiniger
1个回答

2
我假设您可能已经按照以下方式定义了preprocessor
preprocessor = Pipeline([('numerical_pipeline',numerical_pipeline),
                        ('cat_pipeline', cat_pipeline)])

那么你需要将参数更改为以下内容:

pipeline__numerical_pipeline__knnimputer__n_neighbors

但是,这段代码还有其他几个问题:

  1. 在执行完GridSearchCV后,不需要调用cross_val_score。GridSearchCV本身的输出结果就包含了每种超参数组合的交叉验证结果。

  2. 当数据中包含字符串数据时,KNNImputer无法正常工作。您需要先应用cat_pipeline,然后再应用num_pipeline

完整示例:

from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import make_column_transformer
from sklearn.compose import make_column_selector
import pandas as pd  # doctest: +SKIP
X = pd.DataFrame({'city': ['London', 'London', 'Paris', np.nan],
                  'rating': [5, 3, 4, 5]})  # doctest: +SKIP

y = [1,0,1,1]

from sklearn.compose import make_column_selector
from sklearn.pipeline import make_pipeline, Pipeline
from sklearn.model_selection import GridSearchCV
from sklearn.impute import KNNImputer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import cross_val_score, KFold
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder


numerical_features=make_column_selector(dtype_include=np.number)
cat_features=make_column_selector(dtype_exclude=np.number)

numerical_pipeline= make_pipeline(KNNImputer())
cat_pipeline=make_pipeline(SimpleImputer(strategy='most_frequent'),
                            OneHotEncoder(handle_unknown='ignore', sparse=False))
preprocessor = Pipeline([('cat_pipeline', cat_pipeline),
                        ('numerical_pipeline',numerical_pipeline)])
model=make_pipeline(preprocessor, LinearRegression() )

params={
    'pipeline__numerical_pipeline__knnimputer__n_neighbors':[1,2]
}


grid=GridSearchCV(model, param_grid=params,scoring = 'r2',cv=2)

grid.fit(X, y)

1
感谢您及时而详细的反馈。这真的很有帮助,现在已经完美地运行了。为了创建预处理器管道,我使用了make_pipeline而不是pipeline,似乎这是瓶颈所在。还要感谢您关于cat_pipeline和numerical_pipeline的提示。我认为,由于列转换允许不同的预处理,它们的顺序并不重要。再次感谢您,祝您有愉快的一天! - Xavier Fournat
1
ColumnTransformer 转换器的顺序无关紧要。这个答案不包括 ColumnTransformer,而是另一个管道。 - Ben Reiniger
没错。在这里使用列转换器是无用的,因为我们必须在KNN填充之前应用OHE。 - Venkatachalam
@Venkatachalam:还有一个元素我不太明白。在我的数值特征中,我想添加其他的转换器,如下所示:numerical_pipeline= make_pipeline(KNNImputer(),preprocessing.StandardScaler(),PolynomialFeatures()) 但是我没有找到适当的方法来测试网格搜索CV参数中的多项式特征。根据您的指导,我添加了:'pipeline__numerical_pipeline__polynomialfeatures__degree':[2,3,4] 但似乎这并不起作用。您能帮我解决这个问题吗?非常感谢。 - Xavier Fournat
当然,您可以提出一个更详细的问题吗?请单独提问。 - Venkatachalam
但是 numerical_features 和 cat_features 什么时候出现在后面的过程中呢?在定义哪些列属于哪种类型之后,应该指示各自的管道处理特定的特征类型。 - Fredrik

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