从 sklearn 列转换器中提取特征名称

Extracting feature names from sklearn column transformer

我正在使用 sklearn.pipeline 来转换我的特征并拟合模型,因此我的一般流程如下所示:列转换器 --> 通用管道 --> 模型。我希望能够从列转换器中提取特征名称(从接下来的步骤开始,通用管道对所有列应用相同的转换,例如 nan_to_zero)并将它们用于模型可解释性(例如特征重要性)。我也希望它也能与自定义转换器 类 一起使用。

设置如下:

import numpy as np
import pandas as pd
from sklearn import compose, pipeline, preprocessing

df = pd.DataFrame({"a": [1, 2, 3], "b": [1, 2, 3], "c": ["x", "y", "z"]})
column_transformer = compose.make_column_transformer(
   (preprocessing.StandardScaler(), ["a", "b"]),
   (preprocessing.KBinsDiscretizer(n_bins=2, encode="ordinal"), ["a"]),
   (preprocessing.OneHotEncoder(), ["c"]),
)
pipe = pipeline.Pipeline([
   ("transform", column_transformer),
   ("nan_to_num", preprocessing.FunctionTransformer(np.nan_to_num, validate=False))
])
pipe.fit_transform(df)  # returns a numpy array

到目前为止,我已经尝试使用 get_feature_names_out,例如:

pipe.named_steps["transform"].get_feature_names_out()

但我 运行 进入 get_feature_names_out() takes 1 positional argument but 2 were given,不确定发生了什么,但整个过程感觉不对。有更好的方法吗?

编辑: 非常感谢@amiola 回答问题,这确实是问题所在。我只是想为后代补充另一个重点:我在使用自己的自定义管道时遇到了其他问题,并且遇到了错误 get_feature_names_out() takes 1 positional argument but 2 were given。所以事实证明,除了 KBinsDiscretizer 之外,我的自定义转换器 类 中还有另一个错误。我实现了 get_feature_names_out 方法,但它在我这边不接受任何参数,这就是问题所在。如果您 运行 遇到类似问题,请确保此方法具有以下签名:get_feature_names_out(self, input_features) -> List[str].

问题似乎是由传递给 KBinsDiscretizer 构造函数的 encode="ordinal" 参数引起的。在 GitHub issue #22731 and GitHub issue #22841 and solved with PR #22735.

中跟踪了错误

实际上,您可能会发现通过指定 encode="onehot" 您可能会得到一致的结果:

import numpy as np
import pandas as pd
from sklearn import compose, pipeline, preprocessing

df = pd.DataFrame({"a": [1, 2, 3], "b": [1, 2, 3], "c": ["x", "y", "z"]})
column_transformer = compose.make_column_transformer(
   (preprocessing.StandardScaler(), ["a", "b"]),
   (preprocessing.KBinsDiscretizer(n_bins=2, encode="onehot"), ["a"]),
   (preprocessing.OneHotEncoder(), ["c"]),
)
pipe = pipeline.Pipeline([
   ("transform", column_transformer),
   ("nan_to_num", preprocessing.FunctionTransformer(np.nan_to_num, validate=False))
])
pipe.fit_transform(df) 

pipe.named_steps['transform'].get_feature_names_out()

# array(['standardscaler__a', 'standardscaler__b', 'kbinsdiscretizer__a_0.0', 'kbinsdiscretizer__a_1.0','onehotencoder__c_x', 'onehotencoder__c_y', 'onehotencoder__c_z'], dtype=object)

除此之外,我觉得一切都很好。

最后,显然,即使安装 nightly builds,我仍然得到同样的错误。