使用Scikit-learn DecisionTreeClassifier时遇数据格式转换错误求助
问题分析与解决方案
你的错误根源很明确:数据集中存在?这样的非数值字符,这导致你的特征矩阵X的列类型被识别为object(字符串类型),而Scikit-learn的决策树分类器要求输入的特征必须是数值型(整数/浮点数),所以在调用fit()时无法将字符串?转换为浮点数,抛出了ValueError。
具体排查步骤
先确认哪些列包含异常值?,可以用以下代码快速统计:
# 检查每列中?的数量 print(X.isin(['?']).sum())
通常在乳腺癌数据集里,bare_nucleoli列是最常出现?的列。
解决方案:处理异常值并转换为数值型
这里提供两种常用的处理方式,你可以根据数据集大小选择:
方式1:删除包含异常值的行(适合数据集较大的情况)
如果你的数据集样本量足够多,直接删掉带?的行是最简单的方式:
import pandas as pd import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split # 导入数据集 data = pd.read_table('Data/Breast.csv') # 过滤掉包含?的行 data_clean = data[data.apply(lambda row: '?' not in row.values, axis=1)] # 提取特征和目标变量 X = data_clean[['clump_thickness','shape_uniformity','marginal_adhesion','epithelial_size','bare_nucleoli','bland_chromatin','normal_nucleoli','mitoses']] Y = data_clean['class'] # 拆分数据集并训练 X_train, X_test, Y_train, Y_test = train_test_split(X.values, Y.values, test_size=0.2, random_state=42) model = DecisionTreeClassifier() model.fit(X_train, Y_train)
方式2:填充缺失值(更推荐,避免丢失样本)
把?视为缺失值,用统计量(比如中位数、均值)填充,适合样本量较少的场景:
import pandas as pd import numpy as np from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.impute import SimpleImputer # 导入时直接把?识别为缺失值NaN data = pd.read_table('Data/Breast.csv', na_values=['?']) # 提取特征和目标变量 X = data[['clump_thickness','shape_uniformity','marginal_adhesion','epithelial_size','bare_nucleoli','bland_chromatin','normal_nucleoli','mitoses']] Y = data['class'] # 用中位数填充缺失值(分类任务中中位数比均值更鲁棒) imputer = SimpleImputer(strategy='median') X_processed = imputer.fit_transform(X) # 拆分数据集并训练 X_train, X_test, Y_train, Y_test = train_test_split(X_processed, Y, test_size=0.2, random_state=42) model = DecisionTreeClassifier() model.fit(X_train, Y_train)
额外提示
- 提取目标变量
Y时,直接用data['class']得到Series即可,不需要用双层列表data[['class']],这样Y.values会是1维数组,更符合Scikit-learn的输入要求。 - 训练前记得拆分训练集和测试集,这样可以评估模型的泛化能力,避免过拟合。
内容的提问来源于stack exchange,提问作者Tobias Piechowiak
相关产品推荐
相关产品推荐

