Mientras preprocesaba las etiquetas para una tarea de clasificación de aprendizaje automático, necesito codificar en caliente las etiquetas que toman valores de cadena. Sucede que OneHotEncoder de sklearn.preprocessing o to_categorical de kera.np_utils requieren entradas int . Esto significa que debo preceder al codificador activo con un LabelEncoder . Lo he hecho a mano con una clase personalizada:
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) Confío en que debe haber una forma de hacerlo dentro de la API de sklearn usando un sklearn.pipeline , pero cuando se usa:
LabelOneHotEncoder = Pipeline( [ ("le",LabelEncoder), ("ohe", OneHotEncoder)]) Recibo el error ValueError: bad input shape () del OneHotEncoder . Mi conjetura es que la salida de LabelEncoder necesita ser remodelada, agregando un segundo eje trivial. Sin embargo, no estoy seguro de cómo agregar esta función.
Es extraño que no jueguen bien juntos... Estoy sorprendido. Extendería la clase para devolver los datos remodelados como sugirió.
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)Entonces usar la canalización debería funcionar.
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
Desde scikit-learn 0.20, OneHotEncoder acepta cadenas, por lo que ya no necesita un LabelEncoder antes. Y simplemente puede usarlo en una canalización.
He usado una clase personalizada para envolver mi función de codificador de etiquetas y devuelve el conjunto de datos actualizado completo.
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)[Lo he implementado, puedes ver mi enlace de github] [1]: https://github.com/Ayushmina-20/sklearn_pipeline