2017-06-16 124 views
1

我正在使用gensim库通过doc2vec模型在Python中构建NLP聊天应用程序。我有硬编码的文档并给出了一组训练示例,我通过抛出用户问题来测试模型,然后找到大多数类似的文档作为第一步。在这种情况下,我的测试问题是来自培训示例的文档的精确副本。如何提高doc2vec模型中两个文档(句子)的余弦相似度?

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,因为它们是完全一样的。我应该如何提高这个准确度?有没有培训文件的具体方式,我错过了什么?

+0

所有SENT_4和SENT_3首先是不完全一样的。看看单词“promotion” –

+0

纠正后:[('SENT_1',0.043695494532585144),('SENT_2',0.0017897281795740128),('SENT_0',-0.018954679369926453),('SENT_3',-0.08253869414329529)] – Kshitiz

回答

1

Word2Vec/Doc2Vec在玩具大小的示例(如少量文本,简短文本和少量总字)上效果不佳。许多理想的属性只能通过数百万字或数万个文档的训练集可靠实现。

特别是,只有5个例子,只有十几个或两个单词,但是建模向量100维,训练不会被迫做主要的事情,这使word-vectors/doc-vectors很有用:将表示压缩成稠密嵌入,其中相似项目需要在向量空间中彼此靠近地增量式微移,因为没有办法在巨型查找表排序中保留所有原始变化。除了语料库变体以外,您的相同标记SENT_3SENT_4可以采用截然不同的文档向量,并且该模型仍然足够大以在其培训任务(基本上,“过度拟合”)方面做得很好,而没有期望的最终状态类似的文字有相似的向量被迫。

有时您可以通过更多的训练迭代以及更小的模型(根据矢量size)从小数据集中挤出更多的含义,但实际上:这些矢量需要大量不同的数据集才能变得有意义。

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

  • 您的代码不使用类LabeledLineSentence,所以没有必要在这里包括它 - 这是无关紧要的样板。 (另外,TaggedDocument是在最近gensim版本的words + tags文档类首选的名称,而不是LabeledSentence)的alpha

  • 您的自定义管理和min_alpha是不可能做任何有用的东西。除非你已经有了一些工作,理解算法,然后想尝试微妙的优化,否则这些最好保留默认值。

  • train()会做自己的迭代,所以你不需要在外循环中多次调用它。 (这段代码的写入在第一个循环中执行,迭代的值为alpha,值从0.03逐渐下降到0.025,然后在0.028的固定α处进行5次迭代,然后在0.026处再进行5次迭代,然后在α减小的情况下再进行5次迭代27次,以固定的α为-0.028结束于第30个循环。这是一个无意义的结局值 - 学习率永远不会是负值 - 在无意义的进展结束时。即使有一个大的数据集,这150次迭代,在负alpha值的一半左右发生的事情,可能会产生奇怪的结果。)