我正在尝试使用训练数据训练一个doc2vec模型,然后使用训练好的doc2vec模型,查找测试数据中特定文档与测试数据中其他每个文档的相似性。然而,我无法确定如何做到这一点。
我目前使用model.docvecs.most_similar(...)
。然而,这个函数只能查找训练数据中每个文档与测试数据中特定文档的相似性。
我尝试手动比较测试数据中特定文档的推断向量与测试数据中其他每个文档的推断向量,使用model.docvecs.n_similarity(inferred_vector.tolist(), testvectors[i].tolist())
,但这返回了KeyError: "tag '-0.3502606451511383' not seen in training corpus/invalid"
,因为有些向量不在字典中。
回答:
训练一个Doc2Vec
模型会让它记录从训练数据中学到的文档向量,确实,most_similar()
只在这些向量中查找相似性。
一般来说,对训练中未包含的新文档进行任何操作都需要使用infer_vector()
。请注意,这种推断:
- 忽略新文档中任何未知的词
- 可能会因参数调整而受益,特别是对于短文档
- 目前一次只能在一个线程中处理一个文档——因此,为成千上万的文档获取推断向量实际上可能比在同样数量的文档上训练一个新模型还要慢
- 如果不采取额外的步骤,就不一定是确定的,因为底层的算法在训练/推断过程中使用了随机初始化和随机选择过程
- 只给你向量,而不将其加载到任何便于执行进一步
most_similar()
之类比较的存储对象中
另一方面,从“冻结”的模型中进行这种推断可以跨进程或机器并行化。
您提到的n_similarity()
方法实际上并不适合您的需求:它期望的是现有文档向量的查找键(’标签’)列表,而不是您提供的原始向量。
您在回答中提到的similarity_unseen_docs()
方法在某种程度上是合适的,但每次只接受一对文档,重新计算它们的向量——如果需要将单个新文档的文档向量与许多其他新文档的文档向量进行比较,这有些浪费。
您可能只想训练一个全新的模型,包括您的“训练文档”和“测试文档”。然后,所有“测试文档”的文档向量将在批量训练过程中计算并存储在模型中。这对于许多可能的应用来说是一个合适的选择,实际上,它可以以完全无监督的方式,根据仅在“测试文档”中出现的词学习有趣的关系。而且,您的问题中还没有任何部分给出不能在这里考虑它的理由。
或者,您需要对所有新的“测试文档”使用infer_vector()
,并将它们放入类似于gensim
中的各种KeyedVectors
实用类的数据结构中——在一个数组中记住所有向量,记住从文档键到向量索引的映射,并提供对一组向量的有效批量most_similar()
操作。