我正在尝试尽可能仔细地保留随机数生成器的序列。然而,以下代码显示当前随机种子的进展似乎存在一些问题。 我不明白为什么前两个循环对 random_arr 给出相同的答案。
import numpy as np
def train_test_split(X,rint):
print('rint = ',rint)
return X
def index_split(X,rng):
X_train = train_test_split(X, rng.integers(65536))
return X_train
def new_rng():
rng = np.random.default_rng(seed)
return rng
seed = 1234
n_params = 4
extranls = [0, 1, 2]
X = [0]
print('np.__version__ = ',np.__version__)
for ind, extran in enumerate(extranls):
print('\n\n----------')
print('rng #: ',ind)
RNG = new_rng()
X_train = index_split(X, RNG)
for i in range(extran):
print('Extra: rng.integers(65536) = ',RNG.integers(65536))
initial_parameters = np.zeros(n_params, dtype=np.float32)
random_arr = RNG.random(n_params)
print('extran = ',extran)
print('random_arr is ',random_arr)
#
# np.__version__ = 1.26.4
#
#
# ----------
# rng #: 0
# rint = 64182
# extran = 0
# random_arr is [0.38019574 0.92324623 0.26169242 0.31909706]
#
#
# ----------
# rng #: 1
# rint = 64182
# Extra: rng.integers(65536) = 64008
# extran = 1
# random_arr is [0.38019574 0.92324623 0.26169242 0.31909706]
#
#
# ----------
# rng #: 2
# rint = 64182
# Extra: rng.integers(65536) = 64008
# Extra: rng.integers(65536) = 64745
# extran = 2
# random_arr is [0.92324623 0.26169242 0.31909706 0.11809123]
第一个和第二个循环给出 [0.38019574 0.92324623 0.26169242 0.31909706]
默认 PCG64 BitGenerator 底层的算法生成 64 位值,但生成 0 到 65535 之间的数字不需要 64 位随机值。 大多数对随机整数的请求不需要 64 位随机值。所以,NumPy 有一个优化。为了满足 32 位就足够的请求,PCG64 BitGenerator 会分割其底层 64 位输出,每次生成 2 个 32 位值。
在
RNG.integers(65536)
内调用 index_split
会生成 2 个 32 位值,使用其中一个生成您请求的输出,并缓存另一个。再次调用它会使用缓存的值,而不推进底层状态。调用 RNG.random(n_params)
无法使用缓存,因此无论您在 index_split
之后立即调用它,还是在进行一次额外的 RNG.integers(65536)
调用之后,其行为都是相同的。
您可以在 NumPy 源存储库中查看负责的代码,特别是here、here和here。
请注意,这是所有实现细节。文档提到这种事情可能会发生,但不承诺它会发生: