确保 gensim 为相同数据的不同运行生成相同的 Word2Vec 模型

Posted

技术标签:

【中文标题】确保 gensim 为相同数据的不同运行生成相同的 Word2Vec 模型【英文标题】:Ensure the gensim generate the same Word2Vec model for different runs on the same data 【发布时间】:2016-04-22 06:08:38 【问题描述】:

在LDA model generates different topics everytime i train on the same corpus 中,通过设置np.random.seed(0),LDA 模型将始终以完全相同的方式进行初始化和训练。

gensim 的 Word2Vec 模型是否相同?通过将随机种子设置为常数,在同一数据集上的不同运行会产生相同的模型吗?

但奇怪的是,它已经在不同的情况下给了我相同的向量。

>>> from nltk.corpus import brown
>>> from gensim.models import Word2Vec
>>> sentences = brown.sents()[:100]
>>> model = Word2Vec(sentences, size=10, window=5, min_count=5, workers=4)
>>> model[word0]
array([ 0.04985042,  0.02882229, -0.03625415, -0.03165979,  0.06049283,
        0.01207791,  0.04722737,  0.01984878, -0.03026265,  0.04485954], dtype=float32)
>>> model = Word2Vec(sentences, size=10, window=5, min_count=5, workers=4)
>>> model[word0]
array([ 0.04985042,  0.02882229, -0.03625415, -0.03165979,  0.06049283,
        0.01207791,  0.04722737,  0.01984878, -0.03026265,  0.04485954], dtype=float32)
>>> model = Word2Vec(sentences, size=20, window=5, min_count=5, workers=4)
>>> model[word0]
array([ 0.02596745,  0.01475067, -0.01839622, -0.01587902,  0.03079717,
        0.00586761,  0.02367715,  0.00930568, -0.01521437,  0.02213679,
        0.01043982, -0.00625582,  0.00173071, -0.00235749,  0.01309298,
        0.00710233, -0.02270884, -0.01477827,  0.01166443,  0.00283862], dtype=float32)
>>> model = Word2Vec(sentences, size=20, window=5, min_count=5, workers=4)
>>> model[word0]
array([ 0.02596745,  0.01475067, -0.01839622, -0.01587902,  0.03079717,
        0.00586761,  0.02367715,  0.00930568, -0.01521437,  0.02213679,
        0.01043982, -0.00625582,  0.00173071, -0.00235749,  0.01309298,
        0.00710233, -0.02270884, -0.01477827,  0.01166443,  0.00283862], dtype=float32)
>>> exit()
alvas@ubi:~$ python
Python 2.7.11 (default, Dec 15 2015, 16:46:19) 
[GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from nltk.corpus import brown
>>> from gensim.models import Word2Vec
>>> sentences = brown.sents()[:100]
>>> model = Word2Vec(sentences, size=10, window=5, min_count=5, workers=4)
>>> word0 = sentences[0][0]
>>> model[word0]
array([ 0.04985042,  0.02882229, -0.03625415, -0.03165979,  0.06049283,
        0.01207791,  0.04722737,  0.01984878, -0.03026265,  0.04485954], dtype=float32)
>>> model = Word2Vec(sentences, size=20, window=5, min_count=5, workers=4)
>>> model[word0]
array([ 0.02596745,  0.01475067, -0.01839622, -0.01587902,  0.03079717,
        0.00586761,  0.02367715,  0.00930568, -0.01521437,  0.02213679,
        0.01043982, -0.00625582,  0.00173071, -0.00235749,  0.01309298,
        0.00710233, -0.02270884, -0.01477827,  0.01166443,  0.00283862], dtype=float32)

那么默认的随机种子是固定的吗?如果是,那么默认的随机种子数是多少?还是因为我正在测试一个小数据集?

如果随机种子确实是固定的,并且对相同数据的不同运行返回相同的向量,那么将非常感谢提供指向规范代码或文档的链接。

【问题讨论】:

【参考方案1】:

根据 Gensim 的文档,要执行完全确定性可重现的运行,您必须还将模型限制为单个工作线程,以消除 OS 线程调度的排序抖动。

对代码进行简单的参数编辑就可以解决问题。

model = Word2Vec(sentences, size=10, window=5, min_count=5, workers=1)

【讨论】:

【参考方案2】:

是的,默认随机种子固定为1,正如作者在https://radimrehurek.com/gensim/models/word2vec.html 中所述。每个单词的向量都使用单词 + str(seed) 连接的哈希进行初始化。

然而,使用的散列函数是 Python 的基本内置散列函数,如果两台机器不同时会产生不同的结果

32 位与 64 位,reference python 版本,reference 不同的操作系统/解释器,reference1,reference2

以上列表并不详尽。它是否涵盖了您的问题?

编辑

如果要保证一致性,可以在word2vec中提供自己的哈希函数作为参数

一个非常简单(但很糟糕)的例子是:

def hash(astring):
   return ord(astring[0])

model = Word2Vec(sentences, size=10, window=5, min_count=5, workers=4, hashfxn=hash)

print model[sentences[0][0]]

【讨论】:

我试过这个。仍然给我不同的结果【参考方案3】:

只是对随机性的评论。

如果正在使用 gensim 的 W2V 模型并且使用 Python 版本 >= 3.3,请记住默认情况下会启用哈希随机化。如果您正在寻求两次执行之间的一致性,请确保设置 PYTHONHASHSEED 环境变量。例如。像这样运行代码时 PYTHONHASHSEED=123 python3 mycode.py,下次生成模型时(使用相同的哈希种子),它将与先前生成的模型相同(前提是遵循所有其他随机性控制步骤,如上所述 - 随机状态和单个工作人员)。 详情请参阅gensim's W2V source 和Python docs。

【讨论】:

【参考方案4】:

对于完全确定性可重现的运行,除了定义种子之外,您还必须将模型限制为单个工作线程 (workers=1),以消除操作系统线程调度的顺序抖动。 (在 Python 3 中,解释器启动之间的可重复性还需要使用 PYTHONHASHSEED 环境变量来控制哈希随机化)。

def hash(astring):
  return ord(astring[0])

model = gensim.models.Word2Vec (texts, workers=1, seed=1,hashfxn=hash)

【讨论】:

【参考方案5】:

你的问题确实是一个小数据集:只有 100 句话。

注意Gensim FAQ 所说的内容:

[因为随机性是 Word2Vec 和类似模型的一部分],可以预期模型会因运行而异,即使是在相同数据上进行训练。任何词向量或文档向量都没有一个“正确的位置”可以结束:只有在同一模型内共同训练的其他向量的距离和方向越来越有用的位置。 [...]

合适的训练参数应该产生大致相同有用的模型,从运行到运行,彼此。测试和评估过程应该容忍向量位置的任何变化,以及模型整体效用中的小“抖动”,这是由固有的算法随机性引起的。 (如果每次运行时观察到的质量差异很大,可能还有其他问题:数据太少、参数调整不佳或评估方法中的错误/弱点。)

您可以尝试强制确定性[.]但是[...]您会掩盖底层算法的固有随机性/近似性[.]最好容忍一点抖动,并使用过度抖动作为指标数据或模型设置中其他地方的问题 - 而不是强加肤浅的确定性。

【讨论】:

以上是关于确保 gensim 为相同数据的不同运行生成相同的 Word2Vec 模型的主要内容,如果未能解决你的问题,请参考以下文章

带有 ggplots 的 for 循环生成具有相同值但标题不同的图形

保存的相同数据生成不同的图像 - Python

不同的服务器使用相同的参数生成不同的 JWT 令牌

如何保存 Gensim LDA 模型列表?

提交多个具有相同代码库的 iOS 应用

有没有办法确保浮点的输出在不同的操作系统中相同?