You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

np.random.integers()如何改变RNG种子?为何前两次循环随机数组一致?

问题:Numpy随机数生成器序列保留异常分析

我正尝试严格保留随机数生成器(RNG)的序列,但以下代码显示随机种子的推进存在问题,无法理解为何前两次循环的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]

问题原因

问题出在Numpy默认RNG(基于PCG64算法)的位消耗机制:

  • rng.integers(65536)生成16位整数时,仅从当前64位随机数块中截取16位,剩余48位会被缓存。
  • rng.random()生成浮点数时,只会使用完整的64位块,不会利用缓存的剩余位,而是直接生成新的64位块。
  • 前两次循环中,调用integers后缓存的剩余位都不足以凑成完整64位块,因此random()均从同一个新块起始位置生成数据,导致结果完全相同。
  • 第三次循环中,累计调用integers的次数触发了生成器状态的跨块推进,random()才开始读取后续块的数据。

解决方法

要严格控制RNG序列推进,需确保每次随机数调用消耗相同单位的生成器状态,推荐以下方式:

方法:统一使用64位操作生成整数

将rng.integers(65536)替换为消耗完整64位块的生成方式,确保每次调用都推进一个块:

修改后的完整代码

import numpy as np

def train_test_split(X,rint):
    print('rint = ',rint)
    return X

def index_split(X,rng):
    rint = rng.integers(0, 2**64) % 65536
    X_train = train_test_split(X, rint)
    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):
        rint = RNG.integers(0, 2**64) % 65536
        print('Extra: rng.integers(65536) = ',rint)

    initial_parameters = np.zeros(n_params, dtype=np.float32)
    random_arr = RNG.random(n_params)
    print('extran = ',extran)
    print('random_arr is ',random_arr)

修改后,random_arr会随着extran的增加连续推进,不会出现重复结果。

内容的提问来源于stack exchange,提问作者Ed Gan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 01:42:04