我正在尝试生成N组独立的随机数。我有一个简单的代码,显示了3组10个随机数的问题。我注意到,即使我使用tf.set_random_seed
来设置种子,不同运行的结果看起来并不一样。任何帮助或评论都非常感谢。
(py3p6) bash-3.2$ cat test.py
import tensorflow as tf
for i in range(3):
tf.set_random_seed(1234)
generate = tf.random_uniform((10,), 0, 10)
with tf.Session() as sess:
b = sess.run(generate)
print(b)
下面是代码的输出:
# output :
[9.604688 5.811516 6.4159 9.621765 0.5434954 4.1893444 5.8865128
7.9785547 8.296125 8.388672 ]
[8.559105 3.2390785 6.447526 8.316823 1.6297233 1.4103293 2.647568
2.954973 6.5975866 7.494894 ]
[2.0277488 6.6134906 0.7579422 4.6359386 6.97507 3.3192968 2.866236
2.2205782 6.7940736 7.2391043]
"我想要的东西"
[9.604688 5.811516 6.4159 9.621765 0.5434954 4.1893444 5.8865128
7.9785547 8.296125 8.388672 ]
[9.604688 5.811516 6.4159 9.621765 0.5434954 4.1893444 5.8865128
7.9785547 8.296125 8.388672 ]
[9.604688 5.811516 6.4159 9.621765 0.5434954 4.1893444 5.8865128
7.9785547 8.296125 8.388672 ]
**更新1:**事实上,我之所以把seed初始化器放在for循环中,是因为我想用不同的方式设置它们(例如,把它想象成不同的MCMC运行)。这是我的代码,它完成了这项工作,但我不确定它是否有效。基本上,我生成了一对0和2^32-1之间的随机种子,并在每次运行中改变种子。任何帮助或评论,使它更有效的内存/RAM是非常感谢的。
import numpy as np
import tensorflow as tf
global_seed = 42
N_chains = 5
np.random.seed(global_seed)
seeds = np.random.randint(0, 4294967295, size=N_chains)
for i in range(N_chains):
tf.set_random_seed(seeds[i])
.... some stuff ....
kernel_initializer = tf.random_normal_initializer(seed=seeds[i])
.... some stuff
with tf.Session() as sess:
.... some stuff .....
.
.
.
8条答案
按热度按时间omtl5h9j1#
在tensorflow 中,随机操作依赖于两个不同的种子:一个全局种子,由
tf.set_random_seed
设置,一个操作种子,作为操作的参数提供。您将找到关于它们如何关联in the docs的更多详细信息。每个随机操作都有不同的种子,因为每个随机操作都维护自己的内部状态以生成伪随机数。让每个随机生成器维护自己的状态的原因是为了能够稳健地进行更改:如果它们共享相同的状态,那么在图中的某个地方添加一个新的随机生成器将改变所有其他生成器生成的值,从而使使用种子的目的落空。
那么,为什么我们要有全局 * 和 * per-op种子的双重系统呢?实际上,全局种子不是必需的。它是为了方便:它允许一次性将所有随机操作种子设置为不同的确定性(如果未知)值,而不必彻底检查所有操作种子。
现在,当设置了全局种子而不是操作种子时,根据文档,
系统确定性地结合图级种子来挑选操作种子,使得它获得唯一的随机序列。
更准确地说,所提供的种子是在当前图形中创建的最后一个操作的ID。因此,全局取种随机操作对图形中的变化极其敏感,尤其是对在其之前创建的那些操作。
例如,
现在如果我们之前创建了一个节点,结果会发生变化:
但是,如果在之后创建节点,则不会影响操作种子:
显然,就像您的情况一样,如果生成多个操作,它们将具有不同的种子:
出于好奇,为了验证seed仅仅是图中最后使用的id这一事实,您可以将seed
gen2
与gen1
对齐显然,这不应该通过代码评审。
5anewei62#
对于tensorflow 2.0,
tf.random.set_random_seed(seed)
更改为tf.random.set_seed(seed)
。参见TF文件:
2eafrhcq3#
然而,随机数生成器已经被彻底检修(请参见https://github.com/tensorflow/community/pull/38以总结该过程),
tf.random.experimental.Generator
类现在提供了所需的功能。从TF 1.14开始(包括TF 2.0),您可以为生成器设定种子,并获得完全相同的随机数,而不管会话、平台甚至架构如何。
有关详细信息,请参阅文档:
为了回答您的特定问题(我使用的是TF 2.0):
给予
而这
给你想要的:
qco9c6ql4#
有一个相关的GitHub issue,但是在您的情况下,请参考
tf.set_random_seed
的文档:设置图形级随机种子。
您可能希望使用相同的图和相同的操作,在 * 不同的 * 会话中获得相同的随机数。
给予
在您的示例中,您在同一个图表中创建了不同的操作。
o2g1uqev5#
添加此答案以供参考:结果可重现的问题可能不是直接来自TensorFlow,而是来自底层平台。
如果在Nvidia GPU上运行,Nvidia有一个库可以帮助获得确定性结果:tensorflow-determinism
你可以这样使用它:
仍然建议添加以下字段:
对于Tensorflow〈2.1,添加上述内容和以下内容:
uwopmtnx6#
在不同的运行中得到不同的结果,因为在图中定义了三个
generate
变量(操作),而不是一个。这是因为在for循环中有生成操作,这导致了三个操作。(Tensor("random_uniform:0"), Tensor("random_uniform_1:0"), Tensor("random_uniform_2:0"))
。只需在for循环中执行print(generate)
。您将看到如上所述的三个不同的操作。tf.set_random_seed
在图形级别设置种子。因此,它确定性地为图形中的每个操作选择种子。因此,三个generate
操作在每次运行时都被分配了相同的三个种子。这就是为什么每次运行时,您会看到所有三个变量对应的相同结果。有关设置随机种子的详细信息,请参阅this。因此,如果希望每次运行会话时都得到相同的结果,可以执行以下操作:
但是为什么要创建
n
会话呢?理想情况下,您应该创建一个会话,然后运行会话n
次。不需要为每次运行创建一个新会话,每次它尝试将图形中的变量和操作放置到设备(GPU或CPU)。zpjtge227#
我注意到你想要有3个不同的向量包含随机数。每次你想运行代码时,你希望这3个向量包含的随机数与第一次相同。这种方法是完全可以解释的,为什么需要4个相同的随机向量。你想有4个随机向量彼此。
定义图表操作时,可以设置两种类型的种子:图表级别的粒度,由tf.set_random_seed设置,操作级别的种子,放置在初始化器变量中由于粒度在图表级别,每次结果都不一样。必须使用tf.InteractiveSession()
得到4个随机数向量,包含0到10的数字。
vi4fp9gy8#
这对我很有效
您可以找到更多here