Последовательно создавайте один и тот же случайный массив numpy

89

Я жду, пока другой разработчик завершит фрагмент кода, который вернет массив np формы (100,2000) со значениями -1,0 или 1.

А пока я хочу случайным образом создать массив с одинаковыми характеристиками, чтобы иметь возможность начать разработку и тестирование. Дело в том, что я хочу, чтобы этот случайно созданный массив был каждый раз одинаковым, поэтому я не тестирую массив, который постоянно меняет свое значение каждый раз, когда я повторно запускаю свой процесс.

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

r = np.random.randint(3, size=(100, 2000)) - 1
Идр
источник

Ответы:

84

Просто введите в генератор случайных чисел фиксированное значение, например

numpy.random.seed(42)

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

Свен Марнах
источник
43
Кто-то пробрался в numpy.random.seed()функцию, когда я не обращал внимания. :-) Я намеренно исключил его из исходного модуля. Я рекомендую людям использовать свои собственные экземпляры RandomStateи передавать эти объекты.
Роберт Керн
6
Роберт - главный участник numpy. Я думаю, нам следует придать его мнению некоторый вес.
устарело
10
@deprecated: Я благодарен Роберту за работу, но его работа не заменяет обоснование рекомендации. Кроме того, если использование numpy.random.seed()не рекомендуется, это следует указать в документации . Судя по всему, другие участники NumPy не разделяют мнение Роберта. Совершенно без обид, мне просто любопытно.
Свен Марнах
13
Это то же самое, что использовать random.seedвместо использования random.Randomобъекта в стандартной библиотеке Python. Если вы используете random.seedили numpy.random.seed, вы заполняете все случайные экземпляры как в своем коде, так и в любом коде, который вы вызываете, или в любом коде, который выполняется в том же сеансе, что и ваш. Если эти вещи зависят от того, что они действительно случайны, вы начинаете сталкиваться с проблемами. Если вы развернете код, который устанавливает случайное начальное число, вы можете внести уязвимость в системе безопасности.
asmeurer
3
@asmeurer Любой, кто использует генератор псевдослучайных чисел в целях безопасности, вероятно, не знает, что делает.
JAB
191

Создайте свой собственный экземпляр numpy.random.RandomState()с выбранным вами семенем. Не используйте, numpy.random.seed()кроме как для работы с негибкими библиотеками, которые не позволяют вам передавать ваш собственный RandomStateэкземпляр.

[~]
|1> from numpy.random import RandomState

[~]
|2> prng = RandomState(1234567890)

[~]
|3> prng.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])

[~]
|4> prng2 = RandomState(1234567890)

[~]
|5> prng2.randint(-1, 2, size=10)
array([ 1,  1, -1,  0,  0, -1,  1,  0, -1, -1])
Роберт Керн
источник
7
У вас есть какое-нибудь обоснование для вашей рекомендации? Что не так numpy.random.seed()? Я знаю, что это не потокобезопасно, но это действительно удобно, если вам не нужна потокобезопасность.
Sven Marnach
52
В основном это для формирования хороших привычек. Возможно, сейчас вам не нужны независимые стримы, но Sven-6 месяцев спустя может. Если вы напишете свои библиотеки для использования методов напрямую numpy.random, вы не сможете создавать независимые потоки позже. Также проще писать библиотеки с намерением контролировать потоки ГПСЧ. Всегда есть несколько способов войти в вашу библиотеку, и каждый из них должен иметь способ управлять семенем. Передача объектов PRNG - более чистый способ сделать это, чем полагаться на них numpy.random.seed(). К сожалению, это поле для комментариев слишком короткое, чтобы содержать больше примеров. :-)
Роберт Керн
25
Другой способ описания объяснения Роберта: использование numpy.random.seed использует глобальную переменную для сохранения состояния PRNG, и здесь применимы те же стандартные причины, по которым глобальные переменные являются плохими.
Роби Башак
9
Если вы хотите, чтобы ГПСЧ были независимыми, не заполняйте их ничем. Просто используйте numpy.random.RandomState()без аргументов. Это засевает состояние уникальными значениями, полученными из средств вашей операционной системы для таких вещей ( /dev/urandomна машинах UNIX и их эквиваленте Windows). Если numpy.random.RandomState(1234567890)у вас не работает, покажите, что именно вы ввели, и точное сообщение об ошибке.
Роберт Керн
5
Не хорошая идея. Используйте numpy.random.RandomState()без аргументов для достижения наилучших результатов.
Роберт Керн,
3

Если вы используете другие функции, полагающиеся на случайное состояние, вы не можете просто установить общее начальное число, а вместо этого должны создать функцию для генерации случайного списка чисел и установить начальное значение в качестве параметра функции. Это не повлияет на другие генераторы случайных чисел в коде:

# Random states
def get_states(random_state, low, high, size):
    rs = np.random.RandomState(random_state)
    states = rs.randint(low=low, high=high, size=size)
    return states

# Call function
states = get_states(random_state=42, low=2, high=28347, size=25)
mari756h
источник
3

Важно понимать, что такое семя случайного генератора и когда / как оно установлено в вашем коде (посмотрите, например, здесь, чтобы получить хорошее объяснение математического значения семени).

Для этого вам нужно установить семя, выполнив:

random_state = np.random.RandomState(seed=your_favorite_seed_value)

Затем важно генерировать случайные числа из random_state, а не из np.random. Т.е. вам следует сделать:

random_state.randint(...)

вместо того

np.random.randint(...) 

который создаст новый экземпляр RandomState () и в основном будет использовать внутренние часы вашего компьютера для установки семени.

t_sic
источник
2

Я просто хочу кое-что прояснить в отношении ответа @Robert Kern на случай, если это неясно. Даже если вы используете, RandomStateвам придется инициализировать его каждый раз, когда вы вызываете случайный метод numpy, как в примере Роберта, иначе вы получите следующие результаты.

Python 3.6.9 |Anaconda, Inc.| (default, Jul 30 2019, 19:07:31) 
[GCC 7.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import numpy as np
>>> prng = np.random.RandomState(2019)
>>> prng.randint(-1, 2, size=10)
array([-1,  1,  0, -1,  1,  1, -1,  0, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([-1, -1, -1,  0, -1, -1,  1,  0, -1, -1])
>>> prng.randint(-1, 2, size=10)
array([ 0, -1, -1,  0,  1,  1, -1,  1, -1,  1])
>>> prng.randint(-1, 2, size=10)
array([ 1,  1,  0,  0,  0, -1,  1,  1,  0, -1])
Кирк Уолла
источник