2017-04-19 1 views
6

J'essaie de faire un tutoriel sur Pipeline pour les étudiants mais je bloque. Je ne suis pas un expert mais j'essaie de m'améliorer. Donc merci pour votre indulgence. En fait, j'essaie dans un pipeline pour exécuter plusieurs étapes dans la préparation d'un dataframe pour un classificateur:Utilisation de plusieurs classes personnalisées avec Pipeline sklearn (Python)

  • Étape 1: Description de la dataframe
  • Étape 2: Remplissez NaN Valeurs
  • Étape 3: Transformer Les valeurs catégorielles en nombres

Voici mon code:

class Descr_df(object): 

    def transform (self, X): 
     print ("Structure of the data: \n {}".format(X.head(5))) 
     print ("Features names: \n {}".format(X.columns)) 
     print ("Target: \n {}".format(X.columns[0])) 
     print ("Shape of the data: \n {}".format(X.shape)) 

    def fit(self, X, y=None): 
     return self 

class Fillna(object): 

    def transform(self, X): 
     non_numerics_columns = X.columns.difference(X._get_numeric_data().columns) 
     for column in X.columns: 
      if column in non_numerics_columns: 
       X[column] = X[column].fillna(df[column].value_counts().idxmax()) 
      else: 
       X[column] = X[column].fillna(X[column].mean())    
     return X 

    def fit(self, X,y=None): 
     return self 

class Categorical_to_numerical(object): 

    def transform(self, X): 
     non_numerics_columns = X.columns.difference(X._get_numeric_data().columns) 
     le = LabelEncoder() 
     for column in non_numerics_columns: 
      X[column] = X[column].fillna(X[column].value_counts().idxmax()) 
      le.fit(X[column]) 
      X[column] = le.transform(X[column]).astype(int) 
     return X 

    def fit(self, X, y=None): 
     return self 

Si j'exécute les étapes 1 et 2 ou 1 et 3 cela fonctionne mais si j'exécute les étapes 1, 2 et 3 en même temps. J'ai cette erreur:

pipeline = Pipeline([('df_intropesction', Descr_df()), ('fillna',Fillna()), ('Categorical_to_numerical', Categorical_to_numerical())]) 
pipeline.fit(X, y) 
AttributeError: 'NoneType' object has no attribute 'columns' 
+0

probablement certains d'entre eux Aucun: '' X' ou y'. Pile complète s'il vous plaît. – sergzach

Répondre

3

Cette erreur provient du fait que dans le pipeline de la sortie de premier estimateur va à la seconde, puis la sortie de second estimateur va à la troisième et ainsi de suite ...

De la documentation of Pipeline:

Fit all the transforms one after the other and transform the data, then fit the transformed data using the final estimator.

donc, pour votre pipeline, les étapes d'exécution suivent:

  1. Descr_df.fit (X) -> ne fait rien et renvoie
  2. newX = Descr_df.transform (X) -> devrait retourner une valeur à affecter à newX qui devrait être transmise à l'estimateur suivant, mais votre définition ne retourne rien (imprime seulement). Donc Aucun n'est retourné implicitement
  3. Fillna.fit (newX) -> ne fait rien et retourne le
  4. Fillna.transform (newX) -> Appelle newX.columns. Mais newX = None from step2. D'où l'erreur.

Solution: Changer la méthode de transformation de Descr_df pour retourner le dataframe comme il est:

def transform (self, X): 
    print ("Structure of the data: \n {}".format(X.head(5))) 
    print ("Features names: \n {}".format(X.columns)) 
    print ("Target: \n {}".format(X.columns[0])) 
    print ("Shape of the data: \n {}".format(X.shape)) 
    return X 

Suggestion: Faites vos classes héritent de base estimateur et les classes de transformateur scikit pour confirmer à la bonne pratique.

e.e change le class Descr_df(object) en class Descr_df(BaseEstimator, TransformerMixin), Fillna(object) en Fillna(BaseEstimator, TransformerMixin) et ainsi de suite.

Voir cet exemple pour plus de détails sur les classes personnalisées dans Pipeline:

+0

Je vais jeter un coup d'oeil et vous le faire savoir. Votre réponse semble très intéressante et utile. Merci! –

+0

@JeremieGuez Essayez la solution et si cela fonctionne pour vous, s'il vous plaît envisager d'accepter cette réponse –

+0

Cela semble ok !! Merci –