SkLearn DecisionTree拟合未纳入数值特征、特征数不匹配报错解决
问题根因
报错和数值特征未入模的问题来自两处代码逻辑错误:
- 定义
ColumnTransformer时仅配置了分类特征的OneHotEncoder转换规则,未对数值特征指定处理逻辑。该转换器默认行为是丢弃所有未显式绑定转换器的列,因此数值列num1完全没有进入后续训练流程,模型实际仅接收到分类特征独热编码后生成的8个特征。 - 导出决策树可视化代码时,手动将原始数值列名与独热编码输出列名拼接得到9个特征名,与模型实际输入的8个特征数量不符,直接触发
Length of feature_names, 9 does not match number of features, 8报错。
修复方案
- 给
ColumnTransformer补充数值特征的处理分支:决策树基于特征分裂阈值训练,对数值特征尺度不敏感,数值列可直接用passthrough参数透传;如果数值列存在缺失值,可搭配SimpleImputer做缺失值填充后再传入模型。 - 不要手动拼接特征名:拟合完成后直接调用
ColumnTransformer的get_feature_names_out()方法,即可拿到包含透传数值列、独热编码分类列在内的全部输出特征名称,完全避免特征名长度不匹配问题。
修正后的可运行代码如下:
import pandas as pd import numpy as np from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import OneHotEncoder from sklearn.tree import DecisionTreeClassifier from sklearn import tree import graphviz # 示例数据集 df = pd.DataFrame({'brand' : ['aaaa', 'asdfasdf', 'sadfds', 'NaN'], 'category' : ['asdf','asfa','asdfas','as'], 'num1' : [1, 1, 0, 0] , 'target' : [1,0,0,1]}) dtarget = df['target'] dfeatures = df.drop('target', axis=1) # 区分数值、分类特征列 num_cols = dfeatures.select_dtypes(include=["int64"]).columns.tolist() cat_cols = dfeatures.select_dtypes(include=["object"]).columns.tolist() # 列转换器:同时处理分类、数值特征 transformer = ColumnTransformer( transformers=[ ("cat", OneHotEncoder(handle_unknown='ignore'), cat_cols), ("num", SimpleImputer(strategy="median"), num_cols) # 无缺失值可替换为"passthrough"直接透传 ] ) clf = DecisionTreeClassifier(criterion="entropy", max_depth=5) # 组装训练管道 pipe = Pipeline(steps=[ ('col_transformer', transformer), ('decisiontree', clf) ]) # 模型拟合 pipe.fit(dfeatures, dtarget) # 获取转换后的全部特征名,无需手动拼接 correct_feature_names = pipe.named_steps['col_transformer'].get_feature_names_out().tolist() # 导出决策树可视化结构 dot_data = tree.export_graphviz( clf, out_file=None, feature_names=correct_feature_names, class_names=['0', '1'], filled=True ) # 生成可视化文件 graph = graphviz.Source(dot_data) graph.render("decision_tree_result")
补充说明
- 树模型不需要对数值特征做StandardScaler标准化处理,该步骤不会提升模型效果,只会增加计算冗余。
- OneHotEncoder添加
handle_unknown='ignore'参数后,预测阶段遇到训练集未出现过的分类值时不会直接报错,会将该样本对应独热编码位全部置0。 - 原代码中存在重复导入、导入未使用依赖的问题,修正代码中已经做了清理,不清理也不会影响核心逻辑运行。
内容的提问来源于stack exchange,提问作者esokumamon
相关产品推荐
相关产品推荐

