2017-12-19 18 views
1

私はこのように単純化することができますDATAFRAMEあります複数のデータフレーム列のパイプラインを作成する方法は?

import pandas as pd 

df = pd.DataFrame([{ 
'title': 'batman', 
'text': 'man bat man bat', 
'url': 'batman.com', 
'label':1}, 
{'title': 'spiderman', 
'text': 'spiderman man spider', 
'url': 'spiderman.com', 
'label':1}, 
{'title': 'doctor evil', 
'text': 'a super evil doctor', 
'url': 'evilempyre.com', 
'label':0},]) 

をそして、私は別の特徴抽出方法試してみたい:異なるnグラムの設定でTFIDF、word2vec、Coutvectorizerを、などしかし、私はさまざまな組み合わせでそれを試してみたいです:TFIDFで変換された 'テキスト'データと、Countvectoriserで 'url'、そしてTFIDFで 'url'などのテキストデータが1つのフィーチャセットに含まれます。最後に、もちろん、私はさまざまな前処理戦略を比較して、最良のものを選択したいと考えています。ここ

と質問は以下のとおりです。

  1. パイプラインなどの標準的なsklearnツールを使用してそのようなことを行う方法はありますか?

  2. 私の考えには常識がありますか?たぶん、欠けているデータフレームの多くの列でテキストデータを扱う方法が良いアイデアですか?

ありがとうございました!

答えて

1

@elphz答えはFeatureUnionFunctionTransformerをどのように使用してこれを達成できるかを示す良いイントロですが、もう少し詳しく説明することができます。

まず、入力データを適切に処理して返すように、FunctionTransformerの関数を定義する必要があるとします。この場合、私はDataFrameを渡したいと思っていますが、ダウンストリームで使用するために適切な形状の配列を取得するようにしてください。したがって、DataFrameだけを渡し、列名でアクセスすることを提案します。同様に:

def text(X): 
    return X.text.values 

def title(X): 
    return X.title.values 

pipe_text = Pipeline([('col_text', FunctionTransformer(text, validate=False))]) 

pipe_title = Pipeline([('col_title', FunctionTransformer(title, validate=False))]) 

ここで、変圧器と分類器のバリエーションをテストします。私は変圧器のリストと分類器のリストを使って、グリッド探索と同様に単純に反復することを提案します。

tfidf = TfidfVectorizer() 
cv = CountVectorizer() 
lr = LogisticRegression() 
rc = RidgeClassifier() 

transformers = [('tfidf', tfidf), ('cv', cv)] 
clfs = [lr, rc] 

best_clf = None 
best_score = 0 
for tran1 in transformers: 
    for tran2 in transformers: 
     pipe1 = Pipeline(pipe_text.steps + [tran1]) 
     pipe2 = Pipeline(pipe_title.steps + [tran2]) 
     union = FeatureUnion([('text', pipe1), ('title', pipe2)]) 
     X = union.fit_transform(df) 
     X_train, X_test, y_train, y_test = train_test_split(X, df.label) 
     for clf in clfs: 
      clf.fit(X_train, y_train) 
      score = clf.score(X_test, y_test) 
      if score > best_score: 
       best_score = score 
       best_est = clf 

これは簡単な例ですが、このようにさまざまな変換や分類子をどのようにプラグインすることができます。

1

FunctionTransformerの組み合わせを使用して特定の列のみを選択し、FeatureUnionを使用して各列のTFIDF、語数などの機能を組み合わせます。ややクリーンな方法があるかもしれませんが、あなたは何らかの種類のFeatureUnionとパイプラインのネストに関係なく終わるでしょう。

from sklearn.preprocessing import FunctionTransformer 
from sklearn.pipeline import FeatureUnion, Pipeline 
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer 

def first_column(X): 
    return X.iloc[:, 0] 

def second_column(X): 
    return X.iloc[:, 1] 

# pipeline to get all tfidf and word count for first column 
pipeline_one = Pipeline([ 
    ('column_selection', FunctionTransformer(first_column, validate=False)), 
    ('feature-extractors', FeatureUnion([('tfidf', TfidfVectorizer()), 
             ('counts', CountVectorizer()) 

    ])) 
]) 

# Then a second pipeline to do the same for the second column 
pipeline_two = Pipeline([ 
    ('column_selection', FunctionTransformer(second_column, validate=False)), 
    ('feature-extractors', FeatureUnion([('tfidf', TfidfVectorizer()), 
             ('counts', CountVectorizer()) 

    ])) 
]) 


# Then you would again feature union these pipelines 
# to get different feature selection for each column 
final_transformer = FeatureUnion([('first-column-features', pipeline_one), 
            ('second-column-feature', pipeline_two)]) 

# Your dataframe has your target as the first column, so make sure to drop first 
y = df['label'] 
df = df.drop('label', axis=1) 

# Now fit transform should work 
final_transformer.fit_transform(df) 

あなたが各列に複数の変圧器を適用したくない場合は(TFIDFとカウントの両方の可能性が有用ではないだろう)、あなたは一段の入れ子を削減することができます。

+0

あなたの答えをありがとう。しかし、それはテキストデータでは機能しないようです。 値がありませんエラー:文字列を浮動小数点に変換できませんでした。サンプルのデータセットで試してみてください。 –

+1

はい、数値データをチェックしないように、FunctionTransformerに 'validate = False'を追加する必要があります。また、ターゲット変数を削除し、データフレームで動作するように列選択関数を変更する必要がありましたが、私はあなたのデータセットでテストしました。上記のすべての編集で更新しました – elphz

関連する問題