Какие числа я могу положить в numpy.random.seed()?

Я заметил, что вы можете поместить различные числа внутри numpy.random.seed(), например numpy.random.seed(1), numpy.random.seed(101). Что означают разные цифры? Как вы выбираете числа?

Ответ 1

Рассмотрим очень простой генератор случайных чисел:

Z[i] = (a*Z[i-1] + c) % m

Здесь Z[i] - это случайное число ith, a - множитель, а c - приращение - для разных комбинаций a, c и m у вас есть разные генераторы. Это известно как линейный конгруэнтный генератор, представленный Лехмером. Остальная часть этого деления или модуля (%) будет генерировать число между нулем и m-1, и, установив U[i] = Z[i] / m, вы получите случайные числа от нуля до единицы.

Как вы могли заметить, для запуска этого генеративного процесса - для того, чтобы иметь Z[1], вам нужно иметь Z[0] - начальное значение. Это начальное значение, которое запускает процесс, называется семенем. Взгляните на этот пример:

введите описание изображения здесь

Начальное значение, семя определяется как 7 для запуска процесса. Однако это значение не используется для генерации случайного числа. Вместо этого он используется для генерации первого Z.

Наиболее важной особенностью генератора псевдослучайных чисел была бы его непредсказуемость. Как правило, до тех пор, пока вы не делитесь своим семенем, вы в порядке со всеми семенами, поскольку генераторы сегодня намного сложнее, чем это. Однако, как еще один шаг, вы также можете генерировать семя случайно. Вы можете пропустить первые цифры n в качестве другой альтернативы.

Основной источник: Law, A. M. (2007). Моделирование и анализ моделирования. Тата Макгроу-Хилл.

Ответ 2

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

"Семя" является отправной точкой для последовательности, и гарантией является то, что если вы начнете с одного и того же семени, вы получите ту же последовательность чисел. Это очень полезно, например, для отладки (когда вы ищете ошибку в программе, для которой вам нужно воспроизвести проблему и ее изучить, не детерминированной программе было бы гораздо сложнее отладить, потому что каждый прогон был бы иным).

Ответ 3

Короткий ответ:

Существует три способа seed() генератора случайных чисел в numpy.random:

  • не использовать аргумент или использовать None - RNG инициализируется из генератора случайных чисел ОС (что обычно является криптографически случайным)

  • используйте некоторое 32-битное целое число N - RNG будет использовать это для инициализации своего состояния на основе детерминированной функции (то же самое семя → то же состояние)

  • используйте массивную последовательность из 32-разрядных целых чисел n 0, n 1, n 2 и т.д. - опять же, RNG будет использовать это для инициализации своего состояния на основе детерминированной функции (одинаковые значения для семенного и другого состояния). Это должно быть сделано с помощью хеш-функции, но в исходном коде есть магические числа, и неясно, почему они делают то, что они делают.

Если вы хотите сделать что-то повторяемое и простое, используйте одно целое.

Если вы хотите сделать что-то повторяемое, но вряд ли для третьей стороны угадать, используйте кортеж или список или массив numpy, содержащий некоторую последовательность из 32-битных целых чисел. Например, вы можете использовать numpy.random с семенем None для генерации пучка из 32-разрядных целых чисел (скажем, 32 из них, которые будут генерировать в общей сложности 1024 бит) из ОС RNG, хранить в некоторых seed S, который вы сохраняете в каком-то секретном месте, затем используйте это семя для генерации любой последовательности R псевдослучайных чисел, которые вы хотите. Затем вы можете позже воссоздать эту последовательность путем повторного посева с помощью S снова, и до тех пор, пока вы сохраняете значение S secret (а также сгенерированные числа R), никто не сможет воспроизвести эту последовательность R Если вы просто используете одно целое число, есть только 4 миллиарда возможностей, и кто-то потенциально может их попробовать. Это может быть немного на параноидальной стороне, но вы можете это сделать.


Более длинный ответ

В модуле numpy.random используется алгоритм Mersenne Twister, который вы можете подтвердить одним из двух способов:

  • Либо просмотрев документацию numpy.random.RandomState, из которых numpy.random использует экземпляр для numpy.random.* (но вы также можете использовать изолированный независимый экземпляр)

  • Глядя на исходный код в mtrand.pyx, который использует что-то под названием Pyrex для быстрой реализации C и randomkit.c и initarray.c.

В любом случае, о чем говорится в документации numpy.random.RandomState о seed():

Гарантия совместимости. Фиксированное семя и фиксированная серия вызовов методов RandomState, использующих одни и те же параметры, всегда будут давать одинаковые результаты до округленной ошибки, кроме случаев, когда значения были неверными. Неправильные значения будут исправлены, и версия NumPy, в которой было исправлено, будет указана в соответствующей документации. Расширение существующих диапазонов параметров и добавление новых параметров допускается, поскольку предыдущее поведение остается неизменным.

Параметры:
seed
: {None, int, array_like}, необязательный

Случайное семя, используемое для инициализации генератора псевдослучайных чисел. Может быть любое целое число от 0 до 2 ** 32 - 1 включительно, массив (или другая последовательность) таких целых чисел или None (по умолчанию). Если семя None, то RandomState попытается прочитать данные из /dev/urandom (или аналога Windows), если это доступно, или засечь из часов в противном случае.

Он не говорит, как используется семя, но если вы вникнете в исходный код, он ссылается на функцию init_by_array: (docstring elided)

def seed(self, seed=None):
    cdef rk_error errcode
    cdef ndarray obj "arrayObject_obj"
    try:
        if seed is None:
            with self.lock:
                errcode = rk_randomseed(self.internal_state)
        else:
            idx = operator.index(seed)
            if idx > int(2**32 - 1) or idx < 0:
                raise ValueError("Seed must be between 0 and 2**32 - 1")
            with self.lock:
                rk_seed(idx, self.internal_state)
    except TypeError:
        obj = np.asarray(seed).astype(np.int64, casting='safe')
        if ((obj > int(2**32 - 1)) | (obj < 0)).any():
            raise ValueError("Seed must be between 0 and 2**32 - 1")
        obj = obj.astype('L', casting='unsafe')
        with self.lock:
            init_by_array(self.internal_state, <unsigned long *>PyArray_DATA(obj),
                PyArray_DIM(obj, 0))

И вот как выглядит функция init_by_array:

extern void
init_by_array(rk_state *self, unsigned long init_key[], npy_intp key_length)
{
    /* was signed in the original code. RDH 12/16/2002 */
    npy_intp i = 1;
    npy_intp j = 0;
    unsigned long *mt = self->key;
    npy_intp k;

    init_genrand(self, 19650218UL);
    k = (RK_STATE_LEN > key_length ? RK_STATE_LEN : key_length);
    for (; k; k--) {
        /* non linear */
        mt[i] = (mt[i] ^ ((mt[i - 1] ^ (mt[i - 1] >> 30)) * 1664525UL))
            + init_key[j] + j;
        /* for > 32 bit machines */
        mt[i] &= 0xffffffffUL;
        i++;
        j++;
        if (i >= RK_STATE_LEN) {
            mt[0] = mt[RK_STATE_LEN - 1];
            i = 1;
        }
        if (j >= key_length) {
            j = 0;
        }
    }
    for (k = RK_STATE_LEN - 1; k; k--) {
        mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 30)) * 1566083941UL))
             - i; /* non linear */
        mt[i] &= 0xffffffffUL; /* for WORDSIZE > 32 machines */
        i++;
        if (i >= RK_STATE_LEN) {
            mt[0] = mt[RK_STATE_LEN - 1];
            i = 1;
        }
    }

    mt[0] = 0x80000000UL; /* MSB is 1; assuring non-zero initial array */
    self->gauss = 0;
    self->has_gauss = 0;
    self->has_binomial = 0;
}

Это по существу "пугает" состояние случайного числа в нелинейном хэш-подобном методе, используя каждое значение в пределах предоставленной последовательности значений затравки.

Ответ 4

В основном число гарантирует одинаковое "случайность" каждый раз.

Более правильно, число - это семя, которое может быть целым числом, массивом (или другой последовательностью) целых чисел любой длины или значением по умолчанию (none). Если seed нет, тогда случайное будет пытаться читать данные из /dev/urandom, если они доступны, или сделать семя от часов в противном случае.

Редактирование: в большинстве случаев, если ваша программа не является чем-то, что должно быть супер безопасным, не имеет значения, что вы выбираете. Если это так, не используйте эти методы - используйте os.urandom() или SystemRandom, если вам нужен криптографически безопасный генератор псевдослучайных чисел.

Наиболее важным понятием здесь является понимание псевдослучайности. Как только вы поймете эту идею, вы можете определить, действительно ли ваша программа нуждается в семени и т.д. Я бы рекомендовал прочитать здесь.

Ответ 5

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

Таким образом, вы можете представить это число как начальное значение для вычисления следующего числа, которое вы получаете от случайного генератора. Включение такого же значения приведет к тому, что ваша программа будет получать одинаковое "случайное" значение каждый раз, поэтому ваша программа станет детерминированной.

Как сказано в этом сообщении

они (numpy.random и random.random) используют последовательность Twister Mersenne для генерации своих случайных чисел, и они оба полностью детерминированы - то есть, если вы знаете несколько ключевых бит информации, можно предсказать с абсолютной уверенностью, какое число будет дальше.

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

Если ваши коды работают на процессоре Intel (или AMD с новейшими чипами), я также предлагаю вам проверить пакет RdRand, который использует команда cpu rdrand для сбора "истинной" (аппаратной) случайности.

работ: