【问题标题】:Pipeline OrdinalEncoder ValueError Found unknown categoriesPipeline OrdinalEncoder ValueError 发现未知类别
【发布时间】:2019-07-17 01:51:08
【问题描述】:

请放轻松。我正在将职业转向数据科学,并且没有 CS 或编程背景——所以我可能会做一些非常愚蠢的事情。我研究了几个小时都没有成功。

目标:让 Pipeline 与 OrdinalEncoder 一起运行。

问题:代码无法通过 OrdinalEncoder 调用运行。它确实在没有 OrdinalEncoder 的情况下运行。据我所知,我可以传递两个参数,即 categoriesdtype。都没有帮助。

我将公共diabetes data 设置传递给模型。这是问题吗? IOW,将高基数特征传递给 OrdinalEncoder 是否会在模型构建后导致训练/测试数据之间出现问题,即测试拆分具有训练集没有的值?

from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OrdinalEncoder
from sklearn.ensemble import RandomForestClassifier

pipe = Pipeline([
    ('imputer', SimpleImputer()),
    ('ordinal_encoder', OrdinalEncoder()),
    ('classifier', RandomForestClassifier(criterion='gini', n_estimators=100))])

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)

# Construct model
model = pipe.fit(X_train, y_train)

# Show results
print("Hold-out AUC score: %.3f" %roc_auc_score(model.predict_proba(X_test),y_test))

这是我得到的错误:

ValueError: Found unknown categories [17.0] in column 0 during transform

我做错了什么?

设置:

The scikit-learn version is 0.20.2.
3.7.2 (v3.7.2:9a3ffc0492, Dec 24 2018, 02:44:43) 
[Clang 6.0 (clang-600.0.57)]
sys.version_info(major=3, minor=7, micro=2, releaselevel='final', serial=0)

【问题讨论】:

    标签: python-3.x scikit-learn pipeline valueerror ordinal


    【解决方案1】:

    我遇到了完全相同的问题,我只是使用OneHotEncoder(handle_unknown='ignore') 而不是OneHotEncoder() 并且问题已解决。

    【讨论】:

      【解决方案2】:

      您的问题是模型在测试数据中遇到了它在训练数据中没有看到的值。这可以。您只需将“handle_unknown”参数添加到您的编码器。

      您应该将fit 编码器和缩放器用于训练数据(但不是测试数据),然后将它们用于transform 训练和测试数据。因此,您必须为测试数据中出现意外值的可能性做好准备。

      【讨论】:

        【解决方案3】:

        我会考虑在训练期间将序数值存储为 json 文件,并在测试时读取相同的编码。任何进入测试数据集的新值都应该在测试或评估之前处理。

        【讨论】:

          【解决方案4】:

          我遇到了同样的问题,在为我拆分火车和测试工人之前对 X 进行编码。拆分前编码使所有类别都被注册

          【讨论】:

          • 我从来没有使用过 pipeline.fit 但我认为它应该是这样的: pipe = Pipeline([ ('imputer', SimpleImputer()), ('classifier', RandomForestClassifier(criterion= 'gini', n_estimators=100))]) X_enc = OneHotEncoder().fit(X)# 在分割样本之前编码 X X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) # 构建模型模型 = pipe.fit(X_train, y_train) # 显示结果 print("Hold-out AUC score: %.3f" %roc_auc_score(model.predict_proba(X_test),y_test)).抱歉,这是我的第一篇文章,我希望我会学习如何正确发布代码
          • 这样做会损害训练/测试集的整体理念。测试集应该是一个“真实世界”场景,您不知道新值是什么。因此,当它遇到新类别时,您应该为编码合并一个边缘情况。您无法“预见未来”并在看到它们之前就知道存在哪些类别。我认为这是一个典型的数据泄露错误。
          • 是的,我最近才知道这一点,除非您在列中有预定义的类别,否则您不应该对它们进行热编码
          【解决方案5】:

          我迟到了,但我登陆了这个页面,所以我想我还是会回复的。

          您在评论中说过:“对于给定的测试/训练拆分,糖尿病数据集的许多特征中的值太多,无法反映所有值

          当测试集包含训练期间未见的数据时,编码器会发生此错误。

          【讨论】:

          • 考虑到他还没有运行他的测试数据,我认为这不是问题。这是拟合阶段的问题(我目前也有同样的问题)。
          • 看最后一行:print("Hold-out AUC score: %.3f" %roc_auc_score(model.predict_proba(X_test),y_test))
          • 哦,你是对的@kevh ...我的错误。鬼鬼祟祟的。
          【解决方案6】:

          我在使用“OneHoteEncoder()”的ColumnTransformer() 操作期间遇到了同样的错误,我怀疑这是因为编码器需要将二维数组输入到编码器中。

          您可以尝试.apply(lambda x: [x]) 或与您的序数值类似的函数来增加它们的条件。

          【讨论】:

            【解决方案7】:

            我不认为 OrdinalEncoder 在这种情况下是正确的选择。糖尿病数据集由连续特征组成,而不是分类特征。如OrdinalEncoder 的文档中所述:

            这个转换器的输入应该是一个类似数组的整数或字符串,表示分类(离散)特征所采用的值。

            话虽如此,但没有来自回溯或您的设置的额外输出,我无法明确说明为什么您会收到您所做的错误。我能够使用load_diabetes 函数加载的数据成功拆分并执行上述代码。我的猜测是,在您的情况下,您确实以某种方式错过了将编码器与“17.0”类别匹配,但我再次不建议在这种情况下使用分类编码器。

            【讨论】:

            • 非常感谢您的周到,我相信是正确的,回复。我认为对于给定的测试/训练拆分,糖尿病数据集的许多特征中的值太多,无法反映所有值。就您而言,连续分布通常具有此特征-因此 OrdinalEncoder 在这里不是明智的选择。这在很多方面对我来说都是一次学习经历。例如,我在 DataCamp 上花了很多时间,我认为当某些东西不能正常工作时,是因为我编码错误!现在我看得很清楚,情况并非总是如此。
            猜你喜欢
            • 2020-05-28
            • 2021-04-21
            • 2018-01-02
            • 2021-05-11
            • 2020-09-08
            • 2017-07-31
            • 2018-12-16
            • 2021-03-11
            • 2019-07-03
            相关资源
            最近更新 更多