Генерировать несколько независимых случайных потоков в python

#python #numpy #random

#python #numpy #Случайный

Вопрос:

Я хочу сгенерировать несколько потоков случайных чисел в python. Я пишу программу для моделирования системы очередей и хочу, чтобы один поток соответствовал времени прибытия, а другой — времени обслуживания и так далее.

numpy.random() генерирует случайные числа из глобального потока.

В matlab есть нечто, называемое RandStream, которое позволяет мне создавать несколько потоков.

Есть ли какой-нибудь способ создать что-то вроде RandStream в Python

Комментарии:

1. Вы собираетесь использовать это для уменьшения дисперсии?

Ответ №1:

Как Numpy, так и внутренние генераторы случайных чисел имеют создаваемые экземпляры классов.

Для просто random :

 import random
random_generator = random.Random()
random_generator.random()
#>>> 0.9493959884174072
  

И для Numpy:

 import numpy
random_generator = numpy.random.RandomState()
random_generator.uniform(0, 1, 10)
#>>> array([ 0.98992857,  0.83503764,  0.00337241,  0.76597264,  0.61333436,
#>>>         0.0916262 ,  0.52129459,  0.44857548,  0.86692693,  0.21150068])
  

Комментарии:

1. Где мне найти документы для первого? Кажется, я не могу правильно использовать Google…

2. @Atcold «Функции, предоставляемые этим модулем, на самом деле являются связанными методами скрытого экземпляра random.Random класса. Вы можете создавать свои собственные экземпляры Random , чтобы получить генераторы, которые не разделяют состояние «. — docs.python.org/3/library/random.html

3. Но как вы генерируете независимые потоки? Гарантированно ли работают последовательные начальные значения?

4. @RafaelAlmeida Это патологический пример, и есть несколько причин, по которым это здесь не применимо. 1) мы генерируем только две последовательности, поэтому последовательности будут быстро декоррелироваться, а не одну выборку из многих смежных последовательностей, 2) В Python seeding есть шаг хеширования для исправления корреляций, 3) вы все равно никогда не получите идеальной независимости от посредственного генератора, такого как Mersenne Twister; используйтелучший RNG (желательно криптографический) и не используйте фиксированные начальные значения, если это проблема. Я согласен с тем, что использование больших начальных значений с более высокой энтропией более рискованно.

5. @RafaelAlmeida Стоит отметить, что C #, похоже, использует генератор вычитания, который выглядит мусором.

Ответ №2:

Вам не нужно использовать пакет RandomGen. Достаточно просто инициировать два потока. Например:

 import numpy as np
prng1 = np.random.RandomState()
prng2 = np.random.RandomState()
prng1.seed(1)
prng2.seed(1)
  

Теперь, если вы используете оба потока prngX.rand() , вы обнаружите, что два потока дадут вам идентичные результаты, что означает, что они являются независимыми потоками с одинаковым начальным значением.

Чтобы использовать random пакет, просто замените np.random.RandomState() на random.Random() .

Ответ №3:

Для обеспечения воспроизводимости вы можете передать начальное значение непосредственно в random.Random() , а затем вызвать переменные оттуда. Затем каждый инициированный экземпляр будет выполняться независимо от другого. Например, если вы запустите:

 import random
rg1 = random.Random(1)
rg2 = random.Random(2)
rg3 = random.Random(1)
for i in range(5): print(rg1.random())
print('')
for i in range(5): print(rg2.random())
print('')
for i in range(5): print(rg3.random())
  

Вы получите:

 0.134364244112
0.847433736937
0.763774618977
0.255069025739
0.495435087092

0.956034271889
0.947827487059
0.0565513677268
0.0848719951589
0.835498878129

0.134364244112
0.847433736937
0.763774618977
0.255069025739
0.495435087092
  

Ответ №4:

В ответе Veedrac не было указано, как можно генерировать независимые потоки.

Лучший способ, который я смог найти для генерации независимых потоков, — это использовать замену для RandomState numpy. Это обеспечивается пакетом RandomGen.

Он поддерживает независимые случайные потоки, но они используют один из трех генераторов случайных чисел: PCG64, ThreeFry или Philox. Если вы хотите использовать более традиционный MT19937, вы можете вместо этого полагаться на jumping .

Комментарии:

1. random.Random() является независимым потоком, по крайней мере, до пределов твистера Мерсенна. Если вам нужны n потоки, сделайте [random.Random() for _ in range(n)] .

Ответ №5:

numpy добавлена возможность генерировать независимые потоки случайных чисел с использованием SeedSequence . Это обрабатывает предоставленное пользователем начальное значение, обычно в виде целого числа некоторого размера, и преобразует его в начальное состояние для BitGenerator. Он использует методы хеширования, чтобы гарантировать, что низкокачественные начальные состояния превращаются в высококачественные начальные состояния (по крайней мере, с очень высокой вероятностью).

 from numpy.random import SeedSequence, default_rng

ss = SeedSequence(12345)

# Spawn off 10 child SeedSequences to pass to child processes.
child_seeds = ss.spawn(10)
streams = [default_rng(s) for s in child_seeds]
  

каждый поток является генератором PCG64. Случайные числа могут генерироваться последовательно следующим образом —

 for i in 1:K
    instance[i] = [s.uniform() for s in streams]
  

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