新功能與差異#

NumPy 1.17.0 引入了 Generator,作為 舊版 RandomState 的改良替代品。以下是這兩種實作方式的快速比較。

功能

舊版對應

註記

Generator

RandomState

Generator 需要一個串流來源,稱為 BitGenerator。已提供許多此類產生器。RandomState 預設使用 Mersenne Twister MT19937,但也可以使用任何 BitGenerator 實例化。

random

random_sample, rand

存取 BitGenerator 中的值,將其轉換為區間 [0.0., 1.0) 中的 float64。除了 size 參數外,現在還支援 dtype='d'dtype='f',以及用於填滿使用者提供陣列的 out 參數。

也支援許多其他分佈。

integers

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)
   ...: 
936 us +- 4.33 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.72 ms +- 11.5 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)
   ...: 
464 us +- 3.84 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
1.23 ms +- 7.66 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.75 ms +- 9.05 us per loop (mean +- std. dev. of 7 runs, 1 loop each)
3.48 ms +- 4.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.09583911, 0.93160588, 0.71947891])

In [8]: rng.random(3, dtype=np.float32)
Out[8]: array([0.50844425, 0.20221537, 0.7923881 ], dtype=float32)

In [9]: rng.integers(0, 256, size=3, dtype=np.uint8)
Out[9]: array([  4, 201, 126], 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.42493599, 0.03707944])

In [13]: print(existing)
[0.42493599 0.03707944 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([[ 1,  2,  2,  2,  0],
       [ 5,  6,  6,  6,  4],
       [ 9, 10, 10, 10,  8]])

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

In [19]: a
Out[19]: 
array([[ 1,  3,  2,  0],
       [ 5,  7,  6,  4],
       [ 9, 11, 10,  8]])
  • 新增了從複數常態分佈取樣的方法 (complex_normal)