Gensim docvecs.most_similar返回不存在的Id

时间:2017-03-27 16:37:53

标签: python gensim doc2vec

我正在尝试创建一个能够显示与特定文档类似的前n个文档的算法。 为此,我使用了gensim doc2vec。代码如下:

model = gensim.models.doc2vec.Doc2Vec(size=400, window=8, min_count=5, workers = 11, 
dm=0,alpha = 0.025, min_alpha = 0.025, dbow_words = 1)

model.build_vocab(train_corpus)

for x in xrange(10):
    model.train(train_corpus)
    model.alpha -= 0.002
    model.min_alpha = model.alpha
    model.train(train_corpus)

model.save('model_EN_BigTrain')

sims = model.docvecs.most_similar([408], topn=10)

sims var应该给我10个元组,作为doc的第一个元素,第二个是得分。 问题是某些ID与我的训练数据中的任何文档都不对应。

我现在已经尝试了一段时间来理解我的训练数据中没有的ID,但我没有看到任何逻辑。

Ps:这是我用来创建train_corpus

的代码
def readData(train_corpus, jData):

print("The response contains {0} properties".format(len(jData)))
print("\n")
for i in xrange(len(jData)):
    print "> Reading offers from Aux array"
    if i % 10 == 0: 
        print ">>", i, "offers processed..."

      train_corpus.append(gensim.models.doc2vec.TaggedDocument(gensim.utils.simple_preprocess(jData[i][1]), tags=[jData[i][0]]))
print "> Finished processing offers"

作为辅助阵列的每个位置,位置0的一个数组是int(我想成为id)和位置1 a description

提前致谢。

2 个答案:

答案 0 :(得分:2)

您是否使用普通整数ID作为tags,但未使用从0到您MAX_DOC_ID的所有整数?

如果是这样,那可以解释该范围内标签的出现。当你使用普通的int时,gensim Doc2Vec避免创建一个dict映射,为其内部vector-array中的索引位置提供标签 - 并且只使用int本身。

因此,必须分配内部向量数组以包含MAX_DOC_ID + 1行。与未使用的ID相对应的任何行仍然被初始化为随机向量,如所有位置,但是不会从实际文本示例接收任何训练以将它们推入有意义的相对位置。因此,这些随机初始化但未经训练的矢量可能出现在后来的most_similar()结果中。

要避免这种情况,请使用从0到最后ID所需的连续整数。或者,如果您能够承担字符串到索引映射的内存开销,请使用字符串标记而不是普通整数。或者,保留有效ID的额外记录,并从结果中手动过滤不需要的ID。

另外:通过在Doc2Vec模型初始化中不指定iter=1,默认的iter=5将生效,这意味着对train()的每次调用都会对您的数据进行5次迭代。奇怪的是,你的xrange(10) for循环包括每次迭代对train()的两次单独调用(第一次只是使用已经存在的alpha / min_alpha)。因此,您实际上正在对数据进行10 * 2 * 5 = 100次传递,并且具有奇怪的学习率计划。

我建议您改为仅设置iter=10 10次,保持默认alpha / min_alpha不变,然后只调用train()一次。该模型将完成10次传递,从开始到结束值平滑地管理alpha。

答案 1 :(得分:0)

我也遇到了这个问题,我正在用以下内容初始化我的doc2vec:

for idx,doc in data.iterrows():
    alldocs.append(TruthDocument(doc['clean_text'], [idx], doc['label']))

我正在传递一个有一些wink索引的数据框。我所要做的就是。

df.reset_index(inplace=True)