位元產生器#
由 Generator
產生的隨機值源自 BitGenerator。BitGenerator 不直接提供隨機數,僅包含用於播種、取得或設定狀態、跳躍或推進狀態,以及用於存取低階包裝函式的方法,以供可以有效存取所提供函數的程式碼使用,例如 numba。
支援的 BitGenerator#
包含的 BitGenerator 有
PCG-64 - 預設值。一種快速產生器,可以任意量推進。請參閱
advance
的文件。PCG-64 的週期為 \(2^{128}\)。請參閱 PCG 作者的頁面 以取得有關此 PRNG 類別的更多詳細資訊。PCG-64 DXSM - PCG-64 的升級版本,在平行環境中具有更好的統計特性。請參閱 使用 PCG64DXSM 升級 PCG64 以取得有關這些改進的更多資訊。
MT19937 - 標準 Python BitGenerator。新增了
MT19937.jumped
函數,該函數傳回一個新的產生器,其狀態如同已進行 \(2^{128}\) 次繪製。Philox - 一種基於計數器的產生器,能夠推進任意數量的步驟或產生獨立的串流。請參閱 Random123 頁面以取得有關此類位元產生器的更多詳細資訊。
SFC64 - 一種基於隨機可逆映射的快速產生器。通常是四個產生器中最快的。請參閱 SFC 作者的頁面 以取得(一些)更多詳細資訊。
|
通用 BitGenerator 的基礎類別,它根據不同的演算法提供隨機位元串流。 |
播種和熵#
BitGenerator 提供隨機值串流。為了產生可重現的串流,BitGenerator 支援透過種子設定其初始狀態。所有提供的 BitGenerator 都將接受任意大小的非負整數,或此類整數的列表作為種子。BitGenerator 需要取得這些輸入並將其處理為 BitGenerator 的高品質內部狀態。numpy 中的所有 BitGenerator 都將該任務委派給 SeedSequence
,後者使用雜湊技術來確保即使是低品質的種子也能產生高品質的初始狀態。
from numpy.random import PCG64
bg = PCG64(12345678903141592653589793)
SeedSequence
旨在方便實作最佳實務。我們建議隨機程式預設使用來自作業系統的熵,以便每次執行都不同。程式應印出或記錄該熵。為了重現過去的值,程式應允許使用者透過某種機制(命令列引數很常見)提供該值,以便使用者隨後可以重新輸入該熵以重現結果。SeedSequence
可以處理除與使用者溝通之外的所有事情,這取決於您。
from numpy.random import PCG64, SeedSequence
# Get the user's seed somehow, maybe through `argparse`.
# If the user did not provide a seed, it should return `None`.
seed = get_user_seed()
ss = SeedSequence(seed)
print('seed = {}'.format(ss.entropy))
bg = PCG64(ss)
我們預設使用從作業系統收集的熵的 128 位元整數。這是初始化我們在 numpy 中擁有的所有產生器的良好熵量。我們不建議在一般用途中使用小於 32 位元的種子。僅使用一小組種子來實例化更大的狀態空間意味著有些初始狀態無法達到。如果每個人都使用這些值,則會產生一些偏差。
結果本身不會有任何錯誤;即使種子為 0 也是完全可以的,這要歸功於 SeedSequence
所做的處理。如果您只需要用於單元測試或偵錯的一些固定值,請隨意使用您喜歡的任何種子。但是,如果您想從結果中進行推斷或發布它們,那麼從更大的種子集中繪製是一個好的實務。
如果您需要「離線」產生良好的種子,那麼 SeedSequence().entropy
或使用標準函式庫中的 secrets.randbits(128)
都是方便的方法。
如果您需要平行執行多個隨機模擬,最佳實務是為每個模擬建構一個隨機產生器實例。為了確保隨機串流具有不同的初始狀態,您可以使用 SeedSequence
的 spawn 方法。例如,這裡我們建構一個包含 12 個實例的列表
from numpy.random import PCG64, SeedSequence
# High quality initial entropy
entropy = 0x87351080e25cb0fad77a44a3be03b491
base_seq = SeedSequence(entropy)
child_seqs = base_seq.spawn(12) # a list of 12 SeedSequences
generators = [PCG64(seq) for seq in child_seqs]
如果您已經有一個初始隨機產生器實例,則可以使用 spawn
方法縮短上述程式碼
from numpy.random import PCG64, SeedSequence
# High quality initial entropy
entropy = 0x87351080e25cb0fad77a44a3be03b491
base_bitgen = PCG64(entropy)
generators = base_bitgen.spawn(12)
另一種方法是使用 SeedSequence
可以由元素元組初始化的事實。在這裡,我們使用基礎熵值和整數 worker_id
from numpy.random import PCG64, SeedSequence
# High quality initial entropy
entropy = 0x87351080e25cb0fad77a44a3be03b491
sequences = [SeedSequence((entropy, worker_id)) for worker_id in range(12)]
generators = [PCG64(seq) for seq in sequences]
請注意,後一種方法產生的序列將與透過 spawn
建構的序列不同。
|
SeedSequence 以可重現的方式混合熵來源,以設定獨立且非常可能不重疊的 BitGenerator 的初始狀態。 |