有什么新内容或不同之处#

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

功能

旧版等效

备注

生成器

RandomState

Generator 需要一个流源,称为 BitGenerator.提供了许多这样的流源.`RandomState` 默认使用 Mersenne Twister MT19937,但也可以用任何 BitGenerator 实例化.

random

random_sample, rand

访问 BitGenerator 中的值,将它们转换为 [0.0., 1.0) 区间内的 float64.除了 size kwarg 外,现在还支持 dtype='d'dtype='f',以及一个 out kwarg 来填充用户提供的数组.

许多其他发行版也得到支持.

integers

randint, random_integers

使用 endpoint kwarg 来调整包含或排除 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)
   ...: 
516 us +- 18.5 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.62 ms +- 67.4 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)
   ...: 
585 us +- 136 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.23 ms +- 11.7 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)
   ...: 
1.27 ms +- 11.2 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
2.68 ms +- 34.9 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.56834421, 0.66387157, 0.27851115])

In [8]: rng.random(3, dtype=np.float32)
Out[8]: array([0.23236209, 0.28238696, 0.6453461 ], dtype=float32)

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

    这允许使用合适的 BitGenerators 并行地以块为单位填充大数组,从而实现多线程.

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

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

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

In [13]: print(existing)
[0.7525722  0.66417526 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([[ 2,  1,  2,  1,  1],
       [ 6,  5,  6,  5,  5],
       [10,  9, 10,  9,  9]])

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

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