Лучший способ заполнить N независимых генераторов случайных чисел от 1 значения

10

В моей программе мне нужно запустить N отдельных потоков, каждый с собственным RNG, который используется для выборки большого набора данных. Мне нужно иметь возможность заполнить весь этот процесс одним значением, чтобы я мог воспроизвести результаты.

Достаточно ли просто последовательно увеличивать начальное число для каждого индекса?

В настоящее время я использую numpy's, RandomStateкоторый использует генератор псевдослучайных чисел Mersenne Twister.

Фрагмент кода ниже:

# If a random number generator seed exists
if self.random_generator_seed:
    # Create a new random number generator for this instance based on its
    # own index
    self.random_generator_seed += instance_index
    self.random_number_generator = RandomState(self.random_generator_seed)

По сути, я начинаю с введенного пользователем начального числа (если оно существует) и для каждого экземпляра / потока последовательно добавляю индекс (от 0 до N-1) запущенного экземпляра. Я не знаю, является ли это хорошей практикой или есть лучший способ сделать это.

EricR
источник
1
Вы заранее знаете, сколько псевдослучайных значений будет использовать каждый поток, или, по крайней мере, сможете ли вы получить хорошую оценку верхней границы?
whuber
Нет, я не могу. Он выбирает регионы, которые суммируются до порогового значения. Размеры регионов могут значительно различаться.
EricR

Ответы:

9

Это не очень хорошая практика, конечно. Например, рассмотрим, что происходит, когда вы выполняете два запуска с корневыми начальными числами 12345 и 12346. Каждый запуск будет иметь N-1общие потоки.

Реализации Mersenne Twister (включая numpy.randomи random) обычно используют другой PRNG для расширения целочисленного начального числа в большой вектор состояния (624 32-разрядных целых числа), которые использует MT; это массив из RandomState.get_state(). Хороший способ сделать то, что вы хотите, - запустить PRNG, один раз заполнить его входным целым числом и получить из него N*62432-разрядные целые числа. Разделите этот поток на Nвекторы состояний и используйте RandomState.set_state()для явной инициализации каждого RandomStateэкземпляра. Возможно, вам придется обратиться к источникам C numpy.randomили _randomиз стандартной библиотеки, чтобы получить этот PRNG (они одинаковые). Я не уверен, что кто-то реализовал отдельную версию этого PRNG для Python.

Роберт Керн
источник
Я думаю, что это может быть лучшим решением, которое я когда-либо слышал. Я не думаю, что это имеет большое значение для того, как я делю поток, хотя и правильно? Кажется гораздо более маловероятным иметь дублирующую последовательность на 624 32-битных целых числах между экземплярами, независимо от того, как они выбираются из исходного PRNG и начального числа.
EricR
1
На самом деле, я вернусь немного назад. Мне не ясно, что инициализатор PRNG предназначен для произвольного множества значений, извлеченных из него. Рассмотрите возможность использования другого качественного PRNG (предпочтительно не связанного с MT) для генерации потока состояний. Можно реализовать HMAC-DRBG (PRNG, использующий HMAC в качестве криптографического примитива), используя только стандартную библиотеку относительно просто. Криптографическая безопасность не является проблемой; просто простота реализации и качество битового потока. Вы должны будете убедиться, что не будут созданы все нулевые векторы, в очень редких случаях.
Роберт Керн
Или просто используйте одну из более новых RandomStateреализаций в разработке, которая использует алгоритм, который имеет настраиваемые потоки. То есть вы инициализируете каждый RandomStateэкземпляр одним и тем же начальным числом и разными идентификаторами потоков (просто увеличиться - это нормально), и вам гарантированы независимые потоки. pypi.python.org/pypi/randomstate
Роберт Керн
4

Φ(U)UN

  1. Φ(U),ΦN(U),Φ2*N(U),,,,
  2. Φ2(U),Φ1+N(U),Φ1+2*N(U),,,,
  3. ...
  4. ΦN-1(U),ΦN-1+N(U),ΦN-1+2*N(U),,,,

ΦN(U)знак равноΦ(ΦN-1(U))

Сиань
источник
2

Теперь есть пакет Python под названием RandomGen , у которого есть методы для достижения этой цели.

Он поддерживает независимые потоки, созданные из одного начального числа, а также протокол перехода для более старых генераторов случайных чисел, таких как MT19937.

Praveen
источник
0

Некоторые люди утверждают, что есть корреляции в случайных числах, генерируемых последовательными семенами. /programming/10900852/near-seeds-in-random-number-generation-may-give-s Similar-random-numbers Я не уверен, насколько это правда.

Если вы беспокоитесь об этом, почему бы не использовать один генератор случайных чисел, чтобы выбрать семена для всех других генераторов?

Аарон
источник
Просто потому, что я не хочу иметь случайную возможность генерировать одно и то же начальное число для более чем одного генератора. Конечно, я мог бы поработать над программированием, чтобы предотвратить это, но тогда я не знаю, как это было бы лучше, чем сначала собирать семена последовательно.
EricR
1
Очевидно , корреляции возможны с последовательными начальными числами ... Однако, как показано в статье, приведенной в этом ответе из блога Джона Д. Кука, использование одного ГСЧ для создания начальных чисел для других генераторов намного хуже, потому что вы столкнулись с проблемой дня рождения! Это говорит о том, что генерация 1000 16-битных беззнаковых семян случайным образом с вероятностью перекрытия 99,95%!
Правин