我是一个新的词/段落嵌入和尝试理解通过doc2vec在GENSIM。我想就我的理解是否不正确征求意见。我的理解是,doc2vec潜在地能够返回可能具有语义相似内容的文档。作为一个测试,我尝试了以下几个问题。
问题1:我注意到,每一次相同参数和示例的训练都会产生一个与以前的训练结果截然不同的模型(例如,不同的向量和相似文档的每次排序)。为什么这是不确定的?因此,这是否可以可靠地用于任何实际工作?
问题2:为什么我没有得到顶部类似文档的标签ids呢?结果:[(“日”,0.477),(“2016年”,0.386).
问题2回答:问题是由model.most_similar引起的,应该用model.docvecs.most_similar代替
如果我误解了什么,请告诉我?
数据准备
我创建了多个文档,每个文档都有一个句子。我故意使它们在语义上完全不同。
这是一个晴朗的夏天,鸟儿歌唱,阳光灿烂。
如果我有一个赏识学位的话,那真是个美好的日子。
C:地球科学大学2016-2017年学位
D: 2009-2010年生命与自然生命学院
质疑:2009年至2010年思维大学哲学学位
训练
我训练了文档(标记作为单词,运行索引作为标记)
tdlist=[]
docstring=['It is a fine summer weather, with the birds singing and sun shining bright.',
'It is a lovely day indeed, if only i had a degree in appreciating.',
'2016-2017 Degree in Earth Science Earthly University',
'2009-2010 Dip in Life and Nature Life College']
counter=1
for para in docstring:
tokens=tokenize(para) #This will also strip punctuation
td=TaggedDocument(gensim.utils.to_unicode(str.encode(' '.join(tokens))).split(), str(counter))
tdlist.append(td)
counter=counter+1
model=gensim.models.Doc2Vec(tdlist,dm=0,alpha=0.025, size=20, min_alpha=0.025, min_count=0)
for epoch in range(200):
model.train(tdlist, total_examples=model.corpus_count, epochs=model.iter)推理
然后,我试图推断出这个查询。虽然查询的词汇表中有许多缺少的单词,但我希望C和D的文档相似度结果最接近,但结果只给出了一个“单词”列表,然后是一个相似度分数。我不确定我的理解是否错误。下面是我的代码摘录。
mydocvector=model.infer_vector(['Degree' ,'in' ,'Philosophy' ,'from' ,'Thinking' ,'University', 'from', '2009', 'to', '2010'])
print(model.docvecs.most_similar(positive=[mydocvector])发布于 2017-06-16 19:05:44
Doc2Vec不能很好地处理玩具大小的数据集--很少的文档,很少的总单词,每个文档的几个单词。您绝对需要比向量维度(size)更多的文档,理想情况下需要数万个或更多的文档。
TaggedDocument的第二个参数应该是标记列表。通过提供一个字符串的int,它的每个元素(字符)将被视为标记。(仅使用document 1 to 4,这不会有什么影响,但一旦您有了文档10,Doc2Vec就会将其视为标记1和0,除非您将其作为['10'] (一个单一元素列表)提供)。
是的,要找到最相似的文档,您可以使用model.docvecs.most_similar()而不是model.most_similar() (如果有的话,model.most_similar()只对学习过的单词进行操作)。
您正在使用dm=0模式,这是一个很好的开始想法-它的速度快,往往是一流的表现。但是请注意,这种模式也没有训练单词向量。因此,你要求从顶级模型中得到的任何东西,比如model['summer']或model.most_similar('sun'),都将是基于随机初始化但没有经过训练的单词的毫无意义的结果。(如果您也需要训练单词,可以将dbow_words=1添加到dm=0模式,或者使用dm=1模式。但是对于纯文档向量来说,dm=0是一个不错的选择。)
没有必要在循环中调用train() --实际上,考虑到它上面的行,根本不需要调用它。您用来实例化Doc2Vec的表单,使用一个实际的tdlist语料库作为第一个参数,已经使用默认数量的iter passes (5)和提供的alpha和min_alpha触发模型设置和培训。现在,对于Doc2Vec培训,您通常需要更多的传球(10到20次是常见的,尽管较小的数据集可能会受益更多)。对于任何训练,对于适当的梯度下降,您希望有效的学习率alpha逐渐下降到一个可以忽略不计的值,比如默认的0.0001 (而不是强制的相同的起始值)。
通常会显式调用train()的唯一情况是,如果不使用语料库实例化模型。在这种情况下,您需要同时调用model.build_vocab(tdlist) (让模型使用已发现的词汇表初始化),然后调用某种形式的train() -但您仍然只需要一个调用来训练,提供所需的传球数。(允许默认的model.iter 5传递,在一个200次迭代的外部循环中,意味着共有1000次遍历数据.而且都是固定的alpha,这不是适当的梯度下降。)
当您有一个更强的数据集时,您可能会发现使用更高的min_count可以提高结果。通常情况下,只出现几次的单词并没有多大意义,因此只起到了噪音减缓训练和干扰其他载体变得更有表达的作用。(不要认为“更多的话一定等于更好的结果”)。把单身汉或更多的人扔出去通常会有所帮助。
关于推理,你的推理文本中几乎没有一个词是在训练集中的。(我只看到‘学位’,'in',‘大学’重复。)因此,除了上述所有问题外,很难为示例文本推断出一个好的向量。有了更多的训练,你可能会得到更好的结果。它还经常帮助将steps可选参数增加到infer_vector(),远远超过其缺省值5。
https://stackoverflow.com/questions/44589872
复制相似问题