вторник, 29 сентября 2020 г.

Библиотека Random. Генерация случайных чисел в Python

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

От создания фиктивных данных до перетасовки данных для целей обучения и тестирования или инициализации весов нейронной сети - мы все время генерируем случайные числа в Python. 

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

Генерация случайных чисел в Python с использованием библиотеки Random

Хорошие новости - в Python есть разные способы генерации случайных чисел. Самый простой способ - использовать модуль random. Это встроенный модуль в Python, который не требует установки. Этот модуль использует генератор псевдослучайных чисел (PRNG), известный как Mersenne Twister.

Генератор псевдослучайных чисел - это детерминированный генератор случайных чисел. Он не генерирует действительно случайные числа. Он принимает число в качестве входных данных и генерирует для него случайное число.

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

Посев случайных чисел

Как мы обсуждали в предыдущем разделе, модуль random принимает число в качестве входных данных и генерирует для него случайное число. Это начальное значение известно как начальное число (seed), а процедура называется посевом (seeding).

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

Давайте разберемся с этим на примере:
import random

print('Random Number 1=>',random.random())
print('Random Number 2=>',random.random())
Здесь я использую функцию random(), которая генерирует случайное число в диапазоне [0.0, 1.0]. Обратите внимание, что я не упомянул величину начального значения. По умолчанию в качестве начального числа используется текущее системное время в миллисекундах. Давайте посмотрим на результат.


Числа различаются из-за изменения времени во время выполнения от первого оператора ко второму. Посмотрим, что произойдет, если мы засеим генераторы одинаковым значением:
random.seed(42)
print('Random Number 1=>',random.random())

random.seed(42)
print('Random Number 2=>',random.random())

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

Генерация случайных чисел в заданном диапазоне

Пока что мы знаем о создании случайных чисел в диапазоне [0.0, 1.0]. Но что, если нам нужно создать число в другом диапазоне?

Один из способов - умножить и прибавить числа к числу, возвращаемому функцией random(). Например, random.random() * 3 + 2 вернет числа в диапазоне [2.0, 5.0]. Однако это скорее обходной путь, а не прямое решение.

Не волнуйся! Здесь нам поможет модуль random. Он предоставляет функции uniform() и randint(), которые мы можем использовать для этой цели. Давайте разберемся с ними по очереди.

Функция uniform()

Функция uniform() модуля random принимает начальное и конечное значения диапазона в качестве аргументов и возвращает случайное число с плавающей запятой в диапазоне [начало, конец]:
print('Random Number in range(2,8)=>', random.uniform(2,8))

randint()

Эта функция похожа на функцию uniform(). Единственное отличие состоит в том, что функция uniform() возвращает случайные числа с плавающей запятой, а функция randint() возвращает целое число. Она также возвращает число в диапазоне [начало, конец]:
print('Random Number in a range(2,8)=>', random.randint(2,8))

Случайный выбор из списка

choice() и choices() - две функции, предоставляемые модулем random, которые мы можем использовать для случайного выбора значений из списка. Обе эти функции принимают список в качестве аргумента и случайным образом выбирают из него значения. Сможете догадаться, в чем разница между choice() и choices()?

choice() выбирает только одно значение из списка, тогда как choices() выбирает несколько значений из списка с заменой. В этих функциях замечательно то, что они также работают со списком, содержащим строки. Давайте посмотрим на них в действии:
a=[5, 9, 20, 10, 2, 8]
print('Randomly picked number=>',random.choice(a))
print('Randomly picked number=>',random.choices(a,k=3))

Как видите, choice() вернула одно значение, а choices() вернула три значения из a. Здесь k - длина списка, возвращаемого функцией choices().

Еще одна вещь, которую вы можете заметить в ответах, возвращаемых choices(), - это то, что каждое значение встречается только один раз. Вы можете увеличить вероятность выбора каждого значения, передав массив в качестве весов функции choices(). Итак, давайте увеличим вероятность для 10 в три раза и посмотрим на результаты:
for _ in range(5):
   print('Randomly picked number=>',random.choices(a,weights=[1,1,1,3,1,1],k=3))

Здесь мы видим, что в каждом случае из списка выпало 10. В модуле random также есть функция sample(), которая работает аналогично функции choices(), но берет случайные выборки из списка без замены.

Перемешивание списка

Допустим, мы не хотим выбирать значения из списка, а хотим изменить их порядок. Мы можем сделать это с помощью функции shuffle() из модуля random. Эта функция shuffle() принимает список в качестве аргумента и перемешивает его без замены:
print('Original list=>',a)
random.shuffle(a)
print('Shuffled list=>',a)

Примечание. Функция shuffle() не возвращает список.

Генерация случайных чисел в соответствии с распределениями

Еще одна удивительная особенность модуля random заключается в том, что он позволяет нам генерировать случайные числа на основе различных распределений вероятностей. В этом нам помогают различные функции, такие как gauss(), expovariate() и т. д.

Если вы не знакомы с распределениями вероятностей, я настоятельно рекомендую вам прочитать эту статью: 6 Common Probability Distributions every data science professional should know.

gauss()

Начнем с наиболее распространенного распределения вероятностей, то есть с нормального распределения. gauss() - это функция модуля random, используемая для генерации случайных чисел в соответствии с нормальным распределением. В качестве аргумента она принимает среднее значение и стандартное отклонение и возвращает случайное число:
for _ in range(5):
   print(random.gauss(0,1))

Здесь я построил график 1000 случайных чисел, сгенерированных функцией gauss() для среднего, равного 0, и стандартного отклонения, равного 1. Вы можете видеть выше, что все точки разбросаны вокруг среднего, и они не распределены достаточно тесно, поскольку стандартное отклонение равно 1 .

expovariate()

Экспоненциальное распределение - еще одно очень распространенное распределение вероятностей, с которым вы столкнетесь. Функция expovariate() используется для получения случайного числа в соответствии с экспоненциальным распределением. Она принимает значение лямбда в качестве аргумента и возвращает значение от 0 до положительной бесконечности, если лямбда положительная, и от отрицательной бесконечности до 0, если лямбда отрицательная:
print('Random number from exponential distribution=>',random.expovariate(10))


Комментариев нет:

Отправить комментарий