2015-09-20 3 views
5

При стремлении к воспроизводимости кода Python с использованием генераторов случайных чисел рекомендуемым методом является создание отдельных объектов RandomState. К сожалению, некоторые существенные пакеты, такие как scipy.stats, не могут (насколько мне известно) быть настроены на использование определенного RandomState и будут просто использовать текущее состояние numpy.random. Мой текущий обходной путь заключается в использовании менеджер контекста, который сохраняет состояние ГСЧ, а затем сбрасывает его при выходе следующим образом: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. Семена ГСЧ по умолчанию для фиксированного значения
  2. Проверяет, что по умолчанию ГСЧ возвращает те же, ожидаемые значения каждый раз, когда
  3. использует ваш менеджер контекста
  4. подтверждают, что генерируется новая последовательность значений
  5. подтверждают, что исходный сеянный RNG из (1) продолжает излучать ожидаемую последовательность