Sklearn ColumnTransformer + Pipeline = TypeError
Posted
技术标签:
【中文标题】Sklearn ColumnTransformer + Pipeline = TypeError【英文标题】: 【发布时间】:2021-06-17 08:36:36 【问题描述】:我正在尝试正确使用 sklearn 中的管道和列转换器,但总是以错误告终。我在下面的例子中重现了它。
# Data to reproduce the error
X = pd.DataFrame([[1, 2 , 3, 1 ],
[1, '?', 2, 0 ],
[4, 5 , 6, '?']],
columns=['A', 'B', 'C', 'D'])
#SimpleImputer to change the values '?' with the mode
impute = SimpleImputer(missing_values='?', strategy='most_frequent')
#Simple one hot encoder
ohe = OneHotEncoder(handle_unknown='ignore', sparse=False)
col_transfo = ColumnTransformer(transformers=[
('missing_vals', impute, ['B', 'D']),
('one_hot', ohe, ['A', 'B'])],
remainder='passthrough'
)
然后调用transformer如下:
col_transfo.fit_transform(X)
返回以下错误:
TypeError: Encoders require their input to be uniformly strings or numbers. Got ['int', 'str']
【问题讨论】:
【参考方案1】:它给你一个错误,因为OneHotEncoder
只接受一种数据格式。在您的情况下,它是numbers
和object
的混合体。为了克服这个问题,您可以在 imputer
和 OneHotEncoder
之后分离管道,以便在 imputing
的输出上使用 astype
方法。比如:
ohe.fit_transform(imputer.fit_transform(X[['A','B']]).astype(float))
【讨论】:
但是在应用 SimpleImputer 之后,我们应该在每一列中都只有整数,不是吗?此外,如果我最终这样做了,我将不得不分别处理训练和测试,而单个管道允许单个拟合。 不,您将pipeline
与 ColumnTransformer
混淆了。每个变压器的流水线输出是下一个变压器的输入。但是,您的代码中的 ColumnTransformer
正在对 X
数据帧的不同列进行不同的转换。
这个想法是之后能够在管道中使用col_transfo
。例如Pipeline(steps=[('preprocessing', col_transfo), ('model', RandomForestClassifier)])
。使用您的解决方案,我觉得我必须分别进行训练、验证和测试,并手动转换数据框以添加新列,删除列“A”和“B”等等。【参考方案2】:
错误不是来自 ColumnTransformer 而是来自 OneHotEncoder 对象
col_transfo = ColumnTransformer(transformers=[
('missing_vals', impute, ['B', 'D'])],
remainder='passthrough'
)
col_transfo.fit_transform(X)
数组([[2, 1, 1, 3], [2, 0, 1, 2], [5, 0, 4, 6]], dtype=object)
ohe.fit_transform(X)
TypeError: 参数必须是字符串或数字
OneHotEncoder 抛出此错误是因为对象获取混合类型的值(int + string)以在同一列上进行编码,您需要将浮点列转换为字符串才能应用它
【讨论】:
【参考方案3】:ColumnTransformer
并行应用其变压器,而不是按顺序应用。所以OneHotEncoder
看到未估算的列B
并拒绝混合类型。
在您的情况下,只需对所有列进行估算,然后编码 A, B
:
encoder = ColumnTransformer(transformers=[
('one_hot', ohe, ['A', 'B'])],
remainder='passthrough'
)
preproc = Pipeline(steps=[
('impute', impute),
('encode', encoder),
# optionally, just throw the model here...
])
如果A,C
中的未来缺失值会导致错误很重要,那么同样将impute
包装到它自己的ColumnTransformer
中。
另见Apply multiple preprocessing steps to a column in sklearn pipeline
【讨论】:
谢谢。从那以后我就明白了。 sklearn 文档只是忽略了它不是按顺序应用而是并行应用的事实。这样可以避免很多麻烦:)以上是关于Sklearn ColumnTransformer + Pipeline = TypeError的主要内容,如果未能解决你的问题,请参考以下文章
sklearn ColumnTransformer:变压器中的重复列
sklearn OneHotEncoder 与 ColumnTransformer 导致稀疏矩阵代替创建假人
sklearn Pipeline:“ColumnTransformer”类型的参数不可迭代
sklearn.compose.ColumnTransformer:fit_transform() 接受 2 个位置参数,但给出了 3 个
Sklearn ColumnTransformer + Pipeline = TypeError
将 FunctionTransformer 与 sklearn Pipeline 和 ColumnTransformer 一起使用 - 错误:无效的类型提升