Pandas Sklearn Pipeline - DataMapper 转换的 CV?

Posted

技术标签:

【中文标题】Pandas Sklearn Pipeline - DataMapper 转换的 CV?【英文标题】:Pandas Sklearn Pipeline - CV on DataMapper transforms? 【发布时间】:2018-02-14 07:22:20 【问题描述】:

我想知道如何最好地使用 pandas-sklearn 在管道中定义数据映射器转换的参数。

Here 是使用泰坦尼克号数据的可重现示例笔记本。

我将其设置为:

# use pandas sklearn to do some preprocessing
full_mapper = DataFrameMapper([
    ('Name', Pipeline([ ('name_vect', CountVectorizer()) , ('name_tfidf', TfidfTransformer()) ]) ),
    ('Ticket', Pipeline([ ('ticket_vect', CountVectorizer()) , ('ticket_tfidf', TfidfTransformer()) ]) ),
    ('Sex', LabelBinarizer()),
    (['Age', 'Fare'], None), # i tried to use Impute() but got an error
    ])

我还想交叉验证我在“名称”和“票证”字段中使用的 CountVectorizer() 和 TfidfTransformer() 中的参数。

但是在将我的管道定义为:

# build full pipeline
full_pipeline  = Pipeline([
    ('mapper',full_mapper),
    ('clf', SGDClassifier(n_iter=15, warm_start=True))
])

然后我的参数为:

# determine full param search space (need to get the params for the mapper parts in here somehow)
full_params = 'clf__alpha': [1e-2,1e-3,1e-4],
                   'clf__loss':['modified_huber','hinge'],
                   'clf__penalty':['l2','l1']

我不知道如何在上述选项中包含“name_vect”、“name_tfidf”等。

我真的找不到类似于我在 pandas-sklearn docs 中尝试做的示例。

注意:此处仅使用泰坦尼克号数据进行重现。真的只是想让管道在这里工作。

更新(试图适应here的方法。)

如果我这样做:

# make pipeline for individual variables
name_to_tfidf = Pipeline([ ('name_vect', CountVectorizer()) , ('name_tfidf', TfidfTransformer()) ])
ticket_to_tfidf = Pipeline([ ('ticket_vect', CountVectorizer()) , ('ticket_tfidf', TfidfTransformer()) ])

# data frame mapper
full_mapper = DataFrameMapper([
    ('Name', name_to_tfidf ),
    ('Ticket', ticket_to_tfidf ),
    ('Sex', LabelBinarizer()),
    (['Age', 'Fare'], None), # i tried to use Impute() but got an error
    ])

# build full pipeline
full_pipeline  = Pipeline([
    ('mapper',full_mapper),
    ('clf', SGDClassifier(n_iter=15, warm_start=True))
])

# determine full param search space
full_params = 'clf__alpha': [1e-2,1e-3,1e-4],
               'clf__loss':['modified_huber','hinge'],
               'clf__penalty':['l2','l1'],
               # now set the params for the datamapper part of the pipeline
               'mapper__features':[[
                   ('Name',deepcopy(name_to_tfidf).set_params(name_vect__analyzer = 'char_wb')), # How can i set up a list for searching in here
                   ('Ticket',deepcopy(ticket_to_tfidf).set_params(ticket_vect__analyzer = 'char')) # How can i set up a list for searching in here
               ]]
              

# set up grid search
gs_clf = GridSearchCV(full_pipeline, full_params, n_jobs=-1)

# do the fit
gs_clf.fit(df,df['Survived'])

print("Best score: %0.3f" % gs_clf.best_score_)
print("Best parameters set:")
best_parameters = gs_clf.best_estimator_.get_params()
for param_name in sorted(full_params.keys()):
    print("\t%s: %r" % (param_name, best_parameters[param_name]))

然后我得到:

> Best score: 0.746 Best parameters set:    clf__alpha: 0.01    clf__loss:
> 'modified_huber'  clf__penalty: 'l1'  mapper__features: [('Name',
> Pipeline(memory=None,
>      steps=[('name_vect', CountVectorizer(analyzer='char_wb', binary=False, decode_error='strict',
>         dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
>         lowercase=True, max_df=1.0, max_features=None, min_df=1,
>         ngram_range=(1, 1), preprocessor=None, stop_words=None,
>         strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
>         tokenizer=None, vocabulary=None)), ('name_tfidf', TfidfTransformer(norm='l2', smooth_idf=True, sublinear_tf=False,
> use_idf=True))])), ('Ticket', Pipeline(memory=None,
>      steps=[('ticket_vect', CountVectorizer(analyzer='char', binary=False, decode_error='strict',
>         dtype=<class 'numpy.int64'>, encoding='utf-8', input='content',
>         lowercase=True, max_df=1.0, max_features=None, min_df=1,
>         ngram_range=(1, 1), preprocessor=None, stop_words=None,
>         strip_accents=None, token_pattern='(?u)\\b\\w\\w+\\b',
>         tokenizer=None, vocabulary=None)), ('ticket_tfidf', TfidfTransformer(norm='l2', smooth_idf=True, sublinear_tf=False,
> use_idf=True))]))]

所以看起来我可以在这里设置参数。但是,如果我通过类似的列表:

# determine full param search space (need to get the params for the mapper parts in here somehow)
full_params = 'clf__alpha': [1e-2,1e-3,1e-4],
               'clf__loss':['modified_huber','hinge'],
               'clf__penalty':['l2','l1'],
               # now set the params for the datamapper part of the pipeline
               'mapper__features':[[
                   ('Name',deepcopy(name_to_tfidf).set_params(name_vect__analyzer = ['char', 'char_wb'])),
                   ('Ticket',deepcopy(ticket_to_tfidf).set_params(ticket_vect__analyzer = ['char', 'char_wb']))
               ]]
              

我收到如下错误:

C:\Users\Andrew\Miniconda3\lib\site-packages\sklearn\feature_extraction\text.py in build_analyzer(self=CountVectorizer(analyzer=['char', 'char_wb'], bi...)\\b\\w\\w+\\b', tokenizer=None, vocabulary=None))
    265             return lambda doc: self._word_ngrams(
    266                 tokenize(preprocess(self.decode(doc))), stop_words)
    267 
    268         else:
    269             raise ValueError('%s is not a valid tokenization scheme/analyzer' %
--> 270                              self.analyzer)
        self.analyzer = ['char', 'char_wb']
    271 
    272     def _validate_vocabulary(self):
    273         vocabulary = self.vocabulary
    274         if vocabulary is not None:

ValueError: ['char', 'char_wb'] is not a valid tokenization scheme/analyzer

所以不确定如何将 DataFrameMapper 转换的参数设置为 CV 搜索的选项。

肯定有办法。同意,但在这个阶段可能会更好去 pandas > numpy > FeatureUnion...

【问题讨论】:

恐怕这不是一个容易完成的任务。我唯一能找到的是:datascience.stackexchange.com/questions/677/…。我建议为此使用 FeatureUnion,而不是 DataframeMapper。 干杯,是的-我要深入研究这个问题,因为它似乎有我需要的东西。很想留在熊猫中,尽管当我为各种不同的变量类型执行 CV 时,转换为具有各种不同下游错误的 numpy 数组会很有趣。我将调整我的方法以使用 df.to_records() 之类的方法进入 numpy 数组,然后进行特征联合。在其他地方看到了一些迹象,可能 pandas-sklearn 还不太成熟。 是的,事实证明,在问题中做你想做的事情太复杂了。我不确定您代码的其他部分,但对于上述问题,FeatureUnion 非常简单。 您好 Andrew,不确定这是否可行,但您可以尝试 ticket_to_tfidf__param_name 设置嵌套参数 【参考方案1】:

这只是我在使用 sklearn-pandas 包时也遇到的缺点之一。 但是,我发现编写自己的转换器类可以让您完全控制管道中甚至功能联合中发生的事情。

可以自定义每个 sklearn 转换器以仅选择某些 pandas 列,甚至可以将转换输出为 pandas 数据框并进行一些调整。

查看我的博客以获得全面的导览: https://wkirgsn.github.io/2018/02/15/pandas-pipelines/

【讨论】:

欢迎来到 Stack Overflow!请注意,如果您想宣传自己的网站或博客,您必须在回答中披露您的隶属关系。否则,您的回答可能会被标记为垃圾邮件。请阅读How to not be a spammer。 这次我已经为你编辑了。但请记住我们下次可能进行自我推销的政策,并在下次您的问题/答案中包含此披露信息。

以上是关于Pandas Sklearn Pipeline - DataMapper 转换的 CV?的主要内容,如果未能解决你的问题,请参考以下文章

从 sklearn.pipeline.Pipeline 获取转换器结果

从 sklearn 中的 Pipeline 对象返回系数

sklearn.pipeline.Pileline

如何使用 sklearn.pipeline 转换新数据

sklearn:无法使 OneHotEncoder 与 Pipeline 一起使用

Sklearn ColumnTransformer + Pipeline = TypeError