繁体   English   中英

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

[英]Gensim's Doc2Vec - How to use pre-trained word2vec (word similarities)

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

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

关于如何规避这一点的任何建议,即能够使用预先训练的词嵌入,这样我就不需要冒险训练“爱”接近“爱”,“恨”接近“厌恶”,以及很快。

代码(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)]))

仅约 100 个文档太小,无法有意义地训练Doc2Vec (或Word2Vec )模型。 已发布的Doc2Vec工作往往使用数万到数百万个文档。

如果您能够从较小的数据集中获得稍微有意义的结果,您通常需要大量减少向量大小——远小于单词/示例的数量——并增加训练时期。 (您的玩具数据有 4 个文本和 6 个独特的词。即使要获得 5 维向量,您也可能需要类似 5^2 的对比文档。)

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

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

而且,即使您确实设法在更大的数据集上进行了训练,或者以某种方式从其他词向量中注入了'love''adore'有点相似的知识,重要的是要注意反义词在一组中通常非常相似词向量也是如此——因为它们在相同的上下文中使用,并且通常在句法上可以互换,并且属于相同的一般类别。 这些模型往往不在检测从一个字的交换倒装在人类感知的含义为它的反义词(或单“而不是”或其他逆转意图的话插入)非常好。

最后,如果你想使用 gensim 的Doc2Vec ,你应该用更多的数据来训练它。 (如果您愿意获取一些其他预先训练好的词向量,为什么不获取一些类似的大量句子的其他来源?使用与您的实际问题不完全相同的数据的效果将是相似的,无论您是否利用它通过批量文本或预训练模型获取外部数据。)

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM