使用tf.set_random_seed在Tensorflow中可重现的结果

Meh*_*aie 10 python reproducible-research random-seed tensorflow

我正在尝试生成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)
Run Code Online (Sandbox Code Playgroud)

这是代码的输出:

# 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]
Run Code Online (Sandbox Code Playgroud)

我想要类似的东西

[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 ]
Run Code Online (Sandbox Code Playgroud)

更新1:的确,我将种子初始化程序放在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 .....
 .
 .
 .
Run Code Online (Sandbox Code Playgroud)

P-G*_*-Gn 11

在tensorflow中,随机操作依赖于两个不同的种子:由设置的全局种子tf.set_random_seed和作为操作的参数提供的操作种子。您将在文档中找到有关它们之间的关系的更多详细信息。

每个随机运算都有一个不同的种子,因为每个随机运算都会维护自己的内部状态以生成伪随机数。使每个随机生成器保持其自己的状态的原因是要进行更改,因为它们共享相同的状态,然后在图形中的某个位置添加新的随机生成器会更改所有其他生成器产生的值,从而破坏了使用种子。

现在,为什么我们要有全球种子种子种子的双重系统?好吧,实际上并不需要全局种子。这样做是为了方便:它允许立即将所有随机op种子设置为不同的确定性(如果未知)值,而不必详尽地遍历所有这些种子。

根据文档,现在设置了全局种子但未设置op种子时,

系统确定性地选择一个操作种子以及一个图形级种子,以便获得唯一的随机序列。

更准确地说,提供的种子是当前图中已创建的最后一个操作的ID。因此,全局播种的随机操作对图形的变化极为敏感,尤其是对之前创建的图形。

例如,

import tensorflow as tf
tf.set_random_seed(1234)
generate = tf.random_uniform(())
with tf.Session() as sess:
  print(generate.eval())
  # 0.96046877
Run Code Online (Sandbox Code Playgroud)

现在,如果我们之前创建一个节点,结果将发生变化:

import tensorflow as tf
tf.set_random_seed(1234)
tf.zeros(()) # new op added before 
generate = tf.random_uniform(())
with tf.Session() as sess:
  print(generate.eval())
  # 0.29252338
Run Code Online (Sandbox Code Playgroud)

但是,如果在之后创建节点,则不会影响操作种子:

import tensorflow as tf
tf.set_random_seed(1234)
generate = tf.random_uniform(())
tf.zeros(()) # new op added after
with tf.Session() as sess:
  print(generate.eval())
  # 0.96046877
Run Code Online (Sandbox Code Playgroud)

显然,就像您的情况一样,如果您生成多个操作,它们将具有不同的种子:

import tensorflow as tf
tf.set_random_seed(1234)
gen1 = tf.random_uniform(())
gen2 = tf.random_uniform(())
with tf.Session() as sess:
  print(gen1.eval())
  print(gen2.eval())
  # 0.96046877
  # 0.85591054
Run Code Online (Sandbox Code Playgroud)

作为一种好奇心,并验证的事实,种子只需在图中最后使用的ID,你可以对齐的种子gen2,以gen1

import tensorflow as tf
tf.set_random_seed(1234)
gen1 = tf.random_uniform(())
# 4 operations seems to be created after seed has been picked
seed = tf.get_default_graph()._last_id - 4
gen2 = tf.random_uniform((), seed=seed)
with tf.Session() as sess:
  print(gen1.eval())
  print(gen2.eval())
  # 0.96046877
  # 0.96046877
Run Code Online (Sandbox Code Playgroud)

显然,这不应通过代码审查。


mx_*_*muc 6

对于Tensorflow 2.0 tf.random.set_random_seed(seed)更改为tf.random.set_seed(seed)

参见TF文档:

  • r2.0:https://www.tensorflow.org/versions/r2.0/api_docs/python/tf/random/set_seed
  • r1.13:https://www.tensorflow.org/versions/r1.13/api_docs/python/tf/random/set_random_seed


Joh*_*Doe 6

晚会晚了,但是随机数生成器已经过大修(请参阅https://github.com/tensorflow/community/pull/38以总结该过程)并且tf.random.experimental.Generator该类现在提供了所需的功能。

从 TF 1.14 开始(包括 TF 2.0),您可以为生成器播种并获得完全相同的随机数,而不管会话、平台甚至架构如何。

import tensorflow as tf

rng = tf.random.experimental.Generator.from_seed(1234)
rng.uniform((), 5, 10, tf.int64)  # draw a random scalar (0-D tensor) between 5 and 10
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅文档:

要解决您的特定问题(我使用的是 TF 2.0):

for i in range(3):
  b = tf.random.uniform((10,), 0, 10, seed=1234)
  print(b)
Run Code Online (Sandbox Code Playgroud)

tf.Tensor(
[2.7339518  9.339194   5.2865124  8.912003   8.402512   0.53086996
 4.385383   4.8005686  2.2077608  2.1795273 ], shape=(10,), dtype=float32)
tf.Tensor(
[9.668942   3.4503186  7.4577675  2.9200733  1.8064988  6.1576104
 3.9958012  1.889689   3.8289428  0.36031008], shape=(10,), dtype=float32)
tf.Tensor(
[8.019657  4.895439  5.90925   2.418766  4.524292  7.901089  9.702316
 5.1606855 9.744821  2.4418736], shape=(10,), dtype=float32)
Run Code Online (Sandbox Code Playgroud)

而这

for i in range(3):
  rng = tf.random.experimental.Generator.from_seed(1234)
  b = rng.uniform((10,), 0, 10)
  print(b)
Run Code Online (Sandbox Code Playgroud)

给你想要的:

tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
tf.Tensor(
[3.581475  1.132276  5.6670904 6.712369  3.2565057 1.7095459 8.468903
 6.2697005 1.0973608 2.7732193], shape=(10,), dtype=float32)
Run Code Online (Sandbox Code Playgroud)


Pat*_*wie 5

有一个相关的GitHub 问题。但在您的情况下,请参阅以下文档tf.set_random_seed

设置图级随机种子。

您可能希望使用相同的图形和相同的操作在不同的会话中获得相同的随机数。

import tensorflow as tf

tf.set_random_seed(1234)
generate = tf.random_uniform((10,), 0, 10)
tf.get_default_graph().finalize() # something everybody tends to forget

for i in range(3):
    with tf.Session() as sess:
        b = sess.run(generate)
        print(b)
Run Code Online (Sandbox Code Playgroud)

[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 ]
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您在同一个图中创建了不同的操作。