random — Генерация псевдослучайных чисел
Исходный код: Lib/random.py
Этот модуль реализует генераторы псевдослучайных чисел для различных распределений.
Для целых чисел имеется равномерный выбор из диапазона. Для последовательностей имеется равномерный выбор случайного элемента, функция для генерации случайной перестановки списка на месте и функция для случайной выборки без возвращения.
На вещественной оси имеются функции для вычисления равномерного, нормального (гауссова), логарифмически нормального, отрицательно экспоненциального, гамма и бета распределений. Для генерации распределений углов доступно распределение Винера.
Практически все функции модуля зависят от базовой функции random(), которая генерирует случайное вещественное число равномерно в полуоткрытом интервале [0.0, 1.0). Python использует Mersenne Twister в качестве основного генератора. Он производит с плавающей запятой с точностью 53 бита и имеет период 2**19937-1. Подлежащая реализация на C является быстрой и потокобезопасной. Mersenne Twister — один из наиболее широко протестированных генераторов псевдослучайных чисел, которые существуют. Однако, будучи полностью детерминированным, он не подходит для всех целей и совершенно непригоден для криптографических целей.
Функции, предоставляемые этим модулем, фактически являются связанными методами скрытого экземпляра класса random.Random. Вы можете создать свои экземпляры класса Random, чтобы получить генераторы, которые не используют общее состояние.
Класс Random также может быть расширен, если вы хотите использовать другой базовый генератор собственной разработки: в этом случае переопределите методы random(), seed(), getstate(), и setstate(). Дополнительно, новый генератор может предоставить метод getrandbits() — это позволяет randrange() выполнять выборки из произвольно большого диапазона.
Модуль random также предоставляет класс SystemRandom, который использует системную функцию os.urandom() для генерации случайных чисел из источников, предоставляемых операционной системой.
Предупреждение
Генераторы псевдослучайных чисел этого модуля не должны использоваться для целей безопасности. Для целей безопасности или криптографии см. модуль secrets.
См. также
М. Мацумото и Т. Нисимура, «Mersenne Twister: A 623-dimensionally equidistributed uniform pseudorandom number generator», ACM Transactions on Modeling and Computer Simulation Vol. 8, No. 1, январь, стр. 3–30 1998.
Рецепт Complementary-Multiply-with-Carry для совместимого альтернативного генератора псевдослучайных чисел с большим периодом и сравнительно простыми операциями обновления.
9.6.1. Функции ведения записей
-
random.seed(a=None, version=2) -
Инициализирует генератор псевдослучайных чисел.
Если a опущено или
None, используется текущее системное время. Если источники случайности предоставляются операционной системой, они используются вместо системного времени (см. функциюos.urandom()для получения подробной информации о доступности).Если a — целое число, оно используется непосредственно.
С версией 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 случайными битами. Этот метод предоставляется генератором MersenneTwister, и некоторые другие генераторы также могут его предоставить как необязательную часть API. Когда доступен,
getrandbits()позволяетrandrange()обрабатывать произвольно большие диапазоны.
9.6.2. Функции для целых чисел
-
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 <= N <= b. Псевдоним дляrandrange(a, b+1).
9.6.3. Функции для последовательностей
-
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 не указаны, выборки производятся с равной вероятностью. Если указана последовательность weights, она должна иметь тот же размер, что и последовательность population. Указание weights и cum_weights одновременно приводит к ошибке
TypeError.Последовательности weights или cum_weights могут использовать любой числовой тип, взаимодействующий со значениями с плавающей запятой
float, возвращаемыми функциейrandom()(включая целые числа, числа с плавающей запятой и дроби, но исключая десятичные числа).Новое в версии 3.6.
-
random.shuffle(x[, random]) -
Перемешивает последовательность x на месте.
Необязательный аргумент random — это функция без аргументов, возвращающая случайное число с плавающей запятой в диапазоне [0.0, 1.0); по умолчанию это функция
random().Для перемешивания неизменяемой последовательности и возврата нового перемешанного списка используйте
sample(x, k=len(x))вместо этого.Обратите внимание, что даже для небольших
len(x), общее количество перестановок x может быстро стать больше периода большинства генераторов псевдослучайных чисел. Это означает, что большинство перестановок длинной последовательности могут быть не сгенерированы. Например, последовательность длиной 2080 является самой длинной, которая может поместиться в период генератора псевдослучайных чисел Mersenne Twister.
-
random.sample(population, k) -
Возвращает список длиной k, содержащий уникальные элементы, выбранные из последовательности или множества
population. Используется для случайного выбора без возвращения.Возвращает новый список, содержащий элементы из
population, не изменяя исходнуюpopulation. Результирующий список отсортирован по порядку выбора, так что все подсписки также будут являться допустимыми случайными выборками. Это позволяет разделить победителей лотереи (выборка) на победителей главного приза и призёров второго места (подсписки).Элементы
populationне обязательно должны быть хешируемыми или уникальными. Еслиpopulationсодержит повторяющиеся элементы, то каждое вхождение является возможным выбором для выборки.Для выбора выборки из диапазона целых чисел используйте объект
range()в качестве аргумента. Это особенно быстро и эффективно с точки зрения памяти для выборки из большойpopulation:sample(range(10000000), k=60).Если размер выборки больше, чем размер
population, генерируется исключениеValueError.
9.6.4. Дискретные распределения
Следующие функции генерируют конкретные распределения вещественных значений. Параметры функций названы в соответствии с соответствующими переменными в уравнении распределения, как используется в общепринятой математической практике; большинство этих уравнений можно найти в любом учебнике по статистике.
-
random.random() -
Возвращает следующее случайное число с плавающей точкой в диапазоне [0.0, 1.0).
-
random.uniform(a, b) -
Возвращает случайное число с плавающей точкой N, такое что
a <= N <= bдляa <= bиb <= N <= aдляb < a.Значение конечной точки
bможет или не может быть включено в диапазон в зависимости от округления с плавающей точкой в уравненииa + (b-a) * random().
-
random.triangular(low, high, mode) -
Возвращает случайное число с плавающей точкой N, такое что
low <= N <= highи с заданным mode между этими границами. Границы low и high по умолчанию равны нулю и единице. Аргумент mode по умолчанию равен середине между границами, что даёт симметричное распределение.
-
random.betavariate(alpha, beta) -
Бета-распределение. Условия для параметров
alpha > 0иbeta > 0. Возвращаемые значения находятся в диапазоне от 0 до 1.
-
random.expovariate(lambd) -
Экспоненциальное распределение. lambd равно 1.0, делённому на желаемое среднее значение. Оно должно быть ненулевым. (Параметр назывался бы «lambda», но это зарезервированное слово в 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 — параметр формы.
9.6.5. Альтернативный генератор
-
class random.SystemRandom([seed]) -
Класс, использующий функцию
os.urandom()для генерации случайных чисел из источников, предоставляемых операционной системой. Не доступен на всех системах. Не зависит от состояния программного обеспечения, а последовательности не воспроизводимы. Соответственно, методseed()не имеет эффекта и игнорируется. Методыgetstate()иsetstate()генерируютNotImplementedErrorпри вызове.
9.6.6. Замечания о воспроизводимости
Иногда бывает полезно иметь возможность воспроизвести последовательности, создаваемые генератором псевдослучайных чисел. Используя одно и то же значение seed, та же последовательность должна воспроизводиться из запуска в запуск, если не выполняется несколько потоков.
Большинство алгоритмов и функций инициализации случайных чисел в модуле random могут меняться в разных версиях Python, но два аспекта гарантированно не изменятся:
- Если добавляется новый метод инициализации, то будет предложен обратный совместимый инициализатор.
- Метод
random()генератора продолжит создавать ту же последовательность, когда совместимый инициализатор получит тот же seed.
9.6.7. Примеры и рецепты
Основные примеры:
>>> random() # Random float: 0.0 <= x < 1.0 0.37444887175646646 >>> uniform(2.5, 10.0) # Random float: 2.5 <= x < 10.0 3.1800146073117523 >>> expovariate(1 / 5) # Interval between arrivals averaging 5 seconds 5.148957571865031 >>> randrange(10) # Integer from 0 to 9 inclusive 7 >>> randrange(0, 101, 2) # Even integer from 0 to 100 inclusive 26 >>> choice(['win', 'lose', 'draw']) # Single random element from a sequence 'draw' >>> deck = 'ace two three four'.split() >>> shuffle(deck) # Shuffle a list >>> deck ['four', 'two', 'ace', 'three'] >>> sample([10, 20, 30, 40, 50], k=4) # Four samples without replacement [40, 10, 50, 30]
Моделирования:
>>> # Six roulette wheel spins (weighted sampling with replacement)
>>> choices(['red', 'black', 'green'], [18, 18, 2], k=6)
['red', 'green', 'black', 'black', 'red', 'black']
>>> # Deal 20 cards without replacement from a deck of 52 playing cards
>>> # and determine the proportion of cards with a ten-value
>>> # (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
>>> # Estimate the probability of getting 5 or more heads from 7 spins
>>> # of a biased coin that settles on heads 60% of the time.
>>> trial = lambda: choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5
>>> sum(trial() for i in range(10000)) / 10000
0.4169
>>> # Probability of the median of 5 samples being in middle two quartiles
>>> trial = lambda : 2500 <= sorted(choices(range(10000), k=5))[2] < 7500
>>> sum(trial() for i in range(10000)) / 10000
0.7958
Пример статистического бутстрепа с помощью ресэмплинга с возвращением для оценки доверительного интервала для среднего значения выборки размером пять:
# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm
from statistics import mean
from random import choices
data = 1, 2, 4, 4, 10
means = sorted(mean(choices(data, k=5)) for i in range(20))
print(f'The sample mean of {mean(data):.1f} has a 90% confidence '
f'interval from {means[1]:.1f} to {means[-2]:.1f}')
Пример перестановки с ресэмплингом для определения статистической значимости или p-значения наблюдаемого различия между эффектами лекарства и плацебо:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson
from statistics import 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 = 10000
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} label reshufflings produced only {count} instances with a difference')
print(f'at least as extreme as the observed difference of {observed_diff:.1f}.')
print(f'The one-sided p-value of {count / n:.4f} leads us to reject the null')
print(f'hypothesis that there is no difference between the drug and the placebo.')
Моделирование времени прибытия и выполнения обслуживания в очереди с одним сервером:
from random import expovariate, gauss
from statistics import mean, median, stdev
average_arrival_interval = 5.6
average_service_time = 5.0
stdev_service_time = 0.5
num_waiting = 0
arrivals = []
starts = []
arrival = service_end = 0.0
for i in range(20000):
if arrival <= service_end:
num_waiting += 1
arrival += expovariate(1.0 / average_arrival_interval)
arrivals.append(arrival)
else:
num_waiting -= 1
service_start = service_end if num_waiting else arrival
service_time = gauss(average_service_time, stdev_service_time)
service_end = service_start + service_time
starts.append(service_start)
waits = [start - arrival for arrival, start in zip(arrivals, starts)]
print(f'Mean wait: {mean(waits):.1f}. Stdev wait: {stdev(waits):.1f}.')
print(f'Median wait: {median(waits):.1f}. Max wait: {max(waits):.1f}.')
См. также
Статистика для хакеров — видео-урок Джейка Вандерпласа по статистическому анализу, используя всего несколько основных концепций, включая моделирование, выборку, перемешивание и перекрестную проверку.
Моделирование экономики — моделирование рынка Питера Норвига, которое демонстрирует эффективное использование многих инструментов и распределений, предоставляемых этим модулем (gauss, uniform, sample, betavariate, choice, triangular и randrange).
Конкретное введение в теорию вероятностей (используя Python) — учебник Питера Норвига, охватывающий основы теории вероятностей, как писать моделирования и как проводить анализ данных с помощью Python.
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/random.html