像C ++这样的语言要求程序员设置随机数生成器的种子,否则它的输出将始终相同。但是,像numpy这样的库不需要您手动初始化种子。
例如,代码如下:
from numpy.random import rand
rand()
每次给出不同的结果。
这是否意味着每次致电numpy.random.RandomState(seed=None)
时都会调用rand
?
答案 0 :(得分:4)
这是否意味着每次调用rand时都会调用
numpy.random.RandomState(seed=None)
?
不,这意味着RandomState
在启动时播种一次。如果每次调用rand
时重新播种,那么就无法明确地询问是否有可重复的模式。
Python stdlib的random
模块也是如此。
而且,尽管你对C ++有什么看法,但对于C ++ stdlib的<random>
函数,它的也是。
所有这些都证明默认种子,如果你不做任何事情,来自系统时间或系统熵生成器(如大多数* nix系统上的/dev/random
)。
对于C rand
来说情况并非如此(C ++中仍然存在这种情况,尽管您应该将其视为已弃用的 * ),但仅仅因为C消失了要求启动必须相当于调用srand(1)
。
如果您对&#34;启动时的确切感兴趣&#34;适用于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,无偏差分布等等几乎对任何事情都是一个坏主意......
答案 1 :(得分:2)
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)
,它使用一些与平台相关的随机源(通常在* nix上/dev/urandom
)来设置种子。