You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用sklearn ColumnTransformer时特征名长度与X实际维度不匹配

sklearn预处理流水线特征名数量与转换后维度不匹配问题

问题场景

搭建如下预处理流水线用于模型训练:

from sklearn.compose import make_column_selector as selector
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer

cat_imputer = SimpleImputer(strategy='constant',fill_value='missing')
num_imputer = SimpleImputer(strategy='constant',fill_value=0,add_indicator=True)

categorical_pipeline = Pipeline([
    ('imputer',cat_imputer),
    ('encoder',OneHotEncoder())
])

numerical_pipeline = Pipeline([
    ('imputer',num_imputer)
])

def get_column_types(X):
    numerical_columns = numerical_columns_selector(X)
    categorical_columns = categorical_columns_selector(X)
    return numerical_columns, categorical_columns

def get_transformer(X,y):
    numerical_columns, categorical_columns = get_column_types(X)
    pre_transformer = ColumnTransformer([
        ('cat_pipe', pre_categorical_pipeline, categorical_columns),
        ('num_pipe', pre_numerical_pipeline, numerical_columns)
        ])
    return transformer

拟合转换器后,使用如下代码提取特征名,出现特征数量不匹配问题:

transformer = models_and_pipelines.get_transformer(X,y)
X = transformer.fit_transform(X)

# 提取特征名,尝试其他同类特征提取函数得到相同结果
starting_features = list(transformer.transformers_[0][1]['encoder'].get_feature_names()) +  list(transformer.transformers_[1][2])

print(X.shape[1])
print(len(starting_features))

运行输出:

1094
1090

转换后的特征矩阵维度为1094,但手动拼接的特征名仅1090个,二者差4个特征。

根本原因

  • 差值来自数值特征预处理器的配置:初始化数值列缺失值填充器SimpleImputer时,设置了add_indicator=True。该参数开启后,会对每一列存在缺失值的数值特征,额外生成1列0/1指示特征,标记该行对应位置是否为填充的缺失值。手动拼接特征名时,仅统计了原始数值列的列名,没有计入这部分额外生成的缺失指示特征,差的4个特征正好对应4列存在缺失值的数值列生成的指示列。
  • 现有特征拼接逻辑还存在两处隐患:
    • 调用OneHotEncoder.get_feature_names()时没有传入原始分类列名,生成的特征名默认是x0_xxx、x1_xxx这类无业务含义的名称,无法映射到原始字段
    • 代码存在变量名笔误:get_transformer函数内定义的预处理器名为pre_transformer,分类、数值流水线变量名为categorical_pipeline/numerical_pipeline,但函数内引用的是未定义的pre_categorical_pipeline/pre_numerical_pipeline,最终返回的也是未定义的transformer变量,运行时会直接抛出变量不存在的错误。

修复方法

手动拼接特征名时,需要把缺失值指示器生成的特征名也纳入统计,参考实现:

# 提取分类流水线独热编码生成的特征名
cat_pipe = transformer.transformers_[0][1]
cat_features = list(cat_pipe['encoder'].get_feature_names_out(cat_pipe.feature_names_in_))

# 提取数值流水线原始列名 + 缺失指示器生成的特征名
num_pipe = transformer.transformers_[1][1]
num_features = list(num_pipe.feature_names_in_)
if hasattr(num_pipe['imputer'], 'indicator_'):
    num_features += list(num_pipe['imputer'].indicator_.get_feature_names_out())

all_features = cat_features + num_features

提示:sklearn 1.0及以上版本中,所有转换器都自带get_feature_names_out方法,拟合完成后直接调用transformer.get_feature_names_out()即可拿到全量正确的特征名,无需手动拼接。

内容的提问来源于stack exchange,提问作者Jeroen Vermunt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 00:24:21