ValueError:调用 cross_val_score 时发现未知类别

Posted

技术标签:

【中文标题】ValueError:调用 cross_val_score 时发现未知类别【英文标题】:ValueError: Found unknown categories while calling cross_val_score 【发布时间】:2021-04-21 06:05:49 【问题描述】:

我将 Titanic 数据集作为我的第一个 Kaggle 项目。但是我收到了这个用户警告,我正在尝试找出如何摆脱它。

所以我做了两个预处理子管道:

num_pipeline = Pipeline([
('imputer', SimpleImputer( strategy='median')), 
('scaler', StandardScaler()) ])

cat_pipeline = Pipeline([
('imputer', SimpleImputer(strategy='constant', fill_value='missing')),
('onehot', OneHotEncoder()) ])

我选择的用于构建模型的功能是:

numeric_features = ['Age', 'SibSp', 'Parch', 'Fare']
categorical_features = ['Pclass', 'Sex',  'Embarked']

我的预处理管道是:

preprocessor = ColumnTransformer(
transformers = [
    ('num', num_pipeline, numeric_features),
    ('cat', cat_pipeline, categorical_features)
])

在我的最终管道中,我添加了一个分类器:

clf = Pipeline([
('Preprocessor' , preprocessor),
('Classifier', DecisionTreeClassifier()) ])

然后我调用 cross_val_score 来评估模型,这就是我收到用户警告的时候:

cross_val_score(clf, X_train, y_train, cv=3, scoring="accuracy")

ValueError:在转换期间在第 2 列中发现未知类别 ['Missing'] 用户警告,

数组([ 南, 0.70403587, 0.74774775])

我的猜测是 cross_val_score 在没有“缺失”类别的情况下获得第一个折叠,然后在另一个带有“缺失”类别的情况下对其进行测试。因此出现错误。 所以我尝试删除“Embarked”中缺失值的行,但仍然得到奇怪的错误。

【问题讨论】:

【参考方案1】:

我自己也遇到了这个问题,然后我意识到为交叉验证的每一折单独运行 OneHotEncoder 是没有意义的。

docs for ColumnTrasnformer 说

在将数据传递给 scikit-learn 之前对其进行处理可能会由于以下原因之一出现问题:

    将来自测试数据的统计数据整合到预处理器中会导致交叉验证分数不可靠(称为数据泄漏),例如在缩放器或插补缺失值的情况下。 您可能希望在参数搜索中包含预处理器的参数。

因此,您将SimpleImputerStandardScaler 放入ColumnTransformer 中是正确的,后者直接放入Pipeline 馈送到cross_val_score:它们将为每个折叠单独重新安装,避免使用来自验证的信息设置。

但是,OneHotEncoder 应该在单独的步骤中运行,然后再将数据提供给cross_val_score,即X_train 应该已经包含单热变量而不是分类变量。

通过这种方式,您不仅可以避免此警告(因为您已经提到在验证集中看到一个类在折叠的训练集中不存在),而且您将保持 one-hot 变量一致,因为它们应该是。换句话说,您不会冒险为每个折叠对 one-hot 变量进行排序或命名。

【讨论】:

【参考方案2】:

我希望你做到了以下几点:

    清理数据集,即填充所有列的所有 na/缺失值 过滤并删除 NaN 行,即所有值 NaN 行

【讨论】:

感谢您的回复。是的,如上所示,我使用 Imputer 处理缺失值。 这很奇怪,您是否再次检查您的数据以确保您的数据中没有缺失/na 或字符串值?从错误消息来看,似乎是数据导致了这种情况。 这就是我的想法:对于分类数据并且专门针对“Embarked”功能,有 2 个缺失值。我将这两个缺失值替换为“Missing”(错误中提到的“['Missing']”类别)。 所以您要替换为字符串('Missing')?并且您正在将包含字符串值的数据提供给您的模型?如果是,那么您不能这样做,您需要预处理所有字符串(分类等)并将它们转换为数值。处理这些字符串数据的方法有很多,你可以查看 sklearn 的OneHotEncoder()LabelEncoder()。可以帮助您解决问题。 完全同意!但是在我将 null 更改为“Missing”之后,我使用 OneHotEncoder()。当我拟合模型时它可以工作(= clf.fit(X_train, y_train) 工作得很好),当我调用 cross_val_score(clf, X_train, y_train, cv=3,scoring="accuracy") 时会出现问题

以上是关于ValueError:调用 cross_val_score 时发现未知类别的主要内容,如果未能解决你的问题,请参考以下文章

训练 yolov3 时出错:- ValueError: tf.function-decorated 函数试图在非第一次调用时创建变量

ValueError:FixedLocator 位置的数量 (5),通常来自对 set_ticks 的调用,与刻度标签的数量 (12) 不匹配

ValueError:PyCapsule_GetPointer 使用不正确的名称调用 <from PyQt5.QtWebEngineWidgets import QWebEnginePage&g

ValueError:您在优化器 RMSprop 上调用了“set_weights(weights)”,权重列表长度为 3,但优化器期望权重为 0

带有 Shap ValueError 的 DeepExplainer:使用不是符号张量的输入调用了 Layersequential_1

LSTM调用tensorflow提示 raise ValueError("Ambiguous dimension: %s" % value),怎么解决?