2017-04-19 43 views
6

Próbuję zrobić samouczek dotyczący Pipeline dla studentów, ale blokuję. Nie jestem ekspertem, ale staram się poprawić. Więc dziękuję za wyrozumiałość. W rzeczywistości, staram się w rurociągu, aby wykonać kilka kroków w przygotowaniu dataframe dla klasyfikatora:Używanie wielu niestandardowych klas za pomocą sklearn Pipeline (Python)

  • Krok 1: opis dataframe
  • Krok 2: Wypełnij NaN Wartości
  • Etap 3: Przekształcenie kategoryczne wartości w liczbach

Oto mój kod:

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 

Jeśli wykonam krok 1 i 2 lub krok 1 i 3 to działa, ale jeśli wykonam krok 1, 2 i 3 w tym samym czasie. Mam ten błąd:

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

Prawdopodobnie niektórzy z nich None: 'X' lub' y'. Pełny stos proszę. – sergzach

Odpowiedz

3

Ten błąd pojawia się, ponieważ w rurociągu wyjście pierwszego estymatora idzie do drugiego, to wyjście z drugiego estymatora jedzie do trzeciego i tak dalej ...

Z documentation of Pipeline:

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

Więc dla rurociągu, etapy realizacji są następujące:

  1. Descr_df.fit (X) -> nic nie robi i zwraca self
  2. newX = Descr_df.transform (X) -> powinien zwrócić wartość do przypisania do newX, która powinna zostać przekazana do następnego estymatora, ale twoja definicja nie zwraca niczego (tylko odbitki). Więc Brak jest zwracany domyślnie
  3. Fillna.fit (newX) -> nic nie robi i zwraca siebie
  4. Fillna.transform (newX) -> Wywołuje newX.columns. Ale newX = Brak z kroku 2. Stąd błąd.

Rozwiązanie: Zmiana metody transform Descr_df zwrócić dataframe jak to jest:

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 

Sugestia: Make Your klasy dziedziczą z Base prognozy i zajęcia transformatorowe w scikit aby potwierdzić dobra praktyka.

tj zmienić class Descr_df(object) do class Descr_df(BaseEstimator, TransformerMixin), Fillna(object) do Fillna(BaseEstimator, TransformerMixin) i tak dalej.

Zobacz przykład więcej szczegółów na temat niestandardowych klas w potoku:

+0

Popatrzę i dam ci znać. Twoja odpowiedź wydaje się bardzo interesująca i pomocna. Dziękuję! –

+0

@JeremieGuez Wypróbuj rozwiązanie i jeśli to działa, rozważ zaakceptowanie tej odpowiedzi. –

+0

Wygląda dobrze !! Dzięki –