可以用NumPy重现MATLAB的randn()吗?
我在想,能不能用NumPy完全复制MATLAB中的randn()
函数生成的随机数序列。我用Python和NumPy写了自己的代码,但得到的结果和别人用MATLAB写的代码有点不一样,我很难找到原因,因为随机数的生成方式不同。
我找到了一些numpy.random.seed
的值,这样可以让第一次生成的随机数相同,但从第二次开始,结果就完全不同了。我需要生成大约20,000次的多元正态分布随机数,所以我不想只是把MATLAB生成的随机数保存下来,然后在Python中读取。
3 个回答
我想进一步说明一下使用twister/seeding方法的事情:MATLAB和numpy使用相同的种子生成相同的随机数序列,但它们填充矩阵的方式不同。
MATLAB是从列开始填充矩阵,而python则是从行开始填充。所以为了让两个程序生成的矩阵看起来一样,你需要进行转置:
MATLAB:
rand('twister', 1337);
A = rand(3,5)
A =
Columns 1 through 2
0.262024675015582 0.459316887214567
0.158683972154466 0.321000540520167
0.278126519494360 0.518392820597537
Columns 3 through 4
0.261942925565145 0.115274226683149
0.976085284877434 0.386275068634359
0.732814552690482 0.628501179539712
Column 5
0.125057926335599
0.983548605143641
0.443224868645128
python:
import numpy as np
np.random.seed(1337)
A = np.random.random((5,3))
A.T
array([[ 0.26202468, 0.45931689, 0.26194293, 0.11527423, 0.12505793],
[ 0.15868397, 0.32100054, 0.97608528, 0.38627507, 0.98354861],
[ 0.27812652, 0.51839282, 0.73281455, 0.62850118, 0.44322487]])
注意:我也把这个答案放在了一个类似的问题上:比较使用随机数生成的Matlab和Numpy代码
如果你把随机数生成器设置为相同的种子,理论上它会生成相同的数字,比如在matlab中。我不太确定怎么做最好,但这个方法似乎有效,在matlab中可以这样操作:
rand('twister', 5489)
在numy中对应的操作是:
np.random.seed(5489)
这样可以(重新)初始化你的随机数生成器。对我来说,这样做可以让rand()和np.random.random()生成相同的数字,不过randn就不行了,我不太确定有没有简单的方法可以做到这一点。
在较新的matlab版本中,你可能可以设置一个RandStream,使其属性与numpy相同;而在旧版本中,你可以在matlab中复现numpy的randn(或者反过来)。numpy使用极坐标形式来从np.random.random()生成均匀分布的数字(这里给出的第二个算法:http://www.taygeta.com/random/gaussian.html)。你可以在matlab中直接写这个算法,以便从matlab的rand函数生成与numpy相同的randn数字。
如果你不需要大量的随机数,可以直接把它们保存到一个.mat文件中,然后通过scipy.io读取...
用户问是否可以在Python中复现Matlab的randn()输出,而不是rand。我还没找到设置算法或种子的办法来精确复现randn()的结果,但下面的解决方案对我来说是有效的。
在Matlab中:生成正态分布的随机数可以这样做:
rng(1);
norminv(rand(1,5),0,1)
ans =
-0.2095 0.5838 -3.6849 -0.5177 -1.0504
在Python中:生成正态分布的随机数可以这样做:
import numpy as np
from scipy.stats import norm
np.random.seed(1)
norm.ppf(np.random.rand(1,5))
array([[-0.2095, 0.5838, -3.6849, -0.5177,-1.0504]])
在从Matlab转到Python或反过来的时候,能够有一些函数来复现相同的随机数是非常方便的。