使用doc2vec和gensim的文本分类模型

时间:2019-10-02 04:49:30

标签: python machine-learning gensim doc2vec

我正在使用gensim和doc2vec进行文本分类。我正在使用两个数据集对此进行测试,一个是堆栈交换数据集和Reddit数据集。我试图在一个特定主题的一个subreddit / stackexchange网站上的帖子之间进行分类,然后将其他不相关的subreddit / stackexchange网站上的帖子用作负面示例。

我正在使用10k帖子的数据集来训练模型,并使用5k的测试集划分为50%的正面示例和50%的负面示例。然后,我使用infer_vector和most_like函数将条目分类为肯定或否定。在训练模型之前,我会对数据进行预处理,以删除所有单词,符号,链接等,仅留下最重要的单词来训练模型。下面是用于训练模型的代码。

let

此方法有效,我可以从中获得结果,但是我想知道是否有其他训练方法来获得更好的结果。目前,我只是在训练许多具有不同历元和vector_sizes的模型,然后使用infer_vector和most_similar函数查看从most_like条目返回的矢量分数是否大于某个数值,但是有什么方法可以对此方面进行改进训练模型?

此外,为了获得更好的结果,我以较大的数据集(超过100k个条目)以相同的方式训练了另一个模型。当我在相同的数据集上使用该模型时,与在较小的数据集上训练的模型相比,产生的结果相似但更差。我认为更多的训练数据会改善结果,但又不会使结果更糟,有人知道原因吗?

此外,为了进一步测试,我创建了一个新的但更大的测试集(1.5万个条目),其效果甚至比原始测试集还要差。该测试集中的数据虽然唯一,但与原始测试集中使用的数据类型相同,但产生的结果却更糟,这可能是什么原因?

df = pd.read_csv("fulltrainingset.csv")

df.columns.values[0] = "A"

tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(df["A"])]

epoch_list = [1,5,10,15,25,50,100,200,300,400]
size_list = [1,5,10,15,25,50,100,200,300]

for x in epoch_list:
    for y in size_list:

        vec_size = y
        max_epochs = x
        minimum_count = 1
        mode = 0
        window_ = 15
        negative_sampling = 5
        subsampling = 1e-5
        alpha = 0.025
        minalpha = 0.00025

        model = Doc2Vec(alpha=alpha, min_alpha=minalpha, vector_size=vec_size, dm=mode, min_count=minimum_count, window =window_, sample=subsampling ,hs =negative_sampling)
        model.build_vocab(tagged_data)

        for epoch in range(max_epochs):
            print('iteration {0}'.format(epoch))
            model.train(tagged_data,
                        total_examples=model.corpus_count,
                        epochs=model.epochs)#self.epochs
            model.alpha -= 0.0002
            model.min_alpha = model.alpha


        model.save(str(y)+"s_"+str(x)+"e.model")

1 个答案:

答案 0 :(得分:0)

听起来好像您是在为每个论坛的“进” /“出”决策训练一个单独的Doc2Vec模型,然后使用一组临时的infer_vector() / most_similar()操作来做决定。

这是一种非常粗糙的临时方法,您应该查看更正式的文本分类方法的介绍,在此过程中,有一个明确的功能发现步骤(可能包括为您创建Doc2Vec矢量)文字或其他技术),然后再进行清晰的分类器训练,然后进行评估。

(此时您可能还正在训练更大的模型,包括来自所有论坛的带有标签的训练示例,以及从多个可能的类别中选择一个的分类器。)

另外,在您的Doc2Vec培训中,有几件事是错误的或非最佳的,包括:

  • 在您自己的循环中多次调用train()或更改默认alpha / min_alpha几乎总是被误导。实际上,您当前的代码实际上是使model.epochs(5)传递每次调用的数据,并且经常将alpha递减0.0002数百次(变为无意义的负值)。只需一次调用train(),并以所需的epochs数目,默认值alpha / min_alpha调用hs=5,它将做正确的事情。 (并且:不要相信上面的循环调用所建议的任何在线教程/示例。)

  • 您的negative=5将打开/关闭严格打开的分级-softmax模式,但保留默认的negative参数-因此您的模型将使用(非标准否定采样和分层softmax训练的结合可能很无用和缓慢)。最好使用一些hs=0值和negative=0, hs=1(用于纯负采样),或者使用negative=5, hs=0(用于纯分层softmax)。或者只是坚持使用默认值(min_count=1),除非/直到所有事情都已经生效并且您想进行更深入的优化为止。

  • func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) { print("\(URLContexts.first!.url)") } 很少是最佳选择:这些模型通常受益于丢弃稀有词。

更正了这些问题之后,您可能会发现,更多的数据将趋于带来通常预期的改进结果。 (如果那时还不行,请在培训,推理和评估时仔细检查所有文本预处理/标记是否正确完成;如果您仍然有问题,则可以再提出一个新问题,并提供更多详细信息/数字,指出预期的改进结果却差一些。)