我是word / paragraph嵌入的新手,并试图通过GENSIM中的doc2vec来理解。我想就我的理解是否不正确寻求建议。我的理解是doc2vec可能能够返回可能具有语义相似内容的文档。作为测试,我尝试了以下内容并提出以下问题。
问题1 :我注意到每次使用完全相同的参数和示例进行的训练都会产生一个模型,该模型会产生与之前列车完全不同的结果(例如,不同的向量和类似文档的不同排名eveytime)..为什么这么不确定?因此,这可以可靠地用于任何实际工作吗?
问题2 :为什么我没有获得顶级类似文档的标记ID? 结果:[(' day',0.477),(' 2016',0.386)....
问题2回答:问题是由于model.most_similar,应该使用model.docvecs.most_similar而不是
请告知我是否误解了什么?
数据准备
我创建了多个文档,每个文档都有一个句子。我故意使它们在语义上明显不同。
答:这是一个晴朗的夏天,鸟儿在唱歌,阳光明媚。B:如果我有一个欣赏学位,那确实是美好的一天。
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])
答案 0 :(得分:0)
Doc2Vec在玩具大小的数据集上运行良好 - 文档很少,总单词很少,每个文档的单词很少。您绝对需要比矢量维度(size
)更多的文档,理想情况下需要数万个或更多的文档。
TaggedDocument
的第二个参数应该是标记的列表。通过提供单个string-of-an-int,其每个元素(字符)将被视为标记。 (只有文档1
到4
这还不会受到伤害,但只要您有文档10
,Doc2Vec就会将其视为标记1
和{ {1}},除非您将其作为0
(单元素列表)提供。
是的,要查找大多数类似的文档,请使用['10']
而不是model.docvecs.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
传递(5)和提供的alpha
和min_alpha
。现在,对于Doc2Vec培训,您经常需要更多的传递(10到20是常见的,尽管较小的数据集可能会受益更多)。对于任何训练,对于适当的梯度下降,您希望有效学习率alpha
逐渐下降到可忽略的值,例如默认0.0001
(而不是强制相同的起始值)值)。
您通常明确调用train()
的唯一情况是,如果您在没有语料库的情况下实例化模型。在这种情况下,您需要同时调用model.build_vocab(tdlist)
(让模型使用已发现的词汇表初始化),然后调用某种形式的train()
- 但您仍需要一次打电话,提供所需的通行证数量。 (允许默认model.iter
5次传递,在200次迭代的外部循环内,意味着总共有1000次传递数据......并且所有传递都是相同的固定alpha
,这不是适当的渐变 - 下降。)
当您拥有更强大的数据集时,您可能会发现结果随着min_count
更高而得到改善。通常只出现几次的单词不能提供很多意义,因此仅用作降噪训练并且干扰其他向量变得更具表现力。 (不要假设"更多的单词必须等于更好的结果"。)抛出单身或更多,通常会有帮助。
关于推理,您的推理文本中的几乎所有单词都不在训练集中。 (我只看到' Degree',''大学'重复。)所以除了上面的所有问题,推断一个好的向量为例子文字很难。通过更丰富的训练集,您可能会获得更好的结果。它还有助于将steps
可选参数增加到infer_vector()
远远超过其默认值5.