【问题标题】:Why should LabelEncoder from sklearn be used only for the target variable?为什么 sklearn 中的 LabelEncoder 只能用于目标变量?
【发布时间】:2020-11-03 14:34:06
【问题描述】:

我试图创建一个带有 LabelEncoder 的管道来转换分类值。

cat_variable = Pipeline(steps = [
    ('imputer',SimpleImputer(strategy = 'most_frequent')),
    ('lencoder',LabelEncoder())
])
                        
num_variable = SimpleImputer(strategy = 'mean')

preprocess = ColumnTransformer (transformers = [
    ('categorical',cat_variable,cat_columns),
    ('numerical',num_variable,num_columns)
])

odel = RandomForestRegressor(n_estimators = 100, random_state = 0)

final_pipe = Pipeline(steps = [
    ('preprocessor',preprocess),
    ('model',model)
])

scores = -1 * cross_val_score(final_pipe,X_train,y,cv = 5,scoring = 'neg_mean_absolute_error')

但这会引发 TypeError:


TypeError: fit_transform() takes 2 positional arguments but 3 were given

进一步参考,我发现像 LabelEncoders 这样的转换器不应该与特征一起使用,而应该只用于预测目标。

From Documentation:

sklearn.preprocessing.LabelEncoder 类

使用 0 到 n_classes-1 之间的值对目标标签进行编码。

这个转换器应该用于编码目标值,即 y,而不是输入 X。

我的问题是,为什么我们不能在特征变量上使用 LabelEncoder,还有其他具有这种情况的转换器吗?

【问题讨论】:

  • 序数编码对于一个特性来说不是一个好的选择,因为你给它一个人为的隐含排序。你的分类的基数是什么?如果它不是太高,一种热编码是最常见的选择,尽管它对于基于树的模型不是很好,尤其是在基数很高的时候。这是一整套替代方案:contrib.scikit-learn.org/category_encoders

标签: python machine-learning scikit-learn label-encoding


【解决方案1】:

LabelEncoder,按照设计,必须用于目标变量而不是特征变量。这意味着LabelEncoder 类的.fit().transform().fit_transform() 方法的签名与用于特征的转换器之一不同。

fit(y) 与 fit(X[,y]) |变换(y)与变换(X)| fit_transform(y) 与 fit_transform(X[,y]) 或类似

fit(self, y) vs fit(self, X, y=None) |变换(自我,y)与变换(自我,X)| fit_transform(self, y) vs fit_transform(self, X, y=None)

分别用于 LabelEncoder-like 转换器(即应用于目标的转换器)和应用于特征的转换器。

同样的设计也适用于LabelBinarizerMultiLabelBinarizer。我建议阅读用户指南的Transforming the prediction target (y) 段落。

也就是说,这里有几个注意事项来描述当您尝试在 PipelineColumnTransformer 中使用 LabelEncoder 时会发生什么:

  • Pipelines 和ColumnTransformers 是关于转换和拟合数据,而不是目标。他们以某种方式“假设”目标已经处于估算器可以使用的状态。

  • 在这个github issue 和其中引用的那些中,您可以关注关于使管道也可以转换目标的长期讨论。这也在this sklearn FAQ 中进行了总结。

  • 您获得TypeError: fit_transform() takes 2 positional arguments but 3 were given 的具体原因如下(这里从ColumnTransformer 的角度来看):在ColumnTransformer 实例上调用.fit_transform().fit() 时,方法@ 987654329@在Xy上依次调用,触发了._fit_transform_one()的调用,出现错误。事实上,它在transformer 上调用.fit_transform()(你的LabelEncoder);这里不同的方法签名开始发挥作用:

     with _print_elapsed_time(message_clsname, message):
         if hasattr(transformer, "fit_transform"):
             res = transformer.fit_transform(X, y, **fit_params)
         else:
             res = transformer.fit(X, y, **fit_params).transform(X)
    

    确实,.fit_transform()(self, X, y) 上被调用([...] 3 个参数被给出),而只期望 (self, y) ([...] 需要 2 个位置参数)。按照Pipeline 类中的代码,可以看出同样的情况。

  • 如前所述,适用于特征变量(因此适用于管道和列转换器)的标签编码的替代方法是OrdinalEncoder(从版本 0.20 开始)。在这个提议中,我建议阅读Difference between OrdinalEncoder and LabelEncoder

【讨论】:

    【解决方案2】:

    您可以将 OrdinalEncoder 用于分类变量

    【讨论】:

    • 嗨!通常希望您提供一些关于如何解决问题的更详细的解释,并且通常还包含一些代码以更好地帮助提出问题的人。你能用这种方式增强你的答案吗?
    【解决方案3】:

    LabelEncoder 可用于规范化标签或转换非数字标签。对于输入分类,您应该使用OneHotEncoder

    区别:

    le = preprocessing.LabelEncoder()
    le.fit_transform([1, 2, 2, 6])
    array([0, 0, 1, 2])
    
    enc = OneHotEncoder(handle_unknown='ignore')
    enc.fit_transform([[1], [2], [2], [6]]).toarray()
    array([[1., 0., 0.],
           [0., 1., 0.],
           [0., 1., 0.],
           [0., 0., 1.]])
    

    【讨论】:

      猜你喜欢
      • 2017-08-24
      • 2019-03-15
      • 2019-02-16
      • 2020-09-11
      • 2016-11-19
      • 2016-11-20
      • 2017-06-06
      • 1970-01-01
      • 2023-02-06
      相关资源
      最近更新 更多