2015-09-20 21 views
5

當使用隨機數生成器來實現Python代碼的可重複性時,推薦的方法似乎是構建單獨的RandomState對象。不幸的是,像scipy.stats這樣的一些基本軟件包不能(據我所知)被設置爲使用特定的RandomState,並且只會使用numpy.random的當前狀態。 我現在的解決方法是使用節省了RNG的狀態的上下文管理器,然後按如下重置它在離開:Python:使用上下文管理器臨時更改隨機種子的危險?

class FixedSeed: 
    def __init__(self, seed): 
     self.seed = seed 
     self.state = None 

    def __enter__(self): 
     self.state = rng.get_state() 
     np.random.seed(self.seed) 

    def __exit__(self, exc_type, exc_value, traceback): 
     np.random.set_state(self.state) 

有很多關於以任何方式改變狀態的文件中警告 - 上述方法一般安全嗎? (在這個意義上的變化是本地的上下文和我的代碼的其餘部分將不受影響)

回答

2

numpy documentation聲稱:不需要

set_state和get_state與任何隨機的工作NumPy中的 分佈。如果手動更改內部狀態,則用戶應該確切知道他/她正在做什麼。

這聽起來很可怕。在公開的,有記錄的界面上對此警告的可能解釋是,「確切地知道」意味着「知道重新開始PRNG會嚴重降低隨機性」。但是你知道你想在你的上下文中非常特別地減少隨機性。

在支持這個猜想的,我看着numpy/test_random.py包含了像代碼:

class TestSeed(TestCase): 
    def test_scalar(self): 
     s = np.random.RandomState(0) 
     assert_equal(s.randint(1000), 684) 
     s = np.random.RandomState(4294967295) 
     assert_equal(s.randint(1000), 419) 

,因爲他們確實需要確定性的結果。請注意,他們創建了一個np.random.RandomState的實例,但我在代碼中發現沒有任何跡象表明set_state()會破壞任何內容。

如有疑問,編寫一個測試套件,

  1. 種子默認RNG爲固定值
  2. 檢查默認RNG每次
  3. 使用您的上下文管理器返回相同的,預期值
  4. 確認生成了一個新的序列值
  5. 確認來自(1)的原始種子RNG繼續發出其預期序列