numpy.random.RandomState() 是否在调用 rand() 时自动调用?
Is numpy.random.RandomState() automatically called whenever rand() is called?
像C++这样的语言要求程序员设置随机数生成器的种子,否则它的输出总是一样的。但是,像 numpy 这样的库不需要您手动初始化种子。
例如,代码如下:
from numpy.random import rand
rand()
每次都给出不同的结果。
这是否意味着每次调用 rand
时都会调用 numpy.random.RandomState(seed=None)
?
Does that mean numpy.random.RandomState(seed=None)
is called every time you call rand?
不,这意味着 RandomState
在启动时被播种一次。如果每次调用 rand
时都重新播种,那么将无法明确地 询问 可重复的模式。
Python stdlib 的 random
模块也是如此。
而且,不管你怎么说 C++,对于 C++ stdlib 的 <random>
函数来说,也是正确的。
所有这些文件表明,如果您什么都不做,默认种子来自系统时间或系统熵生成器(如大多数 *nix 系统上的 /dev/random
)。
C 的 rand
不是这种情况(在 C++ 中仍然存在,尽管您应该将其视为已弃用*),但这只是因为 C 去特意要求启动必须执行与调用 srand(1)
.
相同的操作
如果您对 "once at startup" 在 NumPy 中的工作原理感兴趣:
- 在
numpy.random
模块的顶层(当您第一次在您的代码中 import numpy.random
或 from numpy.random import something
时,它会得到 运行),它构建了一个全局 RandomState
,使用默认参数(意思是 seed=None
)。
RandomState
的初始化程序只是将 seed
参数传递给 seed
方法。
RandomState.seed
,当使用 None
调用时,使用适合您的平台的系统熵源(如 /dev/urandom
)。
- 当您调用顶级
rand
时,它使用全局 RandomState
。
* 不是因为这个问题;很容易记住在程序开始时调用 srand
。但是一个 PRNG 明确地不保证循环长度长于 32767,无偏分布等对几乎任何事情来说都是一个坏主意......
numpy.random
模块类似于 Python 标准库中的 random
模块,因为 numpy.random
中的函数是隐藏生成器对象的绑定方法,导入模块时实例化。这个隐藏的 numpy.random.RandomState
实例目前存在于 np.random.mtrand._rand
中(尽管你不应该依赖它在未来版本的 numpy 中总是存在):
print(np.random.rand)
# <built-in method rand of mtrand.RandomState object at 0x7f50ced03660>
# note the same memory address of the RandomState object:
print(np.random.mtrand._rand)
# <mtrand.RandomState object at 0x7f50ced03660>
当您导入模块时,隐藏的 RandomState
实例只会被播种 一次 (除非您随后使用 np.random.seed()
显式设置种子)。如果每次调用 rand()
时都选择了一个新种子,那么将无法创建可重现的伪随机数序列。
情况看起来像这样:
# implicit RandomState created and seeded
from numpy import random
# # we could subsequently re-seed the hidden RandomState, e.g.:
# random.seed(None)
# different random variates
r1 = random.rand(1)
r2 = random.rand(1)
r3 = random.rand(1)
# ...
自动播种相当于 np.random.RandomState(None)
,它使用一些依赖于平台的随机源(通常是 /dev/urandom
on *nix)来设置种子。
像C++这样的语言要求程序员设置随机数生成器的种子,否则它的输出总是一样的。但是,像 numpy 这样的库不需要您手动初始化种子。
例如,代码如下:
from numpy.random import rand
rand()
每次都给出不同的结果。
这是否意味着每次调用 rand
时都会调用 numpy.random.RandomState(seed=None)
?
Does that mean
numpy.random.RandomState(seed=None)
is called every time you call rand?
不,这意味着 RandomState
在启动时被播种一次。如果每次调用 rand
时都重新播种,那么将无法明确地 询问 可重复的模式。
Python stdlib 的 random
模块也是如此。
而且,不管你怎么说 C++,对于 C++ stdlib 的 <random>
函数来说,也是正确的。
所有这些文件表明,如果您什么都不做,默认种子来自系统时间或系统熵生成器(如大多数 *nix 系统上的 /dev/random
)。
C 的 rand
不是这种情况(在 C++ 中仍然存在,尽管您应该将其视为已弃用*),但这只是因为 C 去特意要求启动必须执行与调用 srand(1)
.
如果您对 "once at startup" 在 NumPy 中的工作原理感兴趣:
- 在
numpy.random
模块的顶层(当您第一次在您的代码中import numpy.random
或from numpy.random import something
时,它会得到 运行),它构建了一个全局RandomState
,使用默认参数(意思是seed=None
)。 RandomState
的初始化程序只是将seed
参数传递给seed
方法。RandomState.seed
,当使用None
调用时,使用适合您的平台的系统熵源(如/dev/urandom
)。- 当您调用顶级
rand
时,它使用全局RandomState
。
* 不是因为这个问题;很容易记住在程序开始时调用 srand
。但是一个 PRNG 明确地不保证循环长度长于 32767,无偏分布等对几乎任何事情来说都是一个坏主意......
numpy.random
模块类似于 Python 标准库中的 random
模块,因为 numpy.random
中的函数是隐藏生成器对象的绑定方法,导入模块时实例化。这个隐藏的 numpy.random.RandomState
实例目前存在于 np.random.mtrand._rand
中(尽管你不应该依赖它在未来版本的 numpy 中总是存在):
print(np.random.rand)
# <built-in method rand of mtrand.RandomState object at 0x7f50ced03660>
# note the same memory address of the RandomState object:
print(np.random.mtrand._rand)
# <mtrand.RandomState object at 0x7f50ced03660>
当您导入模块时,隐藏的 RandomState
实例只会被播种 一次 (除非您随后使用 np.random.seed()
显式设置种子)。如果每次调用 rand()
时都选择了一个新种子,那么将无法创建可重现的伪随机数序列。
情况看起来像这样:
# implicit RandomState created and seeded
from numpy import random
# # we could subsequently re-seed the hidden RandomState, e.g.:
# random.seed(None)
# different random variates
r1 = random.rand(1)
r2 = random.rand(1)
r3 = random.rand(1)
# ...
自动播种相当于 np.random.RandomState(None)
,它使用一些依赖于平台的随机源(通常是 /dev/urandom
on *nix)来设置种子。