蒙特卡洛仿真(或概率仿真)是一种用于了解金融部门风险和不确定性、项目管理、成本和其他预测机器学习模型的影响的技术。
风险分析是我们做出的几乎每一个决定的一部分,因为我们经常面临生活中的不确定性、模糊性和多变性。此外,即使我们获得了前所未有的信息,我们也不能准确预测未来。
蒙特卡洛仿真使我们能够看到所有可能的结果,并评估风险影响,从而允许在不确定性下更好的决策。
在本文中,我们将通过五个不同的示例来理解蒙特卡洛仿真方法。本教程的代码可在Github及Google Colab 找到。
掷一个无偏硬币的正面向上的概率为 1/2。然而,我们有什么办法可以实验证明吗?在此示例中,我们将使用蒙特卡洛方法模拟掷硬币 5000 次,以找出为什么正面向上的概率始终为 1/2。如果我们重复掷这个硬币很多很多次,那么可以达到更高的准确性。
## 导入库
import random
import numpy as np
import matplotlib.pyplot as plt
## 投硬币的函数
def coin_filp():
return random.randint(0,1) # 产生01随机数
## Monte Carlo Simulation
prob_list1 = [] # 空列表存储概率值
def monte_carlo(n):
"""
n 是模拟次数
"""
results = 0
for i in range(n):
flip_result = coin_filp()
results =results + flip_result
# Calculating probability value
prob_value = results/(i+1)
# append the probability values to the list
prob_list1.append(prob_value)
# plot the results
plt.axhline(y = 0.5,color = 'red',linestyle='-')
plt.xlabel('Iterations')
plt.ylabel('Probability')
plt.plot(prob_list1)
return results/n
# calling the function
answer = monte_carlo(5000)
print('Final value:',answer)
Final value: 0.4968
如上图所示,我们在 5000 次迭代后,获得正面向上的概率为 0.502。因此,这就是我们如何使用蒙特卡洛仿真来找到概率值的实验。
要估计 PI 的价值,我们需要正方型和圆的面积。为了找到这些区域,我们将随机将点放在表面上,并计算落在圆圈内的点和落在正方形内的点。这将给我们估计他们的面积。因此,我们将使用点计数作为区域,而不是使用实际区域的大小。
## 导入库
import turtle
import random
import matplotlib.pyplot as plt
import math
## 绘制点
# to visualize the random points
mypen = turtle.Turtle()
mypen.hideturtle()
mypen.speed(0)
# drawing a square
mypen.up()
mypen.setposition(-100,-100)
mypen.down()
mypen.fd(200)
mypen.left(90)
mypen.fd(200)
mypen.left(90)
mypen.fd(200)
mypen.left(90)
mypen.fd(200)
mypen.left(90)
# drawing a circle
mypen.up()
mypen.setposition(0,-100)
mypen.down()
mypen.circle(100)
# 初始化数据
# to count the points inside and outside the circle
in_circle = 0
out_circle = 0
# to store the values of the PI
pi_values = []
# 主函数
# running for 5 times
for i in range(5):
for j in range(50):
# generate random numbers
x = random.randrange(-100,100)
y = random.randrange(-100,100)
# check if the number lies outside the circle
if (x**2+y**2>100**2):
mypen.color('black')
mypen.up()
mypen.goto(x,y)
mypen.down()
mypen.dot()
out_circle = out_circle + 1
else:
mypen.color('red')
mypen.up()
mypen.goto(x,y)
mypen.down()
mypen.dot()
in_circle = in_circle + 1
# calculating the value of PI
pi = 4.0 * in_circle/(in_circle + out_circle)
# append the values of PI in list
pi_values.append(pi)
# Calculating the errors
avg_pi_errors = [abs(math.pi - pi) for pi in pi_values]
# Print the final values of PI for each iterations
print(pi_values[-1])
3.12
2.96
2.8533333333333335
3.0
3.04
# 绘制图像
# Plot the PI values
plt.axhline(y=math.pi,color='g',linestyle='-')
plt.plot(pi_values)
plt.xlabel('Iterations')
plt.ylabel('Values of PI')
plt.show()
plt.axhline(y = 0.0,color = 'g',linestyle='-')
plt.plot(avg_pi_errors)
plt.xlabel('Iterations')
plt.ylabel('Error')
plt.show()
假设在一个游戏节目中, 你可以选择三扇门之一: 一扇门后面是一辆车; 其他门后面都是山羊。你挑一扇门,比方说门1,主持人,他知道门后面是什么,打开另一扇门,比如说门3,有一只山羊。主持人然后问你:你是要坚持你的选择还是选择另一扇门?
换门对你有利吗?
根据概率,换门对我们是有利的。让我们了解一下:
最初,对于所有三个门,获得汽车的概率(P)是相同的(P = 1/3)。
现在假设参赛者选择门 1。然后主持人打开第三扇门,门后面有一只山羊。接下来,主持人问参赛者是否想换门?
我们将看到为什么换门更有利:
在上图中,我们可以看到,在主持人打开3号门后,两扇门拥有汽车的概率增加到2/3。现在我们知道第三扇门有山羊,第二扇门有车的概率增加到2/3。因此,换门更有利。
## 导入库
import random
import matplotlib.pyplot as plt
## 初始化数据
# 1 = car
# 2 = goat
doors = ['goat','goat','car']
switch_win_probability = []
stick_win_probability = []
plt.axhline(y = 0.66666,color = 'r',linestyle='-')
plt.axhline(y = 0.33333,color = 'g',linestyle='-')
import random
import matplotlib.pyplot as plt
## 初始化数据
# 1 = car
# 2 = goat
doors = ['goat','goat','car']
switch_win_probability = []
stick_win_probability = []
# monte carlo simulation
def monte_carlo(n):
# calculating switch and stick wins:
switch_wins = 0
stick_wins = 0
for i in range(n):
# randomly placing the car and goats behind three doors
random.shuffle(doors)
# contestant's choice
k = random.randrange(2)
# If the contestant doesn't get car
if doors[k] != 'car':
switch_wins += 1
else:
stick_wins += 1
# updatating the list values
switch_win_probability.append(switch_wins/(i+1))
stick_win_probability.append(stick_wins/(i+1))
# plotting the data
plt.plot(switch_win_probability)
plt.plot(stick_win_probability)
# print the probability values
print('Winning probability if you always switch',switch_win_probability[-1])
print('Winning probability if you always stick to your original choice:',stick_win_probability[-1])
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q0oAMCrF-1638621844579)(output_30_0.png)]
monte_carlo(1000)
plt.axhline(y = 0.66666,color = 'r',linestyle='-')
plt.axhline(y = 0.33333,color = 'g',linestyle='-')
Winning probability if you always switch 0.655
Winning probability if you always stick to your original choice: 0.345
法国贵族Buffon,在1777年发布了以下问题:
假设我们在一张划线纸上扔一根短针——针头正好跨越线的位置的可能性是多大?
概率取决于纸上线条之间的距离(d),也取决于我们扔的针的长度(l),或者更确切地说,这取决于比率l/d。对于这个例子,我们可以认为针l ≤ d。简言之,我们的目的是假设针不能同时跨越两条不同的线。令人惊讶的是,这个问题的答案涉及PI。
import random
import matplotlib.pyplot as plt
import math
def monte_carlo(runs,needles,n_lenth,b_width):
# Empty list to store pi values:
pi_values = []
# Horizontal line for actual value of PI
plt.axhline(y=math.pi,color = 'r',linestyle='-')
# For all runs:
for i in range(runs):
# Initialize number of hits as 0
nhits = 0
# For all needles
for j in range(needles):
# We will find the distance from the nearest vertical line
# min = 0,max = b_width/2
x = random.uniform(0,b_width/2.0)
# The theta value will be from 0 to pi/2
theta = random.uniform(0,math.pi/2)
# checking if the needle crosses the line or not
xtip = x - (n_lenth/2.0)*math.cos(theta)
if xtip < 0 :
nhits += 1
# Going with the formula
numerator = 2.0 * n_lenth * needles
denominator = b_width * nhits
# Append the final value of pi
pi_values.append((numerator/denominator))
# Final pi value after all iterations
print(pi_values[-1])
# Plotting the graph:
plt.plot(pi_values)
# Total number of runs
runs = 100
# Total number of needles
needles = 100000
# Length of needle
n_lenth = 2
# space between 2 verical lines
b_width = 2
# Calling the main function
monte_carlo(runs,needles,n_lenth,b_width)
3.153728495513821
赌场如何赚钱?诀窍很简单 —— "你玩得越多, 赌场赚得越多。让我们通过一个简单的蒙特卡洛模拟示例来看看其运作原理。
考虑一个假想的游戏,玩家必须从一袋芯片中挑一个芯片。
规则:
如果我们押注奇数,我们获胜的概率为49/100。庄家获胜的概率是51/100。因此,对于一个奇数赌注,庄家的利润是 = 51/100- 49/100 = 200/10000 = 0.02 = 2%
如果我们押注于偶数,用户获胜的概率为 49/100。庄家获胜的概率是51/100。因此,对于一个偶数赌注,庄家的利润是 = 51/100-49/100 = 200/10000 = 0.02 = 2%
总之,每下1美元的赌注,其中0.02美元就归庄家的。相比之下,轮盘赌庄家的最低利润为2.5%。因此,我们确信,在假想的比赛中,你比轮盘赌更有可能获胜。
import random
import matplotlib.pyplot as plt
# Place your bet:
# User can choose even or odd number
choice = input("Don you want to bet on Even number or odd number\n")
# For even
if choice =='Even':
def pickNote():
# get random number between 1-100
note = random.randint(1,100)
# check for our game conditions
# Notice that 10 isn't considered as even number
if note%2 != 0 or note == 10:
return False
elif note%2 ==0:
return True
# For odd
elif choice =='Odd':
def pickNote():
# get random number between 1-100
note = random.randint(1,100)
# check for our game conditions
# Notice that 10 isn't considered as even number
if note%2 == 0 or note == 11:
return False
elif note%2 == 1:
return True
Don you want to bet on Even number or odd number
Odd
# Main function
def play(total_money ,bet_money,total_plays):
num_of_plays = []
money = []
# start with play number 1
play = 1
for play in range(total_plays):
# Win
if pickNote():
# Add the money to our funds
total_money = total_money + bet_money
# append the play number
num_of_plays.append(play)
# append the new fund amout
money.append(total_money)
# Lose
if pickNote():
# Add the money to our funds
total_money = total_money - bet_money
# append the play number
num_of_plays.append(play)
# append the new fund amout
money.append(total_money)
# Plot the data
plt.ylabel('Player Money in $')
plt.xlabel('Number of bets')
plt.plot(num_of_plays,money)
final_funds = []
# Final values after all the iterations
final_funds.append(money[-1])
return( final_funds)
# Run 10 time
# 修改这里的次数
for i in range(1000):
ending_fund = play(10000,100,50)
print(ending_fund)
print(sum(ending_fund))
# print the money the player ends with
print('The player started with $10,000')
print('The player left with $',str(sum(ending_fund)/len(ending_fund)))
[10400]
10400
The player started with $10,000
The player left with $ 10400.0