【问题标题】:scikit-learn: How to compose LabelEncoder and OneHotEncoder with a pipeline?scikit-learn:如何使用管道组合 LabelEncoder 和 OneHotEncoder?
【发布时间】:2018-08-02 09:42:20
【问题描述】:

在为机器学习分类任务预处理标签时,我需要对采用字符串值的标签进行热编码。碰巧来自sklearn.preprocessingOneHotEncoder 或来自kera.np_utilsto_categorical 需要int 输入。这意味着我需要在一个热编码器之前加上LabelEncoder。我用自定义类手工完成了它:

class LabelOneHotEncoder():
    def __init__(self):
        self.ohe = OneHotEncoder()
        self.le = LabelEncoder()
    def fit_transform(self, x):
        features = self.le.fit_transform( x)
        return self.ohe.fit_transform( features.reshape(-1,1))
    def transform( self, x):
        return self.ohe.transform( self.la.transform( x.reshape(-1,1)))
    def inverse_tranform( self, x):
        return self.le.inverse_transform( self.ohe.inverse_tranform( x))
    def inverse_labels( self, x):
        return self.le.inverse_transform( x)

我相信在 sklearn API 中必须有一种使用sklearn.pipeline 的方法,但是在使用时:

LabelOneHotEncoder = Pipeline( [ ("le",LabelEncoder), ("ohe", OneHotEncoder)])

我从OneHotEncoder 收到错误ValueError: bad input shape ()。我的猜测是LabelEncoder 的输出需要通过添加一个微不足道的第二个轴来重塑。我不确定如何添加此功能。

【问题讨论】:

    标签: python scikit-learn one-hot-encoding


    【解决方案1】:

    这不是针对提出的问题,而是仅将 LabelEncoder 应用于所有列,您可以使用以下格式

    df_non_numeric =df.select_dtypes(['object'])
    non_numeric_cols = df_non_numeric.columns.values
    from sklearn.preprocessing import LabelEncoder
    for col in non_numeric_cols:
        df[col] = LabelEncoder().fit_transform(df[col].values)
    df.head()
    

    【讨论】:

      【解决方案2】:

      我使用了一个自定义类来包装我的标签编码器函数,它会返回整个更新的数据集。

       class CustomLabelEncode(BaseEstimator, TransformerMixin):
        def fit(self, X, y=None):
         return self
        def transform(self, X ,y=None):
          le=LabelEncoder()
          for i in X[cat_cols]:
          X[i]=le.fit_transform(X[i])
          return X 
      cat_cols=['Family','Education','Securities Account','CDAccount','Online','CreditCard']
      le_ct=make_column_transformer((CustomLabelEncode(),cat_cols),remainder='passthrough') 
      pd.DataFrame(ct3.fit_transform(X)) #This will show you your changes
      Final_pipeline=make_pipeline(le_ct)
      

      [我已经实现了你可以看我的github链接] [1]:https://github.com/Ayushmina-20/sklearn_pipeline

      【讨论】:

        【解决方案3】:

        从 scikit-learn 0.20 开始,OneHotEncoder 接受字符串,因此您不再需要 LabelEncoder 之前。您可以在管道中使用它。

        【讨论】:

        • 感谢您的更新,更新后可能会使用此信息。
        【解决方案4】:

        奇怪的是他们不能很好地一起玩......我很惊讶。我会扩展该类以按照您的建议返回重塑后的数据。

        class ModifiedLabelEncoder(LabelEncoder):
        
            def fit_transform(self, y, *args, **kwargs):
                return super().fit_transform(y).reshape(-1, 1)
        
            def transform(self, y, *args, **kwargs):
                return super().transform(y).reshape(-1, 1)
        

        然后使用管道应该可以工作。

        pipe = Pipeline([("le", ModifiedLabelEncoder()), ("ohe", OneHotEncoder())])
        pipe.fit_transform(['dog', 'cat', 'dog'])
        

        https://github.com/scikit-learn/scikit-learn/blob/a24c8b46/sklearn/preprocessing/label.py#L39

        【讨论】:

        • 感谢您的意见。我首先接受了您的答案,因为它看起来很明显它会起作用,但是在实施它时我遇到了错误。首先,管道构造函数接受类而不是实例,因此它必须是ModifiedLabelEncoder 而不是ModifiedLabelEncoder()。其次,reshape 参数应该是(-1,1)。之后,ModifiedLabelEncoder 将自行工作,但不在管道中。我在拨打fit_transform 时收到TypeError: super(type, obj): obj must be an instance or subtype of type
        • @Learningisamess 错误。管道接受实例,而不是类。
        • @Learningisamess 我已经更正了上面的代码,请立即检查。如果仍然有错误,请在问题中发布完整的错误堆栈跟踪。
        • @VivekKumar:确实我在关于管道的实例与类上错了。将很快检查新代码并报告。
        • 添加对额外参数的支持后,代码确实可以工作 (*args, **kwargs)。采纳答案,谢谢!
        猜你喜欢
        • 2018-11-01
        • 2021-11-01
        • 2015-08-14
        • 2020-10-05
        • 2020-01-25
        • 2016-12-28
        • 2017-01-22
        • 2021-03-17
        • 2016-11-24
        相关资源
        最近更新 更多