新功能与变更#

NumPy 1.17.0 引入了 Generator 作为 传统 RandomState 的改进替代品。以下是这两种实现的快速比较。

特性

旧版等效

备注

Generator

RandomState

Generator 需要一个流源,称为 BitGenerator。提供了多种此类生成器。RandomState 默认使用 Mersenne Twister MT19937,但也可以通过任何 BitGenerator 实例化。

随机

random_sample, rand

访问 `BitGenerator` 中的值,并将其转换为 `[0.0., 1.0)` 区间内的 `float64`。除了 `size` 关键字参数外,现在还支持 `dtype='d'` 或 `dtype='f'`,以及用于填充用户提供的数组的 `out` 关键字参数。

还支持许多其他分布。

整数

randint, random_integers

使用 `endpoint` 关键字参数调整 `high` 区间端点的包含或排除。

  • 正态分布、指数分布和伽马分布生成器使用 256 步 Ziggurat 方法,比 NumPy 在 standard_normalstandard_exponentialstandard_gamma 中的默认实现快 2-10 倍。由于算法的改变,无法使用 Generator 为这些分布或任何依赖它们的分布方法重现确切的随机值。

In [1]: import numpy.random

In [2]: rng = np.random.default_rng()

In [3]: %timeit -n 1 rng.standard_normal(100000)
   ...: %timeit -n 1 numpy.random.standard_normal(100000)
   ...: 
1.88 ms +- 13.3 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
3.46 ms +- 20.2 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [4]: %timeit -n 1 rng.standard_exponential(100000)
   ...: %timeit -n 1 numpy.random.standard_exponential(100000)
   ...: 
919 us +- 12.4 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
2.47 ms +- 23.4 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [5]: %timeit -n 1 rng.standard_gamma(3.0, 100000)
   ...: %timeit -n 1 numpy.random.standard_gamma(3.0, 100000)
   ...: 
3.53 ms +- 39.5 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
6.96 ms +- 25.1 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
In [6]: rng = np.random.default_rng()

In [7]: rng.random(3, dtype=np.float64)
Out[7]: array([0.00512656, 0.76054751, 0.5135002 ])

In [8]: rng.random(3, dtype=np.float32)
Out[8]: array([0.13016486, 0.67658764, 0.94141597], dtype=float32)

In [9]: rng.integers(0, 256, size=3, dtype=np.uint8)
Out[9]: array([100, 186,  43], dtype=uint8)
  • 可选的 out 参数允许为选定分布填充现有数组

    这使得多线程能够并行使用合适的 BitGenerator 分块填充大型数组。

In [10]: rng = np.random.default_rng()

In [11]: existing = np.zeros(4)

In [12]: rng.random(out=existing[:2])
Out[12]: array([0.7695275 , 0.73739323])

In [13]: print(existing)
[0.7695275  0.73739323 0.         0.        ]
In [14]: rng = np.random.default_rng()

In [15]: a = np.arange(12).reshape((3, 4))

In [16]: a
Out[16]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])

In [17]: rng.choice(a, axis=1, size=5)
Out[17]: 
array([[ 0,  1,  2,  0,  0],
       [ 4,  5,  6,  4,  4],
       [ 8,  9, 10,  8,  8]])

In [18]: rng.shuffle(a, axis=1)        # Shuffle in-place

In [19]: a
Out[19]: 
array([[ 2,  1,  0,  3],
       [ 6,  5,  4,  7],
       [10,  9,  8, 11]])
  • 添加了一个从复正态分布 (complex_normal) 采样的函数