99 votes

fit_transform () prend 2 arguments de position mais 3 ont été donnés avec LabelBinarizer

Je suis totalement nouveau pour l'Apprentissage de la Machine et j'ai travaillé avec l'apprentissage non supervisé technique.

L'Image montre mes Données-échantillon(Après Nettoyage) Capture d'écran : Les Données De L'Échantillon

J'ai deux Pipline conçu pour Nettoyer les Données:

num_attribs = list(housing_num)
cat_attribs = ["ocean_proximity"]

print(type(num_attribs))

num_pipeline = Pipeline([
    ('selector', DataFrameSelector(num_attribs)),
    ('imputer', Imputer(strategy="median")),
    ('attribs_adder', CombinedAttributesAdder()),
    ('std_scaler', StandardScaler()),
])

cat_pipeline = Pipeline([
    ('selector', DataFrameSelector(cat_attribs)),
    ('label_binarizer', LabelBinarizer())
])

Ensuite, j'ai fait l'union de deux pipelines et le code pour le même est indiqué ci-dessous :

from sklearn.pipeline import FeatureUnion

full_pipeline = FeatureUnion(transformer_list=[
        ("num_pipeline", num_pipeline),
        ("cat_pipeline", cat_pipeline),
    ])

Maintenant, je suis en train de faire fit_transform sur les Données Mais Sa Me montrant l'Erreur.

Code pour la Transformation:

housing_prepared = full_pipeline.fit_transform(housing)
housing_prepared

Message d'erreur: fit_transform() prend 2 arguments de position, mais 3 ont été donnés

79voto

Zaid E. Points 743

Le Problème:

Le pipeline est en supposant que LabelBinarizer de l' fit_transform méthode est définie pour prendre les trois arguments de position:

def fit_transform(self, x, y)
    ...rest of the code

s'il est défini pour ne prendre que deux:

def fit_transform(self, x):
    ...rest of the code

Solution Possible:

Cela peut être résolu en faisant une coutume transformateur qui peut gérer 3 arguments de position:

  1. Importer et de faire une nouvelle classe:

    from sklearn.base import TransformerMixin #gives fit_transform method for free
    class MyLabelBinarizer(TransformerMixin):
        def __init__(self, *args, **kwargs):
            self.encoder = LabelBinarizer(*args, **kwargs)
        def fit(self, x, y=0):
            self.encoder.fit(x)
            return self
        def transform(self, x, y=0):
            return self.encoder.transform(x)
    
  2. Gardez votre code, la même sauf qu'au lieu d'utiliser LabelBinarizer(), utilisez la classe que nous avons créé : MyLabelBinarizer().


Remarque: Si vous souhaitez accéder à LabelBinarizer Attributs (par exemple, classes_), ajoutez la ligne suivante à l' fit méthode:

    self.classes_, self.y_type_, self.sparse_input_ = self.encoder.classes_, self.encoder.y_type_, self.encoder.sparse_input_

68voto

Steven Oxley Points 2682

Je crois que votre exemple est le livre des Mains Sur l'Apprentissage de la Machine avec Scikit-Learn & TensorFlow. Malheureusement, je suis tombé sur ce problème, ainsi. Un récent changement en scikit-learn (0.19.0) ont changé de LabelBinarizers' fit_transform méthode. Malheureusement, LabelBinarizer n'a jamais été destiné à travailler la façon dont cet exemple utilise. Vous pouvez voir des informations sur le changement ici et ici.

Jusqu'à ce qu'ils viennent avec une solution pour cela, vous pouvez installer la version précédente (0.18.0) comme suit:

$ pip install scikit-learn==0.18.0

Après l'exécution, votre code doit s'exécuter sans problème.

Dans l'avenir, il semble que la bonne solution peut être d'utiliser un CategoricalEncoder classe ou quelque chose de semblable. Ils ont été d'essayer de résoudre ce problème depuis des années apparemment. Vous pouvez voir la nouvelle classe ici et la poursuite de la discussion du problème ici.

14voto

Norman Yan Points 66

Je pense que vous allez à travers les exemples du livre: les Mains sur l'Apprentissage de la Machine avec Scikit Learn et Tensorflow. J'ai rencontré le même problème lors du passage à travers l'exemple dans le Chapitre 2.

Comme mentionné par d'autres personnes, le problème est de le faire avec sklearn de LabelBinarizer. Il prend moins d'arguments dans son fit_transform méthode par rapport à d'autres transformateurs dans le pipeline. (uniquement y lorsque d'autres transformateurs normalement de prendre à la fois X et y, voir ici pour les détails). C'est pourquoi, lorsque nous courons pipeline.fit_transform, nous avons nourri plus des arguments dans ce transformateur que nécessaire.

Une solution facile, j'ai utilisé est de l'utiliser juste OneHotEncoder et définir le "sparse" à False pour assurer la sortie est un tableau numpy même que le num_pipeline de sortie. (de cette façon, vous n'avez pas besoin de code de votre propre encodeur)

l'original de votre cat_pipeline:

cat_pipeline = Pipeline([
('selector', DataFrameSelector(cat_attribs)),
('label_binarizer', LabelBinarizer())
])

vous pouvez simplement modifier cette partie de:

cat_pipeline = Pipeline([
('selector', DataFrameSelector(cat_attribs)),
('one_hot_encoder', OneHotEncoder(sparse=False))
])

Vous pouvez aller à partir d'ici et tout devrait fonctionner.

10voto

shyam padia Points 131

Etant donné que LabelBinarizer ne permet pas plus de 2 arguments de position, vous devez créer votre binariseur personnalisé comme

 class CustomLabelBinarizer(BaseEstimator, TransformerMixin):
    def __init__(self, sparse_output=False):
        self.sparse_output = sparse_output
    def fit(self, X, y=None):
        return self
    def transform(self, X, y=None):
        enc = LabelBinarizer(sparse_output=self.sparse_output)
        return enc.fit_transform(X)

num_attribs = list(housing_num)
cat_attribs = ['ocean_proximity']

num_pipeline = Pipeline([
    ('selector', DataFrameSelector(num_attribs)),
    ('imputer', Imputer(strategy='median')),
    ('attribs_adder', CombinedAttributesAdder()),
    ('std_scalar', StandardScaler())
])

cat_pipeline = Pipeline([
    ('selector', DataFrameSelector(cat_attribs)),
    ('label_binarizer', CustomLabelBinarizer())
])

full_pipeline = FeatureUnion(transformer_list=[
    ('num_pipeline', num_pipeline),
    ('cat_pipeline', cat_pipeline)
])

housing_prepared = full_pipeline.fit_transform(new_housing)
 

7voto

rliu054 Points 71

J'ai rencontré le même problème et ai eu de travail par l'application de la solution de contournement spécifié dans le livre du dépôt Github.

Attention: les versions antérieures du livre utilisé le LabelBinarizer classe à de ce point. Encore une fois, cette information était inexacte: tout comme le LabelEncoder la classe, le LabelBinarizer classe a été conçu pour prétraiter les étiquettes, ne sont pas les entités en entrée. Une meilleure solution est d'utiliser Scikit-Learn à venir CategoricalEncoder classe: il sera bientôt ajouté à Scikit-Learn, et en attendant, vous pouvez utiliser le code ci-dessous (copié à partir de Pull Request #9151).

Pour vous enregistrer certains grepping voici la solution, il suffit de copier et de les exécuter dans une cellule précédente:

# Definition of the CategoricalEncoder class, copied from PR #9151.
# Just run this cell, or copy it to your code, do not try to understand it (yet).

from sklearn.base import BaseEstimator, TransformerMixin
from sklearn.utils import check_array
from sklearn.preprocessing import LabelEncoder
from scipy import sparse

class CategoricalEncoder(BaseEstimator, TransformerMixin):
    def __init__(self, encoding='onehot', categories='auto', dtype=np.float64,
                 handle_unknown='error'):
        self.encoding = encoding
        self.categories = categories
        self.dtype = dtype
        self.handle_unknown = handle_unknown

    def fit(self, X, y=None):
        """Fit the CategoricalEncoder to X.
        Parameters
        ----------
        X : array-like, shape [n_samples, n_feature]
            The data to determine the categories of each feature.
        Returns
        -------
        self
        """

        if self.encoding not in ['onehot', 'onehot-dense', 'ordinal']:
            template = ("encoding should be either 'onehot', 'onehot-dense' "
                        "or 'ordinal', got %s")
            raise ValueError(template % self.handle_unknown)

        if self.handle_unknown not in ['error', 'ignore']:
            template = ("handle_unknown should be either 'error' or "
                        "'ignore', got %s")
            raise ValueError(template % self.handle_unknown)

        if self.encoding == 'ordinal' and self.handle_unknown == 'ignore':
            raise ValueError("handle_unknown='ignore' is not supported for"
                             " encoding='ordinal'")

        X = check_array(X, dtype=np.object, accept_sparse='csc', copy=True)
        n_samples, n_features = X.shape

        self._label_encoders_ = [LabelEncoder() for _ in range(n_features)]

        for i in range(n_features):
            le = self._label_encoders_[i]
            Xi = X[:, i]
            if self.categories == 'auto':
                le.fit(Xi)
            else:
                valid_mask = np.in1d(Xi, self.categories[i])
                if not np.all(valid_mask):
                    if self.handle_unknown == 'error':
                        diff = np.unique(Xi[~valid_mask])
                        msg = ("Found unknown categories {0} in column {1}"
                               " during fit".format(diff, i))
                        raise ValueError(msg)
                le.classes_ = np.array(np.sort(self.categories[i]))

        self.categories_ = [le.classes_ for le in self._label_encoders_]

        return self

    def transform(self, X):
        """Transform X using one-hot encoding.
        Parameters
        ----------
        X : array-like, shape [n_samples, n_features]
            The data to encode.
        Returns
        -------
        X_out : sparse matrix or a 2-d array
            Transformed input.
        """
        X = check_array(X, accept_sparse='csc', dtype=np.object, copy=True)
        n_samples, n_features = X.shape
        X_int = np.zeros_like(X, dtype=np.int)
        X_mask = np.ones_like(X, dtype=np.bool)

        for i in range(n_features):
            valid_mask = np.in1d(X[:, i], self.categories_[i])

            if not np.all(valid_mask):
                if self.handle_unknown == 'error':
                    diff = np.unique(X[~valid_mask, i])
                    msg = ("Found unknown categories {0} in column {1}"
                           " during transform".format(diff, i))
                    raise ValueError(msg)
                else:
                    # Set the problematic rows to an acceptable value and
                    # continue `The rows are marked `X_mask` and will be
                    # removed later.
                    X_mask[:, i] = valid_mask
                    X[:, i][~valid_mask] = self.categories_[i][0]
            X_int[:, i] = self._label_encoders_[i].transform(X[:, i])

        if self.encoding == 'ordinal':
            return X_int.astype(self.dtype, copy=False)

        mask = X_mask.ravel()
        n_values = [cats.shape[0] for cats in self.categories_]
        n_values = np.array([0] + n_values)
        indices = np.cumsum(n_values)

        column_indices = (X_int + indices[:-1]).ravel()[mask]
        row_indices = np.repeat(np.arange(n_samples, dtype=np.int32),
                                n_features)[mask]
        data = np.ones(n_samples * n_features)[mask]

        out = sparse.csc_matrix((data, (row_indices, column_indices)),
                                shape=(n_samples, indices[-1]),
                                dtype=self.dtype).tocsr()
        if self.encoding == 'onehot-dense':
            return out.toarray()
        else:
            return out

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X