我有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},])
我想尝试不同的特征提取方法:TFIDF,word2vec,具有不同ngram设置的Coutvectorizer等。但我想以不同的组合尝试它:一个特征集将包含用TFIDF转换的'text'数据,'使用Countvectoriser的url'和第二个将由w2v转换文本数据,由TFIDF转换为'url',依此类推。当然,最后,我想对不同的预处理策略进行比较,并选择最佳策略。
以下是问题:
有没有办法使用像Pipeline这样的标准sklearn工具来做这些事情?
我的想法是否有常识?也许有很好的想法如何处理文本数据与Dataframes中的许多列,我错过了?
非常感谢!
答案 0 :(得分:1)
我会使用FunctionTransformer的组合来仅选择某些列,然后使用FeatureUnion在每列上组合TFIDF,字数等功能。可能会有一种稍微清晰的方式,但我认为无论如何,你最终会得到某种FeatureUnion和Pipeline嵌套。
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和计数两者都可能没用),那么你可以将嵌套减少一步。
答案 1 :(得分:1)
@elphz答案很好地介绍了如何使用FeatureUnion
和FunctionTransformer
来完成此任务,但我认为它可以使用更多细节。
首先我会说你需要定义你的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
这是一个简单的例子,但您可以看到如何以这种方式插入各种变换和分类器。
答案 2 :(得分:1)
看看以下链接: http://scikit-learn.org/0.18/auto_examples/hetero_feature_union.html
class ItemSelector(BaseEstimator, TransformerMixin):
def __init__(self, key):
self.key = key
def fit(self, x, y=None):
return self
def transform(self, data_dict):
return data_dict[self.key]
键值接受熊猫数据框列标签。 在管道中使用它时,它可以应用为:
('tfidf_word', Pipeline([
('selector', ItemSelector(key='column_name')),
('tfidf', TfidfVectorizer())),
]))