Doc2Vec 的管道和网格搜索

Posted

技术标签:

【中文标题】Doc2Vec 的管道和网格搜索【英文标题】:Pipeline and GridSearch for Doc2Vec 【发布时间】:2018-10-21 01:40:02 【问题描述】:

我目前有以下脚本,可帮助找到 doc2vec 模型的最佳模型。它的工作原理是这样的:首先根据给定的参数训练一些模型,然后针对分类器进行测试。最后,它输出最好的模型和分类器(我希望)。

数据

示例数据(data.csv)可以在这里下载:https://pastebin.com/takYp6T8 请注意,数据的结构应该构成一个准确率为 1.0 的理想分类器。

脚本

import sys
import os
from time import time
from operator import itemgetter
import pickle
import pandas as pd
import numpy as np
from argparse import ArgumentParser

from gensim.models.doc2vec import Doc2Vec
from gensim.models import Doc2Vec
import gensim.models.doc2vec
from gensim.models import KeyedVectors
from gensim.models.doc2vec import TaggedDocument, Doc2Vec

from sklearn.base import BaseEstimator
from gensim import corpora

from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
from sklearn.pipeline import Pipeline
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report


dataset = pd.read_csv("data.csv")

class Doc2VecModel(BaseEstimator):

    def __init__(self, dm=1, size=1, window=1):
        self.d2v_model = None
        self.size = size
        self.window = window
        self.dm = dm

    def fit(self, raw_documents, y=None):
        # Initialize model
        self.d2v_model = Doc2Vec(size=self.size, window=self.window, dm=self.dm, iter=5, alpha=0.025, min_alpha=0.001)
        # Tag docs
        tagged_documents = []
        for index, row in raw_documents.iteritems():
            tag = '_'.format("type", index)
            tokens = row.split()
            tagged_documents.append(TaggedDocument(words=tokens, tags=[tag]))
        # Build vocabulary
        self.d2v_model.build_vocab(tagged_documents)
        # Train model
        self.d2v_model.train(tagged_documents, total_examples=len(tagged_documents), epochs=self.d2v_model.iter)
        return self

    def transform(self, raw_documents):
        X = []
        for index, row in raw_documents.iteritems():
            X.append(self.d2v_model.infer_vector(row))
        X = pd.DataFrame(X, index=raw_documents.index)
        return X

    def fit_transform(self, raw_documents, y=None):
        self.fit(raw_documents)
        return self.transform(raw_documents)


param_grid = 'doc2vec__window': [2, 3],
              'doc2vec__dm': [0,1],
              'doc2vec__size': [100,200],
              'logreg__C': [0.1, 1],


pipe_log = Pipeline([('doc2vec', Doc2VecModel()), ('log', LogisticRegression())])

log_grid = GridSearchCV(pipe_log, 
                        param_grid=param_grid,
                        scoring="accuracy",
                        verbose=3,
                        n_jobs=1)

fitted = log_grid.fit(dataset["posts"], dataset["type"])

# Best parameters
print("Best Parameters: \n".format(log_grid.best_params_))
print("Best accuracy: \n".format(log_grid.best_score_))
print("Finished.")

关于我的脚本,我确实有以下问题(我在这里将它们结合起来以避免三个帖子具有相同的代码 sn-p):

    def __init__(self, dm=1, size=1, window=1): 的用途是什么?我可以以某种方式删除这部分(尝试失败)吗? 如何将RandomForest 分类器(或其他)添加到 GridSearch 工作流/管道? 如何将训练/测试数据拆分添加到上述代码中,因为当前脚本仅在完整数据集上进行训练?

【问题讨论】:

关于第三点,通常最好的做法是使用 K-Fold 交叉验证,而不是仅仅在训练和测试集中分割数据集。请参阅:cross_val_predict 或 cross_validate 我可以得到这段代码的来源吗?你从哪里得到的?我需要做类似的事情,所以需要一些参考 【参考方案1】:

1) init() 允许您定义希望类在初始化时采用的参数(相当于 java 中的构造函数)。

请查看这些问题了解更多详情:

Python __init__ and self what do they do? Python constructors and __init__

2) 为什么要添加RandomForestClassifier,它的输入是什么?

看看你的另外两个问题,你想在这里比较一下RandomForestClassifier的输出和LogisticRegression吗?如果是这样,你在this question of yours 做得很好。

3) 你已经导入了train_test_split,就用它吧。

X_train, X_test, y_train, y_test = train_test_split(dataset["posts"], dataset["type"])

fitted = log_grid.fit(X_train, y_train)

【讨论】:

以上是关于Doc2Vec 的管道和网格搜索的主要内容,如果未能解决你的问题,请参考以下文章

在 sklearn 中使用网格搜索和管道获得正确的交叉验证分数

管道和网格搜索的 SKLearn 错误

在 Scikit Learn 中使用网格搜索 (GridSearchCV) 和管道的支持向量回归 (SVR) 中的系数

尝试使用管道和网格搜索运行随机森林分类器时出错

如果我在 python 管道中有自定义的集成模型,如何进行交叉验证和网格搜索

用于管道的网格搜索参数网格的说明