2016-12-16 3 views
0

Ich versuche die FeatureUnion-Funktionalität von scikit-learn Pipelines in einem Projekt zu verwenden, in dem sich die Daten in einer Datenbank befinden. Ich habe einige grundsätzliche Probleme damit, zu strukturieren, was ich mache.Sci-Kit Learn FeatureUnion mit unterschiedlicher Anzahl von Zeilen

Ich erstelle zwei Features aus zwei verschiedenen Tabellen in der Datenbank. Ich habe eine Methode fetch_x1, fetch_x2, um die Daten von Interesse aus den Datenbanktabellen als Pandas DataFrames zu erhalten. Ich packe die zwei DataFrames in ein Dictionary of Dataframe. In jedem Transformator entpacke ich den interessierenden Datenrahmen und arbeite daran. Ich folge dem Muster dieses post.

Mein Code ist unten:

class Feature1Extractor(TransformerMixin): 

    def transform(self, dictionary_of_dataframes): 
     df = dictionary_of_dataframes['feature1_raw_data'] 
     x = df.groupby('user_id').count()['x1'] 
     return df 

class Feature2Extractor(TransformerMixin): 

    def transform(self, dictionary_of_dataframes): 
     df = dictionary_of_dataframes['feature2'] 
     x = df.groupby('user_id').sum()['x2'] 
     return x 

pipeline = Pipeline([ 
    ('union', FeatureUnion(
     transformer_list=[ 
      ('feature1', Feature1Extractor()), 
      ('feature2', Feature2Extractor())])), 
    ('null', None) 
]) 

pipeline.transform(dictionary_of_dataframes) 

ich in ein anderes grundlegen Problem renne - nach der Transformation die beiden Feature-Matrizen, die aus jeder Pipeline kommen eine unterschiedliche Anzahl von Zeilen. Folglich wird die einfache hstack am Ende FeatureUnion wie so versagt:

ValueError: all the input array dimensions except for the concatenation axis must match exactly 

Dies ist von grundlegender Bedeutung für die Daten, die ich habe. Es gibt eine Reihe von user_ids, die nicht in der feature1-Tabelle vorhanden sind, ebenso gibt es eine Anzahl von user_ids, die in der feature2-Tabelle nicht vorhanden sind. Dies ist für die Daten von grundlegender Bedeutung - wenn ein Benutzer keine Daten in der Tabelle feature1 hat, hat er diese Funktion nie in der App verwendet, z. keine Daten = keine Verbindung mit dieser Funktion. Um das Beispiel explizit zu machen, hier ist ein Beispiel der beiden df der, die jedem Transformator übergeben werden:

df (für feature1)

user_id, x1, timestamp 
1, 'click', 1/1/2016 
1, 'click', 1/2/2016 
2, 'click', 1/2/2016 

df (für feature2)

user_id, x2, timestamp 
2, 12.3, 1/2/2016 
3, 14,5, 1/4/2016 

Hinweis Wie der DataFrame für Feature1 nicht Benutzer 3 und der DataFrame für Feature2 nicht über Benutzer 1 verfügt. Wenn ich dies ohne Pipelines getan hätte, würde ich einen Outer Join und dann Fillna (0) auf dem resultierenden zusammengeführten Datenframe, z

merged_df = pd.merge(df1, df1, how='outer', left_on=['user_id'], right_on=['user_id']) 
final_df = merged_df.fillna(0) 

Aber es scheint keine Möglichkeit, dies mit der FeatureUnion Methode zu tun. Und ich kann nicht an eine saubere Umgehung im Pipeline-Framework denken ... Ich muss separate Pipelines ausführen, jeden von ihnen transformieren, den äußeren Join ausführen und Pandas füllen, und dann die fertige Feature-Matrix in einen Downstream verwandeln Modellierungspipeline? Gibt es einen besseren Weg? Ich suche die Gemeinschaft um Hilfe.

HINWEIS: Ich kenne die user_ids NICHT vorher. Ich frage die Tabellen basierend auf dem Zeitstempel Bereich ... nicht Benutzer-ID. Die Abfrage selbst sagt mir, welche Benutzer ich im Training (oder Test) haben sollte.

+0

Es ist schwer zu folgen, was Sie fragen. Geben Sie uns einige Beispieldaten oder eine kleine Eingabe/Ausgabe, damit wir das Problem, das Sie haben, überprüfen können. Ich bin nicht sicher, warum Sie nicht einen Datensatz füllen können, um die gleiche Anzahl von Zeilen wie die andere (füllen Sie es mit 'None' s oder etwas), und dann tun Sie die FeatureUnion – mwm314

+0

Sie haben Recht, ich werde bearbeiten passenderweise ... ich kenne nicht alle user_ids vorher aber --- deshalb habe ich einen Outer Join gemacht ... ich will das nicht getrennt verfolgen. Ich werde das bearbeiten, um mit einem guten Beispiel fokussierter zu sein. –

Antwort

0

Warum, werden Sie nicht Ihre eigene, Pandas basierte Union bauen? So etwas ... (ich es nicht getestet haben, sehen nur die Idee)

class DataMerging(BaseEstimator): 

    def __init__(self): 
     return self 

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

    def transform(self, dfs): 
     df1, df2 = dfs 
     merged_df = pd.merge(df1, df2, how='outer', left_on=['user_id'], right_on=['user_id']).fillna(0) 
     return merged_df.values #(return shape (n_features, n_samples)) 


pipeline = Pipeline([ 
    ('union', DataMerging, 
    ('other thing', ...) 
])   

pipeline.fit(df1, df2) 
+0

Ok das ist interessant - aber ich verstehe nicht ganz, wie das in die Pipeline Beschreibung passt ... Soll ich auch FeatureUnion subclass? –

Verwandte Themen