【问题标题】:python vs octave random generatorpython vs 八度随机生成器
【发布时间】:2012-11-23 23:29:57
【问题描述】:

更具体地说,numpy:

In [24]: a=np.random.RandomState(4)
In [25]: a.rand()
Out[25]: 0.9670298390136767
In [26]: a.get_state()
Out[26]: 
('MT19937',
 array([1248735455, ..., 1532921051], dtype=uint32),
 2,0,0.0)

八度:

octave:17> rand('state',4)
octave:18> rand()
ans =  0.23605
octave:19> rand('seed',4)
octave:20> rand()
ans =  0.12852

Octave 声称执行相同的算法(Mersenne Twister,周期为 2^{19937-1})

有人知道为什么会有差异吗?

【问题讨论】:

  • 您是否尝试获得相同的随机数字?
  • 是的,最好生成相同的(大)组“随机”数字进行调试

标签: python random numpy octave


【解决方案1】:

看起来 numpy 正在返回原始随机整数,而 octave 正在将它们标准化为 0 到 1.0 之间的浮点数。

【讨论】:

  • 不,在第一个 sn-p a.rand() 返回一个float(其中is normalized between 0 and 1.0)。您看到的那些整数是 RNG 内部状态的一部分。
【解决方案2】:

如果您查看details of the Mersenne Twister algorithm,有很多参数会影响实际产生的数字。我不认为 Python 和 Octave 试图产生相同的数字序列。

【讨论】:

  • 很公平。设置或至少获取默认参数会很好。我对八度音程发生的情况并不乐观。谢谢
  • 一个更大的问题是:为什么要它们产生相同的序列?
  • 是的,完全是@mmgp。这是一个非常好的构造,能够模拟随机序列,但在调试期间对其进行控制以比较结果。
  • 这不太对。我几乎可以肯定算法本身在这两种情况下都是相同的。大家只要拿到MT19937的官方代号就可以使用了。可能不同的是每个实现如何采用种子整数并将其扩展为初始的 624 字状态。如果你复制了最初的 624 字状态,我相当肯定你会得到相同的数字。当然,前提是 [0..1] 浮点标准化步骤是相同的​​。
  • @RobertKern:确实,种子->初始状态映射可能是不同的“算法细节”。
【解决方案3】:

不幸的是,Octave 中的 MT19937 生成器不允许您像 np.random.RandomState(4) 那样使用单个 32 位整数对其进行初始化。如果您使用rand("seed",4),这实际上会切换到之前在 Octave 中使用的 PRNG 的早期版本,该 PRNG 根本不是 MT19937,而是 Fortran RANDLIB

在 NumPy 和 Octave 中可以得到相同的数字,但是您必须在 Octave 中破解随机种子生成算法并编写自己的函数来从初始 32 位整数种子中构造状态向量。我不是 Octave 专家,但通过在 Octave/Matlab 中对位操作函数和整数类进行多次 Internet 搜索,我能够编写以下粗略的脚本来实现播种:

function state = mtstate(seed)

state = uint32(zeros(625,1));

state(1) = uint32(seed);
for i=1:623,
   tmp = uint64(1812433253)*uint64(bitxor(state(i),bitshift(state(i),-30)))+i;
   state(i+1) = uint32(bitand(tmp,uint64(intmax('uint32'))));
end
state(625) = 1;

像这样使用它:

octave:9> rand('state',mtstate(4));
octave:10> rand(1,5)
ans =

   0.96703   0.54723   0.97268   0.71482   0.69773

仅用于与 NumPy 比较:

>>> a = numpy.random.RandomState(4)
>>> a.rand(5)
array([ 0.96702984,  0.54723225,  0.97268436,  0.71481599,  0.69772882])

数字(或至少前五个)匹配。

请注意,random 模块提供的 Python 中的默认随机数生成器也是 MT19937,但它使用不同的种子算法,因此random.seed(4) 产生完全不同的状态向量,因此 PRN 序列是不同。

【讨论】:

  • 比我预想的更复杂的解决方案,同时只有 8 行代码。不错!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-20
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-22
  • 1970-01-01
相关资源
最近更新 更多