4.6 伪随机数生成

numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值的函数。例如,你可以用normal来得到一个标准正态分布的4×4样本数组:

  1. In [238]: samples = np.random.normal(size=(4, 4))
  2. In [239]: samples
  3. Out[239]:
  4. array([[ 0.5732, 0.1933, 0.4429, 1.2796],
  5. [ 0.575 , 0.4339, -0.7658, -1.237 ],
  6. [-0.5367, 1.8545, -0.92 , -0.1082],
  7. [ 0.1525, 0.9435, -1.0953, -0.144 ]])

而Python内置的random模块则只能一次生成一个样本值。从下面的测试结果中可以看出,如果需要产生大量样本值,numpy.random快了不止一个数量级:

  1. In [240]: from random import normalvariate
  2. In [241]: N = 1000000
  3. In [242]: %timeit samples = [normalvariate(0, 1) for _ in range(N)]
  4. 1.77 s +- 126 ms per loop (mean +- std. dev. of 7 runs, 1 loop each)
  5. In [243]: %timeit np.random.normal(size=N)
  6. 61.7 ms +- 1.32 ms per loop (mean +- std. dev. of 7 runs, 10 loops each)

我们说这些都是伪随机数,是因为它们都是通过算法基于随机数生成器种子,在确定性的条件下生成的。你可以用NumPy的np.random.seed更改随机数生成种子:

  1. In [244]: np.random.seed(1234)

numpy.random的数据生成函数使用了全局的随机种子。要避免全局状态,你可以使用numpy.random.RandomState,创建一个与其它隔离的随机数生成器:

  1. In [245]: rng = np.random.RandomState(1234)
  2. In [246]: rng.randn(10)
  3. Out[246]:
  4. array([ 0.4714, -1.191 , 1.4327, -0.3127, -0.7206, 0.8872, 0.8596,
  5. -0.6365, 0.0157, -2.2427])

表4-8列出了numpy.random中的部分函数。在下一节中,我将给出一些利用这些函数一次性生成大量样本值的范例。

4.6 伪随机数生成 - 图1

4.6 伪随机数生成 - 图2