为什么我在 gensim 中的 Doc2Vec 模型不可重现?

时间:2021-04-20 13:00:41

标签: gensim word2vec random-seed doc2vec

我注意到我的 gensim Doc2Vec (DBOW) 模型对文档标签很敏感。我的理解是这些标签是装饰性的,因此它们不应该影响学习到的嵌入。我误解了什么吗?这是一个最小的例子:

from gensim.test.utils import common_texts
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
import numpy as np
import os
    
os.environ['PYTHONHASHSEED'] = '0'
    
reps = []
for a in [0,500]:
    documents = [TaggedDocument(doc, [i + a]) 
                 for i, doc in enumerate(common_texts)]
    model = Doc2Vec(documents, vector_size=100, window=2, min_count=0,
                    workers=1, epochs=10, dm=0, seed=0)
    reps.append(np.array([model.docvecs[k] for k in range(len(common_texts))])
    
reps[0].sum() == reps[1].sum()

最后一行返回 False。我正在使用 gensim 3.8.3 和 Python 3.5.2。更一般地说,标签的值是否有任何作用(假设它们是唯一的)?我之所以这么问是因为我发现在分类任务中为文档使用不同的标签会导致性能差异很大。

提前致谢。

3 个答案:

答案 0 :(得分:2)

首先,您的测试甚至不比较对应于相同文本的向量!

在运行 #1 中,model.docvecs[0] 中第一个文本的向量。在运行 #2 中,第一个文本的向量在 model.docvecs[1] 中。

并且,在运行 #2 中,model.docvecs[0] 处的向量只是一个随机初始化但从未训练过的向量 - 因为没有一个训练文本具有 (int) 的文档 tag 0。 (如果使用纯整数作为文档标签,Doc2Vec 将它们用作文字索引 - 可能会留下任何未使用的插槽少于分配和初始化但从未训练过的最高标签。)

由于 common_texts 只有 11 个条目,当您到达 run #12 时,all 前 11 个向量的 reps 数组中的向量与你的任何文字/

然而,即使在更正之后:

Gensim FAQ answer #11 中所述,鉴于潜在随机性的许多来源以及整个方法的模糊/近似性质,通常不应预期此算法中的确定性。如果您依赖它或测试它,您可能会做出一些毫无根据的假设。

一般来说,对这些算法的测试应该评估“在比较用途中大致等效的有用性”,而不是“相同(甚至相似)的特定向量”。例如,测试 appleorange 在彼此的最近邻排名中是否大致处于相同的位置比检查它们(有点随意的)精确向量位置甚至余弦相似性更有意义。

另外:

  • common_texts 这样的小玩具数据集不会显示算法的通常行为/好处
  • PYTHONHASHSEED 仅在启动时由 Python 解释器查询;从 Python 设置它没有任何效果。而且,它引入的那种不确定性只会在单独的解释器启动时出现:像这样在单个解释器中运行的紧密循环在任何情况下都不会受到影响。

答案 1 :(得分:1)

您是否检查过差异的大小?

刚刚运行:

delta = reps[0].sum() - reps[1].sum()

对于我运行时 -1.2598932e-05 的汇总差异结果。

维度比较:

 eps = 10**-4
 over = (np.abs(diff) <= eps).all()

在绝大多数运行中返回 True,这意味着考虑到计算的复杂性,您将获得可重现的结果。

我会责怪 numerical stability 的计算或不受控制的随机性。尽管您确实尝试控制随机种子,但 NumPy 中存在不同的随机种子,而 random 标准库中的随机种子也不同,因此您无法控制所有随机源。这也会对结果产生影响,但我没有检查 gensim 中的实际实现及其依赖项。

答案 2 :(得分:0)

改变

import os
    
os.environ['PYTHONHASHSEED'] = '0'

import os
import sys
hashseed = os.getenv('PYTHONHASHSEED')
if not hashseed:
    os.environ['PYTHONHASHSEED'] = '0'
    os.execv(sys.executable, [sys.executable] + sys.argv)
相关问题