Gensim的Doc2Vec-如何使用经过预训练的word2vec(单词相似性)

问题描述 投票:0回答:1

我没有大量的数据集来训练单词相似性,例如“热”比“冷”更类似于“温暖”。但是,我喜欢在相对较小的语料库(约100个文档)上训练doc2vec,以便可以对我的特定领域文档进行分类。

为了详细说明,让我使用这个玩具示例。假设我只有4个训练文档,由4个句子给出:“我爱热巧克力。”,“我讨厌热巧克力”,“我爱热茶”。 ”和“我喜欢热蛋糕”。我希望给定一个测试文件“我喜欢热巧克力”,doc2vec总是会返回“我喜欢热巧克力”。作为最近的文档。如果word2vec已经提供了“崇拜”与“爱”非常相似的知识,那么这种期望将是正确的。但是,我得到的最相似的文档是“我讨厌热巧克力”,这很奇怪!

关于如何规避此问题的任何建议,即能够使用预先训练的单词嵌入,这样我就不必冒险去训练“崇拜”接近“爱”,“恨”接近“憎恶” ,依此类推。

代码(Jupyter Nodebook。Python 3.7。Jensim 3.8.1)

from gensim.models.doc2vec import Doc2Vec, TaggedDocument
from nltk.tokenize import word_tokenize
data = ["I love hot chocolate.",
        "I hate hot chocolate",
       "I love hot tea.",
       "I love hot cake."]

tagged_data = [TaggedDocument(words=word_tokenize(_d.lower()), tags=[str(i)]) for i, _d in enumerate(data)]
print(tagged_data)
#Train and save
max_epochs = 10
vec_size = 5
alpha = 0.025


model = Doc2Vec(vector_size=vec_size, #it was size earlier
                alpha=alpha, 
                min_alpha=0.00025,
                min_count=1,
                dm =1)

model.build_vocab(tagged_data)

for epoch in range(max_epochs):
    if epoch % 10 == 0:
        print('iteration {0}'.format(epoch))
    model.train(tagged_data,
                total_examples=model.corpus_count,
                epochs=model.epochs) #It was model.iter earlier
    # decrease the learning rate
    model.alpha -= 0.0002
    # fix the learning rate, no decay
    model.min_alpha = model.alpha

print("Model Ready")

test_sentence="I adore hot chocolate"
test_data = word_tokenize(test_sentence.lower())
v1 = model.infer_vector(test_data)
#print("V1_infer", v1)

# to find most similar doc using tags
sims = model.docvecs.most_similar([v1])
print("\nTest: %s\n" %(test_sentence))
for indx, score in sims:
    print("\t(score: %.4f) %s" %(score, data[int(indx)]))
python nlp gensim doc2vec
1个回答
0
投票

仅约100个文档太小,无法有效地训练Doc2Vec(或Word2Vec)模型。已发布的Doc2Vec作品倾向于使用数万到数百万个文档。

在某种程度上,您可能可以从较小的数据集中获得稍微有意义的结果,通常需要将向量大小大量减少-远小于单词/示例的数量-并增加训练时间。 (您的玩具数据有4个文本和6个唯一的单词。即使要获得5维向量,您可能还需要5 ^ 2个可简化文档的文件。)

[此外,gensim的Doc2Vec没有提供任何官方选项来从其他位置导入字向量。内部Doc2Vec训练不是首先训练单词向量,然后计算doc向量的过程。相反,文档向量和单词向量是在同时进行的过程中进行训练的,逐渐一起改进。 (某些模式,例如可以通过DBOW启用的快速且通常高效的dm=0,根本不创建或使用字向量。)

[4句结果的确没有什么奇怪的,当我们看数据时就好像我们是Doc2VecWord2Vec算法一样,它们没有关于单词的先验知识,只有训练数据中的内容。在您的训练数据中,标记'love'和标记'hate'的使用方式几乎完全相同,周围的单词也相同。这些“密集嵌入”模型只有通过看到单词的许多细微变化的替代用法以及许多相反的周围单词,才能将单词向量移动到有用的相对位置,在这些位置上,它们更接近相关单词,而与其他单词的距离更远。 (并且,由于您没有使用令牌'adore'提供任何训练数据,因此该模型对该单词一无所知–如果该单词在测试文档中提供,就像该模型的infer_vector()方法一样,它将被忽略。因此,它“看到”的测试文档只是已知的单词['i', 'hot', 'chocolate']。)

但是,即使您确实设法在更大的数据集上进行训练,或者以某种方式从其他单词向量中注入了'love''adore'有点相似的知识,也必须注意,反义词在单词向量的集合也是如此-因为它们在相同的上下文中使用,并且通常在语法上可互换,并且具有相同的一般类别。这些模型通常非常擅长通过将单词交换成其反义词(或插入单个“ not”或其他反向意图的单词)来检测人类翻转的含义。 最终,如果您想使用gensim的Doc2Vec,则应该使用更多的数据进行训练。 (如果您愿意使用其他一些预先训练的单词向量,为什么不使用其他一些类似的批量句子来源呢?使用不完全符合您实际问题的数据的效果也会相似。外部数据(通过批量文本或预先训练的模型)。]

最后:在您自己的循环中使用您自己的train()调整多次调用alpha是一种错误且容易出错的模式。您只需使用正确的epochs编号调用一次,模型将执行多次训练并在正确的时期数内平滑管理内部alpha

© www.soinside.com 2019 - 2024. All rights reserved.