我正在尝试根据here中的代码评估doc2vec模型。基本上,我想知道推断文档的百分比与其自身最相似。这是我当前的代码:
for doc_id, doc in enumerate(cur.execute('SELECT Text FROM Patents')):
docs += 1
doc = clean_text(doc)
inferred_vector = model.infer_vector(doc)
sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
rank = [docid for docid, sim in sims].index(doc_id)
ranks.append(rank)
counter = collections.Counter(ranks)
accuracy = counter[0] / docs
此代码可与较小的数据集完美配合。但是,由于我有一个包含数百万个文档的巨大文件,因此此代码变得太慢,需要花费数月的时间进行计算。我分析了我的代码,大部分时间被以下行占用:sims = model.docvecs.most_similar([inferred_vector], topn=len(model.docvecs))
。
如果我没记错的话,那就必须将每个文档与每个其他文档进行度量。我认为,如果我将其更改为topn=1
,则可能会大大减少计算时间,因为我唯一想知道的是最相似的文档本身就是不是。这样做基本上会占用每个文档(即inferred_vector
),测量其最相似的文档(即topn=1
),然后我看看它是否本身。我该如何实施?欢迎任何帮助或想法。
答案 0 :(得分:0)
要让most_similar()
仅返回最相似的单个文档,就像指定topn=1
一样简单。
但是,要知道数百万个文档中的哪一个与单个目标向量最相似,则必须计算与 all 个候选者的相似性。 (即使遗漏了一个文档,也可能是排名最高的文档!)
确保绝对不会发生虚拟内存交换将有助于确保在RAM中都尽可能快地进行暴力比较-但是对于数百万的文档,这仍然很耗时。
您要尝试的是一个非常简单的“自检”,即训练是否导致了自洽的模型:文档的重新推论是否创建了一个“非常接近”剩下的相同doc-vector的矢量从批量培训结束。失败将表明在文档准备或培训中存在一些大问题,但这并不是衡量模型在任何实际任务中的“准确性”的真实指标,并且最好根据您的预期用途评估模型的价值。
此外,由于此“重推自检”仅是粗略的健全性检查,因此对于每一个文档都没有真正的需要。挑选一千个(或一万个或其他任何东西)随机文档将使您对大多数重新推断的向量是否具有这种质量有代表性。
类似地,您可以简单地检查重新推断的向量与同一文档ID的单个模型内向量的相似性,并检查它们是否“足够相似”。 (这将更快,但是也可以仅是随机抽取一个文档样本来完成。)“足够相似”没有神奇的适当门槛。您必须选择一个看起来与您的其他目标匹配的目标。例如,使用scikit-learn
的{{1}}比较两个向量:
cosine_similarity()
(您必须将列表中的单个向量包装为from sklearn.metrics.pairwise import cosine_similarity
# ...
inferred_vector = model.infer_vector(doc_words)
looked_up_vector = model.dv[doc_id]
self_similarity = cosine_similarity([inferred_vector], [looked_up_vector])[0]
# then check that value against some threshold
的参数,然后访问返回值的第0个元素,因为它通常设计为可用于较大的向量列表。)
通过这种计算,例如,您将不知道其他一些存储的文档向量是否更接近您的推断目标-但这可能并不那么重要。这些文档可能真的很相似!并且,如果原始的“最接近自己的”自检会在训练中出现重大缺陷而失败,那么即使是训练有素的模型也可能会遇到某些情况,即自然模型抖动会阻止每个文档的“最接近自身”。 (如果在相同数量的维中有更多文档,或者某些语料库中有很多非常相似的文档,这将变得更加普遍……但这并不是任何模型问题的关注指标。)