0

Ich möchte eine binäre Klassifizierung basierend auf verschiedenen Features, die ich habe (sowohl Text als auch numerisch). Trainingsdaten sind die Form des Pandas Datenrahmens. Meine Pipeline sieht ungefähr so ​​aus:Sklearn: FeatureUnion von heterogenen Features gibt inkompatible Zeilenbemaßungen Fehler mit Klassifizierer in der Pipeline

final_pipeline = Pipeline([('union', FeatureUnion(
       transformer_list=[('body_trans', Pipeline([('selector', ItemSelector(key='body')), 
                  ('count_vect', CountVectorizer())])), 
            ('body_trans2', Pipeline([('selector', ItemSelector(key='body2')), 
                  ('count_vect', TfidfVectorizer())])), 
           ('length_trans', Pipeline([('selector', ItemSelector(key='length')), 
                  ('min_max_scaler', MinMaxScaler())]))], 
       transformer_weights={'body_trans': 1.0,'body_trans2': 1.0,'length_trans': 1.0})), 
          ('svc', SVC())]) 

ItemSelector wie folgt aussieht:

class ItemSelector(BaseEstimator, TransformerMixin): 
    def __init__(self, key): 
     self.key = key 

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

    def transform(self, data_frame): 
     return data_frame[[self.key]] 

Nun, wenn ich final_pipeline.fit(X_train, y_train) versuchen, es mir die Ausnahme ValueError: blocks[0,:] has incompatible row dimensions gibt.

X_train, X_test, y_train, y_test = train_test_split(train_set, target_set) 

ist, wie ich meine Trainingsdaten bekomme. train_set ist ein Datenframe mit den Feldern body, body2, length usw. target_set ist ein Datenframe mit nur einem Feld namens label, das ist meine eigentliche Bezeichnung zu klassifizieren.

Edit:

Ich glaube, meine Eingabedaten an die Pipeline nicht im richtigen Format ist.

train_set sind meine Trainingsdaten mit den Merkmalen, Beispiel:

body   length body2 
0 blah-blah  193  blah-blah-2 
1 blah-blah-blah 153  blah-blah-blah-2 

und die target_set, die der Datenrahmen mit dem Klassifizierungsetikett ist

label 
0 True 
1 False 

Wenn es eine Anleitung auf Eingabeformat für Die Anpassungsparameter einer Pipeline unter Verwendung von DataFrames, bitte geben Sie mir einen Link! Ich kann keine ordnungsgemäße Dokumentation finden, wie Sie DataFrames als Eingabe für Pipelines laden, während Sie mehrere Spalten als separate Features verwenden.

Jede Hilfe wird geschätzt!

+0

Bitte senden Sie einige Beispieldaten und einfach zu kopieren und Code zusammen mit der vollständigen Stack-Ablaufverfolgung von Fehler ausführen. –

+0

haben einige Datenproben hinzugefügt! Danke – void

+0

Das Problem ist in Ihrem ItemSelector. Es gibt einen 2-d Datenrahmen aus, aber CountVectorizer und TfidfVectorizer benötigen ein 1-d Array von Strings. –

Antwort

2

Das Problem liegt in Ihrem ItemSelector. Es gibt einen 2-d Datenrahmen aus, aber CountVectorizer und TfidfVectorizer benötigen ein 1-d Array von Strings.

-Code die Ausgabe von ItemSelector zeigen: -

import numpy as np 
from pandas import DataFrame 
df = DataFrame(columns = ['body','length','body2'],data=np.array([['blah-blah', 193, 'blah-blah-2'],['blah-blah-2', 153, 'blah-blah-blah-2'] ])) 

body_selector = ItemSelector(key='body') 
df_body = body_selector.fit_transform(df) 

df_body.shape 
# (2,1) 

Sie können eine andere Klasse definieren, welche die Daten ausfransen können in der richtigen Form zum nächsten Schritt präsentiert werden.

Fügen Sie diese Klasse, um Ihren Code wie folgt aus:

class Converter(BaseEstimator, TransformerMixin): 
    def fit(self, x, y=None): 
     return self 

    def transform(self, data_frame): 
     return data_frame.values.ravel() 

Dann definieren Sie Ihre Pipeline wie folgt aus:

final_pipeline = Pipeline([('union', FeatureUnion(
       transformer_list=[('body_trans', Pipeline([('selector', ItemSelector(key='body')), 
                  ('converter', Converter()), 
                  ('count_vect', CountVectorizer())])), 
            ('body_trans2', Pipeline([('selector', ItemSelector(key='body2')), 
                  ('converter', Converter()), 
                  ('count_vect', TfidfVectorizer())])), 
           ('length_trans', Pipeline([('selector', ItemSelector(key='length')), 
                  ('min_max_scaler', MinMaxScaler())]))], 
       transformer_weights={'body_trans': 1.0,'body_trans2': 1.0,'length_trans': 1.0})), 
          ('svc', SVC())]) 

keine Notwendigkeit, dies zu dritten Teil zu schreiben, weil MinMaxScalar erfordert 2-D-Eingang Daten.

Fühlen Sie sich frei zu fragen, ob irgendein Problem.

+0

Scheint so, als wäre das das Problem! Könnten Sie mir auch die Schritte erklären, die Sie unternommen haben, um dieses Problem zu beheben? Ich finde es schwierig, solche Probleme in Python zu debuggen. Vielen Dank! – void

+1

@void Eine Sache, die ich aus früheren Erfahrungen wusste, ist, dass dieser Fehler von der unterschiedlichen Form der Features in FeatureUnion-Schritten herrührte. Also habe ich Ihre Schritte abgebrochen und die Ausgabeform jeder inneren Pipeline in der FeatureUnion gedruckt. Dort fand ich heraus, dass die ersten beiden Pipelines [1,1] und der letzte [2,1] für die gegebenen Demo-Daten ausgegeben wurde. Dann brach die ersten beiden Pipelines weiter, um die Ein- und Ausgangsform zu überprüfen. Und ich habe das Problem gefunden. –

Verwandte Themen