如何提高 doc2vec 模型中两个文档(句子)的余弦相似度?

How can I improve the cosine similarity of two documents(sentences) in doc2vec model?

我正在 Python 中通过 doc2vec 模型使用 gensim 库构建一个 NLP 聊天应用程序。我有硬编码文档并给出了一组训练示例,我通过抛出用户问题然后找到最相似的文档作为第一步来测试模型。在这种情况下,我的测试问题是训练示例中文档的精确副本。

import gensim
from gensim import models
sentence = models.doc2vec.LabeledSentence(words=[u'sampling',u'what',u'is',u'tell',u'me',u'about'],tags=["SENT_0"])
sentence1 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'what',u'is',u'my',u'limit',u'how',u'much',u'can',u'I',u'claim'],tags=["SENT_1"])
sentence2 = models.doc2vec.LabeledSentence(words=[u'eligibility',u'I',u'am',u'retiring',u'how',u'much',u'can',u'claim',u'have', u'resigned'],tags=["SENT_2"])
sentence3 = models.doc2vec.LabeledSentence(words=[u'what',u'is',u'my',u'eligibility',u'post',u'my',u'promotion'],tags=["SENT_3"])
sentence4 = models.doc2vec.LabeledSentence(words=[u'what',u'is', u'my',u'eligibility' u'post',u'my',u'promotion'], tags=["SENT_4"])
sentences = [sentence, sentence1, sentence2, sentence3, sentence4]
class LabeledLineSentence(object):
    def __init__(self, filename):
        self.filename = filename
    def __iter__(self):
        for uid, line in enumerate(open(filename)):
            yield LabeledSentence(words=line.split(), labels=['SENT_%s' % uid])
model = models.Doc2Vec(alpha=0.03, min_alpha=.025, min_count=2)
model.build_vocab(sentences)
for epoch in range(30):
    model.train(sentences, total_examples=model.corpus_count, epochs = model.iter)
    model.alpha -= 0.002  # decrease the learning rate`
    model.min_alpha = model.alpha  # fix the learning rate, no decay
model.save("my_model.doc2vec")
model_loaded = models.Doc2Vec.load('my_model.doc2vec')
print (model_loaded.docvecs.most_similar(["SENT_4"]))

结果:

[('SENT_1', 0.043695494532585144), ('SENT_2', 0.0017897281795740128), ('SENT_0', -0.018954679369926453), ('SENT_3', -0.08253869414329529)]

SENT_4SENT_3 的相似度仅为 -0.08253869414329529,因为它们完全相同,应该为 1。我应该如何提高这种准确性?是否有特定的培训文件方式,我遗漏了什么?

Word2Vec/Doc2Vec 不适用于玩具大小的示例(例如文本少、文本短和总字数少)。许多理想的特性只有通过数百万个单词或数万个文档的训练集才能可靠地实现。

特别是,只有 5 个示例,只有一打或两个单词,但建模向量有 100 维,训练不会被迫做使 word-vectors/doc-vectors 有用的主要事情:压缩将表示转化为密集嵌入,其中相似的项目 需要 在向量 space 中逐渐靠近彼此,因为无法以某种方式保留所有原始变化巨型查找-table。由于维度比语料库变体更多,您的相同标记 SENT_3SENT_4 可以采用截然不同的文档向量,并且模型仍然足够大,可以很好地完成其训练任务(本质上,'overfit'), 而不会强制具有相似向量的相似文本的期望最终状态。

有时您可以通过更多的训练迭代和更小的模型(就向量 size 而言)从小数据集中挤出更多的意义,但实际上:这些向量需要大而多样的数据集变得有意义。

这是主要问题。您的示例代码中的其他一些低效或错误:

  • 您的代码未使用 class LabeledLineSentence,因此无需在此处包含它——它是不相关的样板文件。 (此外,TaggedDocumentwords+tags 文档 class 在最近的 gensim 版本中的首选名称,而不是 LabeledSentence。)

  • 您对 alphamin_alpha 的自定义管理不太可能做任何有用的事情。这些最好保留默认值,除非您已经有一些工作,很好地理解算法,然后想尝试微妙的优化。

  • train() 将进行自己的迭代,因此您无需在外循环中多次调用它。 (这段代码在其第一个循环中进行了 5 model.iter 次迭代 alpha 值逐渐从 0.03 下降到 0.025,然后在 0.028 的固定 alpha 下进行 5 次迭代,然后在 0.026 处再进行 5 次迭代,然后再进行 27 次迭代以递减的 alpha 进行 5 次迭代的集合,在第 30 个循环结束时以固定的 alpha -0.028 结束。这是一个无意义的结束值——学习率永远不应该是负的——在无意义的进展结束时。即使有一个大数据集,这 150 次迭代,大约一半发生在负 alpha 值,可能会产生奇怪的结果。)