Как использовать seed в любом генераторе
Перейти к содержимому

Как использовать seed в любом генераторе

  • автор:

Краеугольный камень псевдослучайности: с чего начинается поиск чисел

(с)

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

Когда речь заходит о генераторах случайных (или псевдослучайных) чисел, рассказ всегда строится вокруг поиска истинной случайности. Пока серьезные математики десятилетиями ведут дискуссии о том, что считать случайностью, в практическом отношении мы давно научились использовать «правильную» энтропию. Впрочем, «шум» — это лишь вершина айсберга.

С чего начать, если мы хотим распутать клубок самых сильных алгоритмов PRNG и TRNG? На самом деле, с какими бы алгоритмами вы не имели дело, все сводится к трем китам: seed, таблица предопределенных констант и математические формулы.

Каким бы ни был seed, еще есть алгоритмы, участвующие в генераторах истинных случайных чисел, и такие алгоритмы никогда не бывают случайными.

Что такое случайность

Первое подходящее определение случайной последовательности дал в 1966 году шведский статистик Пер Мартин-Лёф, ученик одного из крупнейших математиков XX века Андрея Колмогорова. Ранее исследователи пытались определить случайную последовательность как последовательность, которая проходила все тесты на случайность.

Основная идея Мартина-Лёфа заключалась в том, чтобы использовать теорию вычислимости для формального определения понятия теста случайности. Это контрастирует с идеей случайности в вероятности; в этой теории ни один конкретный элемент пространства выборки не может быть назван случайным.

«Случайная последовательность» в представлениях Мартина-Лёфа должна быть типичной, т.е. не должна обладать индивидуальными отличительными особенностями.

Было показано, что случайность Мартина-Лёфа допускает много эквивалентных характеристик, каждая из которых удовлетворяет нашему интуитивному представлению о свойствах, которые должны иметь случайные последовательности:

  • несжимаемость;
  • прохождение статистических тестов для случайности;
  • сложность создания прогнозов.

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

Seed: основа псевдослучайных алгоритмов

Первые алгоритмы формирования случайных чисел выполняли ряд основных арифметических действий: умножить, разделить, добавить, вычесть, взять средние числа и т.д. Сегодня такие мощные алгоритмы, как Fortuna и Yarrow (используется в FreeBSD, AIX, Mac OS X, NetBSD) выглядят как генераторы случайных чисел для параноиков. Fortuna, например, это криптографический генератор, в котором для защиты от дискредитации после выполнения каждого запроса на случайные данные в размере 220 байт генерируются еще 256 бит псевдослучайных данных и используются в качестве нового ключа шифрования — старый ключ при этом каждый раз уничтожается.

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

Функция rand () является простейшей из функций генерации случайных чисел в C.

#include #include int main() < int r,a,b; puts("100 Random Numbers"); for(a=0;a<20;a++) < for(b=0;b<5;b++) < r=rand(); printf("%dt",r); >putchar('n'); > return(0); >

В этом примере рандома используется вложенный цикл для отображения 100 случайных значений. Функция rand () хороша при создании множества случайных значений, но они являются предсказуемыми. Чтобы сделать вывод менее предсказуемым, вам нужно добавить seed в генератор случайных чисел — это делается с помощью функции srand ().

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

#include #include int main() < unsigned seed; int r,a,b; printf("Input a random number seed: "); scanf("%u",&seed); srand(seed); for(a=0;a<20;a++) < for(b=0;b<5;b++) < r=rand(); printf("%dt",r); >putchar('n'); > return(0); >

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

Вот пример простой формулы случайного числа из «классики» — книги «Язык программирования C» Кернигана и Ричи, первое издание которой вышло аж в 1978 году:

int rand() < random_seed = random_seed * 1103515245 +12345; return (unsigned int)(random_seed / 65536) % 32768; >

Эта формула предполагает существование переменной, называемой random_seed, изначально заданной некоторым числом. Переменная random_seed умножается на 1 103 535 245, а затем 12 345 добавляется к результату; random_seed затем заменяется этим новым значением. Это на самом деле довольно хороший генератор псевдослучайных чисел. Если вы используете его для создания случайных чисел от 0 до 9, то первые 20 значений, которые он вернет при seed = 10, будут такими:

44607423505664567674

Если у вас есть 10 000 значений от 0 до 9, то распределение будет следующим:

0 — 10151 — 10242 — 10483 — 9964 — 9885 — 10016 — 9967 — 10068 — 9659 — 961

Любая формула псевдослучайных чисел зависит от начального значения. Если вы предоставите функции rand() seed 10 на одном компьютере, и посмотрите на поток чисел, которые она производит, то результат будет идентичен «случайной последовательности», созданной на любом другом компьютере с seed 10.

К сожалению, у генератора случайных чисел есть и другая слабость: вы всегда можете предсказать, что будет дальше, основываясь на том, что было раньше. Чтобы получить следующее число в последовательности, мы должны всегда помнить последнее внутреннее состояние генератора — так называемый state. Без state мы будем снова делать одну и ту же математическую операцию с одинаковыми числами, чтобы получить тот же ответ.

Как сделать seed уникальным для каждого случая? Самое очевидное решение — добавить в вычисления текущее системное время. Сделать это можно с помощью функции time().

#include #include #include int main() < int r,a,b; srand((unsigned)time(NULL)); for(a=0;a<20;a++) < for(b=0;b<5;b++) < r=rand(); printf("%dt",r); >putchar('n'); > return(0); >

Функция time() возвращает информацию о текущем времени суток, значение, которое постоянно изменяется. При этом метод typecasting гарантирует, что значение, возвращаемое функцией time(), является целым числом.

Итак, в результате добавления «случайного» системного времени функция rand() генерирует значения, которые являются более случайными, чем мы получили в первом примере.

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

В .net framework есть функция System.Security.Cryptography.RandomNumberGenerator, где в расчетах учитываются следующие факторы:

  • ID текущего процесса;
  • текущий ID потока;
  • количество отсчетов с момента загрузки;
  • текущее время;
  • различные высокоточные счетчики производительности процессора;
  • MD4-хэш среды пользователя (имя пользователя, имя компьютера и т.д.).

Но опять же, все эти числа не случайны.

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

Период (цикл) генератора

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

Xn+1 = (aXn + c) mod m, где m — модуль, a — множитель, c — приращение, mod — операция взятия остатка от деления. Причем m > 0, 0 < a ≤ m, 0 < c ≤ m, также задается начальное значение X0: 0 < X0 ≤ m.

Линейный конгруэнтный метод дает нам повторяющиеся последовательности — конгруэнтная последовательность всегда образует «петли». Этот цикл (период), повторяющийся бесконечное число раз — свойство всех последовательностей вида Xn+1 = f(n).

В языке С линейно-конгруэнтный метод реализован в уже знакомой вам функции rand():

#define RAND_MAX 32767 unsigned long next=1; int rand(void) < next=next*1103515245+12345; return((unsigned int)(next/65536)%RAND_MAX);>void srand(unsigned int seed)

Что вообще такое цикл с точки зрения случайных чисел? Период — это количество чисел, которое генерируется до того, как они вернутся в той же последовательности. Для примера число периодов в шифре А5 в среднем составляет 2 23 , а сложность атаки 240, что позволяет взломать его на любом персональном компьютере.

Рассмотрим случай, когда seed равен 1, а период — 100 (на языке Haskell):

random i = (j, ans) where j = 7 * i `mod` 101 ans = (j — 1) `mod` 10 + 1 — just the ones place, but 0 means 10

В результате мы получим следующий ответ:

random 1 —> ( 7, 7) random 7 —> (49, 9) random 49 —> (40, 10) random 40 —> (78, 8) random 78 —> (41, 1) random 41 —> (85, 5) random 85 —> (90, 10) random 90 —> (24, 4) random 24 —> (67, 7) random 67 —> (65, 5) random 65 —> (51, 1)

Это лишь пример и подобную структуру в реальной жизни не используют. В Haskell, если вы хотите построить случайную последовательность, можно воспользоваться следующим кодом:

random :: StdGen —> (Int, StdGen)

Выбор случайного Int дает вам обратно Int и новый StdGen, который вы можете использовать для получения более псевдослучайных чисел. Многие языки программирования, включая Haskell, имеют генераторы случайных чисел, которые автоматически запоминают свое состояние (в Haskell это randomIO).

Чем больше величина периода, тем выше надежность создания хороших случайных значений, однако даже с миллиардами циклов крайне важно использовать надежный seed. Реальные генераторы случайных чисел обычно используют атмосферный шум (поставьте сюда любое физическое явление — от движения мыши пользователя до радиоактивного распада), но мы можем и схитрить программным методом, добавив в seed асинхронные потоки различного мусора, будь то длины интервалов между последними heartbeat потоками или временем ожидания mutual exclusion (а лучше добавить все вместе).

Истинная случайность бит

Итак, получив seed с примесью данных от реальных физических явлений (либо максимально усложнив жизнь будущему взломщику самым большим набором потоков программного мусора, который только сможем придумать), установив state для защиты от ошибки повтора значений и добавив криптографических алгоритмов (или сложных математических задач), мы получим некоторый набор данных, который будем считать случайной последовательностью. Что дальше?

Дальше мы возвращаемся к самому началу, к одному из фундаментальных требований — тестам.

Национальный институт стандартов и технологий США вложил в «Пакет статистических тестов для случайных и псевдослучайных генераторов чисел для криптографических приложений» 15 базовых проверок. Ими можно и ограничиться, но этот пакет вовсе не является «вершиной» проверки случайности.

Одни из самых строгих статистических тестов предложил профессор Джордж Марсалья из Университета штата Флорида. «Тесты diehard» включают 17 различных проверок, некоторые из них требуют очень длинных последовательностей: минимум 268 мегабайт.

Случайность можно проверить с помощью библиотеки TestU01, представленной Пьером Л’Экуйе и Ричардом Симардом из Монреальского университета, включающей классические тесты и некоторые оригинальные, а также посредством общедоступной библиотеки SPRNG.

Еще один полезный сервис для количественного измерения случайности.

Модуль Random для генерации случайных чисел в Python

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

  • Для целых чисел есть выбор одного из диапазона.
  • Для последовательностей — выбор случайного элемента, функция случайной сортировки списка и функция случайного выбора нескольких элементов из последовательности.
  • Есть функции для вычисления однородных, нормальных (Гауссовских), логнормальных, отрицательных экспоненциальных, гамма и бета распределений.
  • Для генерации распределений углов доступно распределение фон Мизеса.

Почти все функции модуля зависят от основной функции random() , которая генерирует случайным образом чисто с плавающей точкой(далее float) равномерно в полуоткрытом диапазоне [0.0, 1.0).

Python использует Mersenne Twister в качестве основного генератора. Он производит 53-битные точные float и имеет период 2**19937-1. Основная его реализация в C быстрая и многопоточная. Mersenne Twister один из наиболее широко протестированных генераторов случайных чисел. Однако, будучи полностью детерминированным, он подходит не для любых целей, особенно для криптографических.

Модуль random так же предоставляет класс SystemRandom . Этот класс использует системную функцию os.urandom() для генерации случайных чисел из источников, которые предоставляет операционная система.

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

Функции для целых чисел

random.randrange(stop)
random.randrange(start, stop[, step])
Возвращает случайно выбранный элемент из range(start, stop, step) . Это эквивалентно choice(range(start, stop, step)) , но не создает объект диапазона.

Модуль random

Python 3 логотип

Модуль random предоставляет функции для генерации случайных чисел, букв, случайного выбора элементов последовательности.

random.seed([X], version=2) — инициализация генератора случайных чисел. Если X не указан, используется системное время.

random.getstate() — внутреннее состояние генератора.

random.setstate(state) — восстанавливает внутреннее состояние генератора. Параметр state должен быть получен функцией getstate().

random.getrandbits(N) — возвращает N случайных бит.

random.randrange(start, stop, step) — возвращает случайно выбранное число из последовательности.

random.randint(A, B) — случайное целое число N, A ≤ N ≤ B.

random.choice(sequence) — случайный элемент непустой последовательности.

random.shuffle(sequence, [rand]) — перемешивает последовательность (изменяется сама последовательность). Поэтому функция не работает для неизменяемых объектов.

random.sample(population, k) — список длиной k из последовательности population.

random.random() — случайное число от 0 до 1.

random.uniform(A, B) — случайное число с плавающей точкой, A ≤ N ≤ B (или B ≤ N ≤ A).

random.triangular(low, high, mode) — случайное число с плавающей точкой, low ≤ N ≤ high. Mode — распределение.

random.betavariate(alpha, beta) — бета-распределение. alpha>0, beta>0. Возвращает от 0 до 1.

random.expovariate(lambd) — экспоненциальное распределение. lambd равен 1/среднее желаемое. Lambd должен быть отличным от нуля. Возвращаемые значения от 0 до плюс бесконечности, если lambd положительно, и от минус бесконечности до 0, если lambd отрицательный.

random.gammavariate(alpha, beta) — гамма-распределение. Условия на параметры alpha>0 и beta>0.

random.gauss(значение, стандартное отклонение) — распределение Гаусса.

random.lognormvariate(mu, sigma) — логарифм нормального распределения. Если взять натуральный логарифм этого распределения, то вы получите нормальное распределение со средним mu и стандартным отклонением sigma. mu может иметь любое значение, и sigma должна быть больше нуля.

random.normalvariate(mu, sigma) — нормальное распределение. mu — среднее значение, sigma — стандартное отклонение.

random.vonmisesvariate(mu, kappa) — mu — средний угол, выраженный в радианах от 0 до 2π, и kappa — параметр концентрации, который должен быть больше или равен нулю. Если каппа равна нулю, это распределение сводится к случайному углу в диапазоне от 0 до 2π.

random.paretovariate(alpha) — распределение Парето.

random.weibullvariate(alpha, beta) — распределение Вейбулла.

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

Для вставки кода на Python в комментарий заключайте его в теги

random — Генерация псевдослучайных чисел¶

Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.

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

На реальных случаев есть функции для вычисления равномерного, нормального (гауссовского), логнормального, отрицательного экспоненциального, гамма- и бета-распределений. Для генерации распределений углов доступно распределение Фон Мизеса.

Почти все функции модуля зависят от базовой функции random() , которая равномерно генерирует случайное число с плавающей запятой в полуоткрытом диапазоне [0.0, 1.0). Python использует Твистер Мерсенна в качестве основного генератора. Он производит 53-битные точные числа с плавающей запятой и имеет период 2**19937-1. Базовая реализация на C является быстрой и потокобезопасной. Твистер Мерсенна — один из наиболее тщательно протестированных существующих генераторов случайных чисел. Однако, будучи полностью детерминированным, он не подходит для всех целей и совершенно непригоден для криптографических целей.

Функции, предоставляемые этим модулем, на самом деле являются связанными методами скрытого экземпляра класса random.Random . Вы можете создать свои собственные экземпляры Random , чтобы получить генераторы, которые не разделяют состояние.

Класс Random также можно разделить на подклассы, если вы хотите использовать другой базовый генератор собственной разработки: в этом случае переопределите методы random() , seed() , getstate() и setstate() . Необязательно, новый генератор может предоставить метод getrandbits() , который позволяет randrange() производить выборки в произвольно большом диапазоне.

Модуль random также предоставляет класс SystemRandom , который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставленных операционной системой.

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

М. Мацумото и Т. Нисимура, «Твистер Мерсенна: 623-мерно равнораспределённый генератор однородных псевдослучайных чисел», ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, январь, стр. 3–30 1998.

Рецепт дополнительного умножения с переносом для совместимого альтернативного генератора случайных чисел с большим периодом и сравнительно простыми операциями обновления.

Бухгалтерские функции¶

random. seed ( a=None, version=2 ) ¶

Инициализировать генератор случайных чисел.

Если a пропущен или None , используется текущее системное время. Если источники случайности предоставляются операционной системой, они используются вместо системного времени (подробности о доступности см. в функции os.urandom() ).

Если a — это int, он используется напрямую.

В версии 2 (по умолчанию) объект str , bytes или bytearray преобразуется в int , и используются все его биты.

В версии 1 (предназначенной для воспроизведения случайных последовательностей из более старых версий Python) алгоритм для str и bytes генерирует более узкий диапазон начальных чисел.

Изменено в версии 3.2: Перешёл на схему версии 2, в которой используются все биты начального числа строки.

random. getstate ( ) ¶

Возвращает объект, фиксирующий текущее внутреннее состояние генератора. Этот объект можно передать в setstate() для восстановления состояния.

random. setstate ( state ) ¶

state должен был быть получен из предыдущего вызова getstate() , а setstate() восстанавливает внутреннее состояние генератора до того, каким оно было на момент вызова getstate() .

random. getrandbits ( k ) ¶

Возвращает целое число Python со случайными битами k. Этот метод поставляется с генератором Твистер Мерсенна, и некоторые другие генераторы также могут предоставлять его как дополнительную часть API. Если доступно, getrandbits() позволяет randrange() обрабатывать произвольно большие диапазоны.

Функции для целых чисел¶

random. randrange ( stop ) ¶ random. randrange ( start, stop [ , step ] )

Возвращает случайно выбранный элемент из range(start, stop, step) . Это эквивалентно choice(range(start, stop, step)) , но фактически не создаёт объект диапазона.

Шаблон позиционного аргумента совпадает с шаблоном range() . Ключевые аргументы не должны использоваться, потому что функция может использовать их неожиданным образом.

Изменено в версии 3.2: randrange() более сложен в отношении создания одинаково распределенных значений. Раньше использовался такой стиль, как int(random()*n) , который мог давать немного неравномерное распределение.

random. randint ( a, b ) ¶

Возвращает случайное целое число N, такое что a

Функции для последовательностей¶

random. choice ( seq ) ¶

Возвращает случайный элемент из непустой последовательности seq. Если seq пуст, вызывает IndexError .

random. choices ( population, weights=None, *, cum_weights=None, k=1 ) ¶

Возвращает список элементов размера k, выбранных из population, с заменой. Если population пуст, вызывает IndexError .

Если указана последовательность weights, выбор выполняется в соответствии с относительными весами. В качестве альтернативы, если дана последовательность cum_weights, выбор выполняется в соответствии с совокупными весами (возможно, вычисленными с использованием itertools.accumulate() ). Например, относительные веса [10, 5, 30, 5] эквивалентны совокупным весам [10, 15, 45, 50] . Внутренне относительные веса преобразуются в кумулятивные веса перед выполнением выбора, поэтому предоставление кумулятивных весов экономит работу.

Если не указаны ни weights, ни cum_weights, выбор выполняется с равной вероятностью. Если предоставляется последовательность весов, она должна быть той же длины, что и последовательность population. Это TypeError , чтобы указать как weights, так и cum_weights.

weights или cum_weights могут использовать любой числовой тип, который взаимодействует со значениями float , возвращаемыми random() (включая целые числа, числа с плавающей запятой и дроби, но исключая десятичные числа). Предполагается, что веса неотрицательны.

Для заданного начального числа функция choices() с равным весом обычно производит другую последовательность, чем повторные вызовы choice() . Алгоритм, используемый choices() , использует арифметику с плавающей запятой для обеспечения внутренней согласованности и скорости. Алгоритм, используемый choice() , по умолчанию использует целочисленную арифметику с повторным выбором, чтобы избежать небольших смещений из-за ошибки округления.

Добавлено в версии 3.6.

random. shuffle ( x [ , random ] ) ¶

Перемешивает последовательность x на месте.

Необязательный аргумент random — это функция с 0 аргументами, возвращающая случайное число с плавающей запятой в [0.0, 1.0); по умолчанию это функция random() .

Чтобы перемешать неизменяемую последовательность и вернуть новый перемешанный список, использовать вместо этого sample(x, k=len(x)) .

Обратите внимание, что даже для небольшого len(x) общее количество перестановок x может быстро вырасти больше, чем период большинства генераторов случайных чисел. Это означает, что большинство перестановок длинной последовательности никогда не могут быть сгенерированы. Например, последовательность длиной 2080 является наибольшей, которая может соответствовать периоду генератора случайных чисел Мерсенна Твистера.

random. sample ( population, k ) ¶

Возвращает список уникальных элементов длиной k, выбранных из последовательности или набора population. Используется для случайной выборки без замены.

Возвращает новый список, содержащий элементы из population, оставляя исходную population неизменной. Результирующий список находится в порядке выбора, так что все субсрезы (sub-slices) также будут действительными случайными выборками. Это позволяет разделить победителей розыгрыша (образец) на обладателей главного приза и занявших второе место (фрагменты).

Элементы population не обязательно должны быть хэшируемы или уникальными. Если генеральная совокупность содержит повторы, то каждое вхождение является возможным выбором в выборке.

Чтобы выбрать образец из диапазона целых чисел, использовать в качестве аргумента объект range() . Это особенно быстро и эффективно для выборки из большой population: sample(range(10000000), k=60) .

Если размер выборки больше, чем размер генеральной population, вызывается ValueError .

Распределения с действительными значениями¶

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

Возвращает следующее случайное число с плавающей запятой в диапазоне [0.0, 1.0).

Возвращает случайное число с плавающей запятой N, такое, что a

Значение конечной точки b может или не может быть включено в диапазон в зависимости от округления с плавающей запятой в уравнении a + (b-a) * random() .

Возвращает случайное число с плавающей запятой N, такое, что low mode между этими границами. Границы low и high по умолчанию равны нулю и единице. Аргумент mode по умолчанию равен средней точке между границами, что дает симметричное распределение.

random. betavariate ( alpha, beta ) ¶

Бета-распространение. Условия для параметров: alpha > 0 и beta > 0 . Возвращаемые значения находятся в диапазоне от 0 до 1.

random. expovariate ( lambd ) ¶

Экспоненциальное распределение. lambd делится на желаемое среднее значение 1,0. Оно должно быть ненулевым. (Параметр будет называться «лямбда», но это зарезервированное слово в Python.) Возвращаемые значения варьируются от 0 до положительной бесконечности, если lambd положительное значение, и от отрицательной бесконечности до 0, если lambd отрицательное.

random. gammavariate ( alpha, beta ) ¶

Гамма-распределение. (Не гамма-функция!) Условия для параметров: alpha > 0 и beta > 0 .

Функция распределения вероятностей равна:

x ** (alpha - 1) * math.exp(-x / beta) pdf(x) = -------------------------------------- math.gamma(alpha) * beta ** alpha 

random. gauss ( mu, sigma ) ¶

Гауссово распределение. mu — среднее значение, а sigma — стандартное отклонение. Немного быстрее, чем функция normalvariate() , определенная ниже.

random. lognormvariate ( mu, sigma ) ¶

Журнал нормального распределения. Если вы возьмете натуральный логарифм этого распределения, вы получить нормальное распределение со средним значением mu и стандартным отклонением sigma. mu может иметь любое значение, а sigma должно быть больше нуля.

random. normalvariate ( mu, sigma ) ¶

Нормальное распределение. mu — это среднее значение, а sigma — стандартное отклонение.

random. vonmisesvariate ( mu, kappa ) ¶

mu — средний угол, выраженный в радианах от 0 до 2*pi, а kappa — параметр концентрации, который должен быть больше или равен нулю. Если kappa равно нулю, это распределение уменьшается до равномерного случайного угла в диапазоне от 0 до 2*pi.

random. paretovariate ( alpha ) ¶

Распределение Парето. alpha — параметр формы.

random. weibullvariate ( alpha, beta ) ¶

Распределение Вейбулла. alpha — это параметр масштаба, а beta — параметр формы.

Альтернативный генератор¶

class random. Random ( [ seed ] ) ¶

Класс, реализующий генератор псевдослучайных чисел по умолчанию, используемый модулем random .

class random. SystemRandom ( [ seed ] ) ¶

Класс, использующий функцию os.urandom() для генерации случайных чисел из источников, предоставленных операционной системой. Доступно не во всех системах. Не зависит от состояния программного обеспечения, и последовательности не воспроизводятся. Соответственно, метод seed() не действует и игнорируется. Методы getstate() и setstate() вызывают NotImplementedError , если они вызываются.

Примечания по воспроизводимости¶

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

Большинство алгоритмов и функций заполнения модуля random могут изменяться в разных версиях Python, но два аспекта гарантированно не изменятся:

  • Если добавлен новый метод посева, то будет предложена сеялка с обратной совместимостью.
  • Метод генератора random() будет продолжать производить ту же последовательность, когда совместимой сеялке будет передано то же самое семя.

Примеры и рецепты¶

>>> random() # случайный float: 0.0 0.37444887175646646 >>> uniform(2.5, 10.0) # случайный float: 2.5 3.1800146073117523 >>> expovariate(1 / 5) # Интервал между прибытиями в среднем 5 секунд 5.148957571865031 >>> randrange(10) # Целое число от 0 до 9 включительно 7 >>> randrange(0, 101, 2) # Четное целое число от 0 до 100 включительно 26 >>> choice(['win', 'lose', 'draw']) # Один случайный элемент из последовательности 'draw' >>> deck = 'ace two three four'.split() >>> shuffle(deck) # Перемешать список >>> deck ['four', 'two', 'ace', 'three'] >>> sample([10, 20, 30, 40, 50], k=4) # Четыре образца без замены [40, 10, 50, 30] 
>>> # Шесть вращений колеса рулетки (взвешенная выборка с заменой) >>> choices(['red', 'black', 'green'], [18, 18, 2], k=6) ['red', 'green', 'black', 'black', 'red', 'black'] >>> # Раздача 20 карт без замены из колоды из 52 игральных карт >>> # и определить пропорцию карточек с 10 значением >>> # (a ten, jack, queen, or king). >>> deck = collections.Counter(tens=16, low_cards=36) >>> seen = sample(list(deck.elements()), k=20) >>> seen.count('tens') / 20 0.15 >>> # Оценить вероятность получения 5 или более "орлов" за 7 подбрасываний >>> # смещенной монеты, которая оседает на "орлах" 60% времени. >>> def trial(): . return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5 . >>> sum(trial() for i in range(10_000)) / 10_000 0.4169 >>> # Вероятность того, что медиана из 5 выборок окажется в двух средних квартилях >>> def trial(): . return 2_500  sorted(choices(range(10_000), k=5))[2]  7_500 . >>> sum(trial() for i in range(10_000)) / 10_000 0.7958 

Пример статистического бутстрапа с использованием повторной выборки с заменой для оценки доверительного интервала для среднего значения выборки:

# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm from statistics import fmean as mean from random import choices data = [41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95] means = sorted(mean(choices(data, k=len(data))) for i in range(100)) print(f'Выборочное среднее значение mean(data):.1f> имеющее 90% доверительный ' f'интервал от means[5]:.1f> до means[94]:.1f>') 

Пример тест перестановки передискретизации для определения статистической значимости или p-значение наблюдаемой разницы между эффектами препарата и плацебо:

# Пример из книги "Статистика проста" Денниса Шаши и Аманды Уилсон from statistics import fmean as mean from random import shuffle drug = [54, 73, 53, 70, 73, 68, 52, 65, 65] placebo = [54, 51, 58, 44, 55, 52, 42, 47, 58, 46] observed_diff = mean(drug) - mean(placebo) n = 10_000 count = 0 combined = drug + placebo for i in range(n): shuffle(combined) new_diff = mean(combined[:len(drug)]) - mean(combined[len(drug):]) count += (new_diff >= observed_diff) print(f'n> перестановки меток привели только к count> экземпляров с разницей') print(f'по крайней мере, такая же экстремальная, как наблюдаемая разница observed_diff:.1f>.') print(f'Одностороннее p-значение count / n:.4f> приводит нас к отклонению нулевого') print(f'гипотеза о том, что нет никакой разницы между препаратом и плацебо.') 

Моделирование времени прибытия и доставки услуг для многосерверной очереди:

from heapq import heappush, heappop from random import expovariate, gauss from statistics import mean, median, stdev average_arrival_interval = 5.6 average_service_time = 15.0 stdev_service_time = 3.5 num_servers = 3 waits = [] arrival_time = 0.0 servers = [0.0] * num_servers # время, когда каждый сервер становится доступным for i in range(100_000): arrival_time += expovariate(1.0 / average_arrival_interval) next_server_available = heappop(servers) wait = max(0.0, next_server_available - arrival_time) waits.append(wait) service_duration = gauss(average_service_time, stdev_service_time) service_completed = arrival_time + wait + service_duration heappush(servers, service_completed) print(f'Среднее ожидание: mean(waits):.1f>. Stdev ожидание: stdev(waits):.1f>.') print(f'Медианное ожидание: median(waits):.1f>. Макс. ожидание: max(waits):.1f>.') 

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

Моделирование экономики моделирование рынка с помощью Питера Норвига, которое показывает эффективное использование многих инструментов и распределений, предоставляемых этим модулем (гаусс, равномерное, сэмплирование, бетавариант, перемешивание, треугольное и рандрандж).

Знакомство с теорией вероятностей (с использованием Python), учебник Питера Норвига, покрывающий основы теории вероятности, как написать моделирования, и как выполнить анализ данных.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *