Отвечая на загадку Монти Холла с Монте-Карло

Монте-Карло - концептуально простой, но мощный метод, который широко используется. Он использует случайность для ответов на вопросы.

В этом посте я объясню, как решить проблему Монти Холла с помощью метода Монте-Карло. Реализация выполнена на языке программирования python, название которого само по себе является данью уважения британской Comedy Group - Monty Python.

Проблема Монти Холла

Впервые я познакомился с проблемой Монти Холла в фильме - 21. Этот клип демонстрирует проблему.

Этому есть объяснения со стороны Майкла Дэвида Стивенса из Vsauce и Vox.

Давайте перейдем к проблеме - Представьте, перед вами три двери.

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

Допустим, вы выбрали дверь №1

Ведущий игрового шоу, который знает, что находится за каждой дверью - открывает дверь № 3 и показывает козу.

Организатор игрового шоу предлагает два варианта

  1. Наклейка с дверцей № 1
  2. Переключитесь на номер двери. 2

Что бы вы выбрали?

Эксперименты Монте-Карло

Определение экспериментов Монте-Карло согласно wikipWikipedia методы те-Карло или эксперименты Монте-Карло, представляют собой широкий класс вычислительных алгоритмов, которые полагаются на о повторной случайной выборке для получения числовых результатов. Основная идея заключается в использовании случайности для решения проблем, которые в принципе могут быть детерминированными ».

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

В фильме «Мстители: Война бесконечности» Доктор Стрэндж выполняет почти 14 миллионов симуляций будущего, чтобы определить, сколько из будущих результатов выиграют мстители? По сути, он применяет принципы экспериментов Монте-Карло.

Моделирование Монти Холла с помощью Монте-Карло

Представьте, что описанная ранее игра застряла в петле, как Билл Мюррей в фильме День сурка.

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

Допустим, игра проводилась 100 раз. Мы проверим, в скольких из этих 100 игр машина была выиграна, не переключая дверь и не переключая дверь.

Глядя на эти коэффициенты, мы узнаем, какой вариант увеличивает шансы на успех.

Кодификация Монти Холла и Монте-Карло

Давайте определим функцию, которая имитирует проблему Монти Холла.

def monty_hall():
    ...

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

doors = [0, 1, 0]
shuffle(doors)

Игрок выбирает дверь, которую нужно открыть. Значения 0,1 и 2 представляют собой индексы переменной списка «дверей».

door_selected = choice([0, 1, 2])

Ведущий игрового шоу теперь открывает дверь, за которой нет машины.

non_car_doors = list()
for i,d in enumerate(doors):
 if d == 0 and i != door_selected: non_car_doors.append(i)
door_opened = choice(non_car_doors)

Теперь оцените следующие два варианта

  1. Выигрывает автомобиль, придерживаясь первоначального выбора
non_switch_success =  True if doors[door_selected] == 1 else False

2. Побеждает автомобиль, переключившись на оставшуюся дверь.

remaining_door = set([0,1,2]).difference([door_selected, door_opened])
remaining_door = remaining_door.pop()
switch_success =  True if doors[remaining_door] == 1 else False

Наконец, верните успех для каждого из вариантов

return non_switch_success, switch_success

Определите функцию Монте-Карло, которая принимает единственный аргумент «n», представляющий количество запускаемых симуляций. Запустите моделирование Монте-Холла «n» раз и верните распределение успешности для каждого из вариантов.

def monte_carlo(n):
    non_switch_success_count = 0
    switch_success_count = 0
for i in range(n):
        ns, ss = monty_hall()
        non_switch_success_count += ns
        switch_success_count += ss
print(f"Number of plays: {n}")
    print(f"Number of success on switch: {switch_success_count}     
     {(switch_success_count/n)*100}%")
    print(f"Number of success on non-switch:                       {non_switch_success_count}  
     {(non_switch_success_count/n)*100}%")

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

Запуск симуляции

Смоделируем 100 игр

╰─$ ./main.py 100
Number of plays: 100
Number of success on switch: 71  71.0%
Number of success on non-switch: 29  28.999999999999996%

Мы видим, что переключение происходит более успешно.

Давай снова запустим

╰─$ ./main.py 100
Number of plays: 100
Number of success on switch: 62  62.0%
Number of success on non-switch: 38  38.0%

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

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

╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666566  66.6566%
Number of success on non-switch: 333434  33.3434%
╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666588  66.6588%
Number of success on non-switch: 333412  33.3412%
╰─$ ./main.py 1000000
Number of plays: 1000000
Number of success on switch: 666628  66.6628%
Number of success on non-switch: 333372  33.3372%

Мы видим, что процент успеха не сильно различается, и это говорит нам о том, что если мы сделаем переход, то шансы на победу увеличиваются в 2 раза из 3.

Сделай переключатель!

Заключение

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