Генераторы битов#

Случайные значения, созданные Generator происходят из BitGenerator. BitGenerators не предоставляют случайные числа напрямую и содержат только методы, используемые для инициализации, получения или установки состояния, перехода или продвижения состояния, а также для доступа к низкоуровневым обёрткам для использования кодом, который может эффективно обращаться к предоставляемым функциям, например, numba.

Поддерживаемые BitGenerators#

Включенные генераторы случайных чисел:

  • PCG-64 - По умолчанию. Быстрый генератор, который можно продвинуть на произвольное количество шагов. См. документацию для advance. PCG-64 имеет период \(2^{128}\). См. Страница автора PCG для получения дополнительной информации об этом классе ГПСЧ.

  • PCG-64 DXSM - улучшенная версия PCG-64 с лучшими статистическими свойствами в параллельных контекстах. См. Обновление PCG64 с PCG64DXSM для получения дополнительной информации об этих улучшениях.

  • MT19937 - стандартный BitGenerator Python. Добавляет MT19937.jumped функция, которая возвращает новый генератор с состоянием, как если бы \(2^{128}\) были сделаны выборки.

  • Philox - генератор на основе счётчика, способный продвигаться на произвольное количество шагов или генерировать независимые потоки. См. Random123 страницу для получения более подробной информации об этом классе генераторов битов.

  • SFC64 - Быстрый генератор на основе случайных обратимых отображений. Обычно самый быстрый генератор из четырёх. См. Страница автора SFC для (немного) большей детализации.

BitGenerator([seed])

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

Инициализация генератора и энтропия#

BitGenerator предоставляет поток случайных значений. Для генерации воспроизводимых потоков BitGenerators поддерживают установку начального состояния через seed. Все предоставленные BitGenerators принимают произвольное неотрицательное целое число или список таких чисел в качестве seed. BitGenerators должны обработать эти входные данные в высококачественное внутреннее состояние для BitGenerator. Все BitGenerators в numpy делегируют эту задачу 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(f'seed = {ss.entropy}')
bg = PCG64(ss)

По умолчанию мы используем 128-битное целое число, используя энтропию, собранную из ОС. Это хорошее количество энтропии для инициализации всех генераторов, которые у нас есть в numpy. Мы не рекомендуем использовать маленькие сиды ниже 32 бит для общего использования. Использование всего лишь небольшого набора сидов для создания больших пространств состояний означает, что есть некоторые начальные состояния, которых невозможно достичь. Это создаёт некоторые смещения, если все используют такие значения.

Ничего не будет неправильно с результатами как таковыми; даже начальное значение 0 вполне подходит благодаря обработке, которую SeedSequence делает. Если вам просто нужно некоторые фиксированное значение для модульных тестов или отладки, не стесняйтесь использовать любое начальное значение, которое вам нравится. Но если вы хотите делать выводы из результатов или публиковать их, выбор из большего набора начальных значений является хорошей практикой.

Если вам нужно сгенерировать хорошее начальное значение «офлайн», то SeedSequence().entropy или с помощью secrets.randbits(128) из стандартной библиотеки являются удобными способами.

Если необходимо запустить несколько стохастических симуляций параллельно, лучшей практикой является создание экземпляра генератора случайных чисел для каждой симуляции. Чтобы убедиться, что случайные потоки имеют различные начальные состояния, можно использовать spawn метод SeedSequence. Например, здесь мы создаём список из 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 method:

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([entropy, spawn_key, ...])

SeedSequence смешивает источники энтропии воспроизводимым образом для установки начального состояния независимых и, вероятно, непересекающихся BitGenerators.