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

Что такое моделирование Монте-Карло?

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

Изучая, как создавать симуляции Монте-Карло, лучше всего начать с базовой модели, чтобы понять основы. Самый простой и распространенный способ сделать это — использовать простые игры, поэтому в этой статье мы воспользуемся игрой в кости. Вы, наверное, слышали поговорку «заведение всегда побеждает», поэтому в этом примере казино (обычно казино) будет иметь преимущество, и мы покажем, что это означает для возможного заработка игрока.

Игра в кости

В нашей простой игре будут задействованы два шестигранных кубика. Чтобы выиграть, игроку нужно выбросить одинаковое число на обоих кубиках. Шестигранный кубик имеет шесть возможных исходов (1, 2, 3, 4, 5 и 6). С двумя кубиками теперь 36 возможных исходов (1 и 1, 1 и 2, 1 и 3 и т. д., или 6 x 6 = 36 вариантов). В этой игре у дома больше шансов на победу (30 исходов против 6 исходов у игрока), а это означает, что у заведения есть значительное преимущество.

Допустим, наш игрок начинает с баланса в 1000 долларов и готов проиграть все, поэтому он ставит 1 доллар на каждый бросок (это означает, что бросаются оба кубика) и решает сыграть 1000 бросков. Поскольку дом настолько щедр, они предлагают выплату в 4 раза больше ставки игрока, когда игрок выигрывает. Например, если игрок выигрывает первый бросок, его баланс увеличивается на 4 доллара, и он заканчивает раунд с балансом в 1004 доллара. Если бы они каким-то чудом выиграли серию из 1000 бросков, они могли бы вернуться домой с 5000 долларов. Если бы они проигрывали каждый раунд, они могли бы вернуться домой ни с чем. Неплохое соотношение риска и вознаграждения… или, может быть, так оно и есть.

Импорт пакетов Python

Давайте смоделируем нашу игру, чтобы выяснить, сделал ли игрок правильный выбор. Мы начинаем наш код с импорта необходимых пакетов Python: Pyplot из Matplotlib и random. Мы будем использовать Pyplot для визуализации наших результатов и random для моделирования обычного шестигранного броска костей.

# Importing Packages
import matplotlib.pyplot as plt
import random

Функция броска кубиков

Затем мы можем определить функцию, которая будет рандомизировать целое число от 1 до 6 для обеих костей (имитируя бросок). Функция также сравнит два кубика, чтобы увидеть, одинаковы ли они. Функция вернет логическую переменную same_num, чтобы сохранить, одинаковы ли рулоны или нет. Мы будем использовать это значение позже для определения действий в нашем коде.

# Creating Roll Dice Function
def roll_dice():
    die_1 = random.randint(1, 6)
    die_2 = random.randint(1, 6)

    # Determining if the dice are the same number
    if die_1 == die_2:
        same_num = True
    else:
        same_num = False
    return same_num

Входные данные и переменные отслеживания

Каждое моделирование методом Монте-Карло потребует от вас знания ваших входных данных и информации, которую вы хотите получить. Мы уже определили наши входные данные, когда описывали игру. Мы сказали, что наше количество бросков за игру равно 1000, а сумма, которую игрок будет ставить на каждый бросок, составляет 1 доллар. В дополнение к нашим входным переменным нам нужно определить, сколько раз мы хотим моделировать игру. Мы можем использовать переменную num_simulations в качестве счетчика симуляций Монте-Карло. Чем больше мы делаем это число, тем точнее прогнозируемая вероятность соответствует ее истинному значению.

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

# Inputs
num_simulations = 10000
max_num_rolls = 1000
bet = 1

# Tracking
win_probability = []
end_balance = []

Настройка рисунка

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

# Creating Figure for Simulation Balances
fig = plt.figure()
plt.title("Monte Carlo Dice Game [" + str(num_simulations) + "   
          simulations]")
plt.xlabel("Roll Number")
plt.ylabel("Balance [$]")
plt.xlim([0, max_num_rolls])

Моделирование Монте-Карло

В приведенном ниже коде у нас есть внешний цикл for, который повторяет предварительно заданное количество симуляций (10 000 симуляций), и вложенный цикл while, который запускает каждую игру (1000 симуляций). роллы). Прежде чем запускать каждый цикл while, мы инициализируем баланс игрока как 1000 долларов (в виде списка для построения графиков) и количество бросков и выигрышей.

Наш цикл while имитирует игру на 1000 бросков. Внутри этого цикла мы бросаем кости и используем логическую переменную, возвращаемую функцией roll_dice(), чтобы определить результат. Если на костях одинаковое число, мы добавляем 4-кратную ставку в список баланса и добавляем выигрыш к подсчету выигрышей. Если кости разные, мы вычитаем ставку из списка баланса. В конце каждого рулона мы добавляем счетчик в наш список num_rolls.

Как только количество бросков достигает 1000, мы можем рассчитать вероятность выигрыша игрока как количество выигрышей, деленное на общее количество бросков. Мы также можем сохранить конечный баланс завершенной игры в переменной отслеживания end_balance. Наконец, мы можем построить переменные num_rolls и balance, чтобы добавить линию к фигуре, которую мы определили ранее.

# For loop to run for the number of simulations desired
for i in range(num_simulations):
    balance = [1000]
    num_rolls = [0]
    num_wins = 0
    # Run until the player has rolled 1,000 times
    while num_rolls[-1] < max_num_rolls:
        same = roll_dice()
        # Result if the dice are the same number
        if same:
            balance.append(balance[-1] + 4 * bet)
            num_wins += 1
        # Result if the dice are different numbers
        else:
            balance.append(balance[-1] - bet)

        num_rolls.append(num_rolls[-1] + 1)
# Store tracking variables and add line to figure
    win_probability.append(num_wins/num_rolls[-1])
    end_balance.append(balance[-1])
    plt.plot(num_rolls, balance)

Получение результатов

Последний шаг — отображение значимых данных из наших переменных отслеживания. Мы можем отобразить нашу фигуру (показанную ниже), которую мы создали в нашем цикле for. Кроме того, мы можем рассчитать и отобразить (как показано ниже) нашу общую вероятность выигрыша и конечный баланс, усреднив наши списки win_probability и end_balance.

# Showing the plot after the simulations are finished
plt.show()

# Averaging win probability and end balance
overall_win_probability = sum(win_probability)/len(win_probability)
overall_end_balance = sum(end_balance)/len(end_balance)
# Displaying the averages
print("Average win probability after " + str(num_simulations) + "   
       runs: " + str(overall_win_probability))
print("Average ending balance after " + str(num_simulations) + " 
       runs: $" + str(overall_end_balance))

Average win probability after 10000 simulations: 0.1667325999999987
Average ending balance after 10000 simulations: $833.663

Анализ результатов

Самая важная часть любого моделирования методом Монте-Карло (или любого анализа, если уж на то пошло) — сделать выводы из результатов. Из нашего рисунка мы можем определить, что игрок редко получает прибыль после 1000 бросков. Фактически, средний конечный баланс наших 10 000 симуляций составляет 833,66 доллара США (ваши результаты могут немного отличаться из-за рандомизации). Таким образом, несмотря на то, что казино было «щедро» выплатив в 4 раза больше нашей ставки, когда игрок выиграл, казино все равно вышло на первое место.

Мы также замечаем, что наша вероятность выигрыша составляет около 0,1667, или примерно 1/6. Давайте подумаем, почему это может быть. Возвращаясь к одному из предыдущих абзацев, мы отметили, что у игрока было 6 исходов, в которых он мог выиграть. Мы также отметили, что существует 36 возможных бросков. Используя эти два числа, мы ожидаем, что игрок выиграет 6 из 36 бросков, или 1/6 бросков, что соответствует нашему прогнозу Монте-Карло. Довольно круто!

Заключение

Вы можете использовать этот пример для творчества и попробовать разные ставки, разные броски костей и т. д. Вы также можете отслеживать некоторые другие переменные, если хотите. Используйте этот пример, чтобы освоиться с моделированием по методу Монте-Карло и действительно превратить его в свое собственное. Что еще интереснее, если бы казино выплачивало в 5 раз больше ставки, игрок в среднем оставался бы безубыточным с казино. Кроме того, если бы они выплатили сумму, превышающую ставку более чем в 5 раз, дом, скорее всего, в конечном итоге обанкротился бы. Если вы хотите увидеть эти результаты, дайте мне знать в комментариях! Этот простой пример показывает, почему симуляции и вероятности методом Монте-Карло так важны.

Спасибо за прочтение статьи! Я надеюсь, что это поможет вам в создании надежной симуляции Монте-Карло! Подпишитесь на другие статьи, связанные с Python, и ознакомьтесь с другими статьями, которые я написал!