Нашли ошибку?
Скачать чистый
урок 3 из 4≈ 20 минупражнения: 0 из 4

Моделирование без циклов

Сто тысяч экспериментов одной таблицей — сумма двух кубиков, число π методом Монте-Карло, парадокс дней рождения. Вероятность — доля удачных строк.

Python запустится при первом выполнении

Какова вероятность выбросить 7 на двух кубиках? Можно посчитать на бумаге, а можно смоделировать: бросить кубики много раз и посмотреть на долю удачных бросков. Метод, который отвечает на вопросы о вероятностях повторением случайных экспериментов, называют методом Монте-Карло — в честь Монте-Карло, города казино.

Приём, который делает моделирование на NumPy быстрым: один эксперимент — одна строка таблицы. Генератор сразу выдаёт таблицу size=(экспериментов, бросков), итог каждого эксперимента — агрегат по axis=1, а вероятность — среднее маски по всем строкам. Ни одного цикла.

Два кубика

[ ]Сто тысяч бросков двух кубиков
import numpy as np

rng = np.random.default_rng(1)
throws = rng.integers(1, 7, size=(100000, 2))   # строка — один бросок двух кубиков
print(throws[:3])
sums = throws.sum(axis=1)
print((sums == 7).mean())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[[3 4]
 [5 6]
 [1 1]]
0.16619

Точный ответ — 6 из 36 = 0.1667: из 36 равновероятных пар ровно 6 дают семь. Моделирование попало почти в точку.

[ ]Упражнение 1Дубль решено

Создайте генератор с seed 12 и бросьте два кубика 100 000 раз (таблица 100 000 × 2). Сохраните в doubles долю бросков, где на кубиках выпало одно и то же число.

rng = ...
doubles = ...

Вопрос

Какова точная вероятность дубля на двух кубиках?

Сколько орлов

[ ]Упражнение 2Три орла из пяти решено

Создайте генератор с seed 5 и смоделируйте 50 000 серий по 5 бросков монеты (таблица 50 000 × 5 из маски < 0.5). Сохраните в at_least_3 долю серий, где орлов было не меньше трёх.

rng = ...
at_least_3 = ...

Число π

Бросим точки в квадрат со стороной 1. Четверть круга радиусом 1 занимает π/4 площади квадрата — значит, доля точек, попавших в круг (x² + y² ≤ 1), примерно равна π/4:

[ ]π методом Монте-Карло
rng = np.random.default_rng(1)
points = rng.random((100000, 2))
inside = (points[:, 0] ** 2 + points[:, 1] ** 2) <= 1
print(inside.mean() * 4)
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
3.145
[ ]Упражнение 3Оценить π решено

Создайте генератор с seed 3, бросьте 100 000 точек (таблица 100 000 × 2 из rng.random) и сохраните в pi_est оценку числа π: доля точек внутри четверти круга, умноженная на 4.

rng = ...
pi_est = ...

Парадокс дней рождения

Сколько человек нужно собрать, чтобы у двоих совпал день рождения с вероятностью около 50 %? Интуиция говорит «человек 180», а ответ — 23. Проверим: строка — группа из 23 человек, дни — случайные числа от 1 до 365. Совпадение в группе легко найти, если отсортировать строку: тогда одинаковые дни окажутся соседями.

[ ]Сортировка ставит одинаковые дни рядом
group = np.sort(np.random.default_rng(6).integers(1, 366, size=23))
print(group)
print(group[1:] == group[:-1])
print((group[1:] == group[:-1]).any())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
[ 19  45  69 121 126 135 137 156 163 165 165 189 197 226 231 241 246 247
 249 276 324 346 361]
[False False False False False False False False False  True False False
 False False False False False False False False False False]
True

group[1:] == group[:-1] сравнивает каждый элемент с предыдущим — два среза одной строки, сдвинутые на один. В этой группе два человека родились в 165-й день года — рядом после сортировки, и в маске появился True.

[ ]Упражнение 423 человека решено

Создайте генератор с seed 23, смоделируйте 10 000 групп по 23 человека и сохраните в same_bday долю групп, где хотя бы у двоих совпал день рождения.

rng = ...
same_bday = ...

[ ]Миллион бросков — одной строкой
rng = np.random.default_rng(0)
big = rng.integers(1, 7, size=(1000000, 2)).sum(axis=1)
print(len(big), (big == 7).mean())
Выводсохранённый · нажмите «Выполнить», чтобы получить свой
1000000 0.166822

Итоги

  • Метод Монте-Карло: вероятность ≈ доля удачных исходов в большом числе случайных экспериментов.
  • Эксперимент — строка таблицы size=(n, k); итог эксперимента — агрегат по axis=1.
  • .any(axis=1), .sum(axis=1) и сравнения столбцов отвечают на «было ли» и «сколько» в каждой строке.
  • Чем больше экспериментов, тем точнее оценка.

Подробнее в справочнике

Нашли ошибку?