蒙特卡洛思想

import numpy as np
import random
import matplotlib.pyplot as plt
# 设置中文字体
plt.rcParams['font.sans-serif'] = ['SimHei']

# 显示减号
plt.rcParams['axes.unicode_minus'] = False

计算圆周率

经典方法

def circle(x):
    return np.sqrt(1-x**2)


data_x = np.linspace(-1, 1, 10000)
data_y = circle(data_x)

plt.figure(figsize=(5, 5))
plt.plot(data_x, data_y, color='green')
plt.plot(data_x, -data_y, color='green')

plt.vlines(1, -1, 1)
plt.vlines(-1, -1, 1)
plt.hlines(1, -1, 1)
plt.hlines(-1, -1, 1)
plt.hlines(0, 0, 1)
plt.text(0.45, 0.1, 'r', fontsize=20)
plt.axis(False)
plt.show()

在这里插入图片描述

向正方形内随机撒点,点落在圆内的概率 p = S 圆 S 正方形 = π r 2 4 r 2 p=\frac{S_圆}{S_{正方形}}=\frac{\pi r^2}{4r^2} p=S正方形S=4r2πr2,即 π = 4 p \pi=4p π=4p

def pi1(n):

    count_circle = 0
    for _ in range(n):
        x = np.random.uniform(-1, 1)
        y = np.random.uniform(-1, 1)

        if x**2+y**2 <= 1:
            count_circle += 1

    return 4*count_circle/n
plt_x = []
plt_y = []

num = 1000
for i in range(num, 21*num, num):
	# 计算与π值的误差
    error = (pi1(i)-np.pi)/np.pi
    plt_x.append(i)
    plt_y.append(error)

plt.plot(plt_x, plt_y, 'o-')
plt.hlines(0, 0, 10*num)
plt.show()

在这里插入图片描述

布丰投针

plt.hlines(0, 0, 1)
plt.hlines(1, 0, 1)
plt.hlines(2, 0, 1)
plt.hlines(3, 0, 1)
plt.vlines(0.8, 1, 2, colors='orange')
plt.text(0.82, 1.5, '$d$', color='orange', fontsize=20)
plt.plot([0.4, 0.7], [0.65, 1.6])
plt.vlines(0.7, 0.65, 1.6, linestyle='--')
plt.hlines(0.65, 0.4, 0.7, linestyle='--')
plt.text(0.6, 1.1, '$\Theta$', fontsize=15)
plt.text(0.5, 1.1, '${L}$', fontsize=20)
plt.text(0.72, 1.1, '${L}^{\prime}$', fontsize=20)


plt.axis(False)
plt.show()

在这里插入图片描述

平行线间距为d,取长度为L的针(L<d)随机投掷

将夹角 [ 0 , π ] [0,\pi] [0,π]按照 Δ θ \Delta\theta Δθ等分

针与线夹角为 θ \theta θ的概率 p 1 = Δ θ π p_1=\frac{\Delta\theta}{\pi} p1=πΔθ

针与线相交的概率 p 2 = L ′ d = L s i n θ d p_2=\frac{{L}^{\prime}}{d}=\frac{L sin\theta}{d} p2=dL=dLsinθ

针与线以任意夹角相交的概率 p = ∑ θ = 0 π p 1 ∗ p 2 = ∫ 0 π L d π s i n θ d θ = 2 L d π {p=\sum_{\theta=0}^{\pi}{p_1*p_2}}=\int_{0}^{\pi}{\frac{L}{d\pi}sin\theta d\theta}=\frac{2L}{d\pi} p=θ=0πp1p2=0πdπLsinθdθ=dπ2L,即 π = 2 L p d \pi=\frac{2L}{pd} π=pd2L

有时为了计算方便,取 L = d 2 {L}=\frac{d}{2} L=2d,则 π = 1 p {\pi=\frac{1}{p}} π=p1

# 蒙特卡洛模拟布丰投针
def buffon_needle_simulation(num_trials, needle_length, line_spacing):
    """
    num_trials 试验次数
    needle_length 针的长度
    line_spacing 平行线的间距
    """
    intersect_count = 0

    for _ in range(num_trials):
        # 针的中点位置
        needle_midpoint = np.random.uniform(0, line_spacing / 2)
        # 针的倾斜角度
        needle_angle = np.random.uniform(0, np.pi / 2)

        # 如果针和线相交
        if needle_midpoint < (needle_length / 2) * np.sin(needle_angle):
            intersect_count += 1
    p = intersect_count / num_trials

#     return 2 * needle_length / p / line_spacing
    return 1 / p
# 设置参数
needle_length = 1
line_spacing = 2

plt_x = []
plt_y = []

num = 1000
for i in range(num, 11*num, num):
    estimated_pi = buffon_needle_simulation(i, needle_length, line_spacing)

    error = (estimated_pi-np.pi)/np.pi
    plt_x.append(i)
    plt_y.append(error)

plt.plot(plt_x, plt_y, 'o-')
plt.hlines(0, 0, 10*num)
plt.show()

在这里插入图片描述

计算定积分

def fx_2(x):
    return x**2


data_x = np.linspace(0, 1.15, 10000)
data_x_2 = fx_2(data_x)
plt.figure(figsize=(5, 5))
plt.plot(data_x, data_x_2, 'orange')
plt.text(0.5, 0.5, '$y=x^2$')
plt.hlines(0, 0, 1, colors='green')
plt.hlines(1, 0, 1, colors='green')
plt.vlines(1, 0, 1, colors='green')
plt.vlines(0, 0, 1, colors='green')

for i in np.arange(0.2, 1, 0.05):
    plt.vlines(i, 0, fx_2(i), linestyles='--')


plt.show()

在这里插入图片描述

定积分 S 阴影 = ∫ 0 1 x 2 d x = 1 3 S_{阴影}=\int_{0}^{1}{x^2}dx=\frac{1}{3} S阴影=01x2dx=31

向绿色矩形内随机撒点,点在阴影部分的概率为 p = S 阴影 S 矩形 p=\frac{S_{阴影}}{S_{矩形}} p=S矩形S阴影

def f2(x):
    count = 0
    for _ in range(x):
        random_x = np.random.uniform(0, 1)
        random_y = np.random.uniform(0, 1)
        if random_y <= fx_2(random_x):
            count += 1
    return count/x
plt_x = []
plt_y = []

num = 1000
for i in range(num, 11*num, num):
    res = f2(i)

    # 计算误差
    error = 3*res-1
    plt_x.append(i)
    plt_y.append(error)

# 随着次数上升,误差的大小
plt.plot(plt_x, plt_y, 'o-')
plt.hlines(0, 0, 10*num)
plt.show()

在这里插入图片描述

模拟游戏

  • 前置条件,基本资金10000,当资金小于500时,认为失败。
  • 目标,赚更多钱。

等份策略

每次拿出一定额度(比如100)进行游戏,50%的概率赢100,50%的概率输100

funds = 10000
res_lis = []

for i in range(1, 10000):

    random_res = np.random.choice(['win', 'lose'])
    if random_res == 'win':
        funds += 100
    else:
        funds -= 100
    res_lis.append(funds)
plt.plot(range(1, 10000), res_lis)
plt.hlines(500, 0, 10000)
plt.show()

在这里插入图片描述

理论上fund会在10000上下徘徊,模拟过程中,也可能会出现赔本的情况。

对半策略

每次拿出全部本金的一半,50%的概率输一半或赢一半

过程类型指数级变化,相较于等份策略,收敛速度会明显加快。

funds = 10000
res_lis = [10000]

for i in range(1, 10000):

    random_res = np.random.choice(['win', 'lose'])

    chips = funds/2

    if random_res == 'win':
        funds += chips
    else:
        funds -= chips
    res_lis.append(funds)

    if funds < 500:
        break
plt.plot(res_lis)
# plt.hlines(500, 0, 10000)
plt.show()

在这里插入图片描述

凯利公式

凯莉公式的核心思想是,如果知道每次下注获胜的概率以及赢得的比例,可以通过公式计算出应该下注的资金比例,以使长期来看最大化投资或赌博的收益。
f ∗ = b p − q b f^*=\frac{bp-q}{b} f=bbpq

  • f ∗ f^* f 表示应该投入的资金的比例。
  • b 表示每笔投注的可能净收益(赔率)。
  • p 表示投注成功的概率。
  • q 表示投注失败的概率。

假设赔率为b,输了失去下注数,赢了获得b倍(包括下注数)

def f4(b, x=10000):

    f = (b*0.5-0.5)/b
    funds = 10000   # 基本资金
    game_count = 0  # 游戏次数
    funds_list = [funds]  # 保存每次游戏后的资金

    for i in range(x):
        chips = funds*f
        random_res = np.random.choice(['win', 'lose'])
        if random_res == 'win':
            funds += chips*(b-1)
        else:
            funds -= chips

        game_count += 1
        funds_list.append(funds)
        if funds < 500:
            break

    return game_count, funds_list
# 赔率为2进行测试
game_count, funds_list = f4(2)

plt.plot(funds_list)
plt.show()

在这里插入图片描述

赔率高于1时,也有输光(<500)的风险。

当输赢收益一样时,最佳 f ∗ f^* f为0,即不赌。

题外话:参考电影《消失的她》,第一次下注t元,进行n次,无论上一次的输赢,后续每一次下注数总为上一次的两倍。进行n次后,理论上无论前面输赢情况,只需最后一次(第n次)是赢,根据等比数列求和公式,前n-1项的和总小于第n项,即使前n-1次全输,此时收益也为正。虽然这种方式可以做到理论最优(保证最后一次为赢的情况下,总收益呈指数型上升),但是每次下注的本金是在成倍增长,在实际中本金额度会过大,带来风险。即使可以做到理论最优的方式,现实总也存在操盘等行为,所以说,珍爱生命,原理赌博

随机游走

醉汉问题

在十字路口中心,有一个醉汉会向四个方向随机移动,在移动足够长的步数后,是否会返回原点?(离原点的距离)

def f5(num):
    x = 0
    y = 0
    x_left = 0
    x_right = 0
    y_upper = 0
    y_lower = 0
    x_list = [0]
    y_list = [0]

    for _ in range(num):
        op = np.random.choice(['left', 'right', 'upper', 'lower'])
        if op == 'left':
            x_left += 1
            x -= 1
        elif op == 'right':
            x_right += 1
            x += 1
        elif op == 'upper':
            y_upper += 1
            y += 1
        elif op == 'lower':
            y_lower += 1
            y -= 1
        x_list.append(x)
        y_list.append(y)
    return x_list, y_list, x_left, x_right, y_upper, y_lower
x_list,y_list,x_left,x_right,y_upper,y_lower = f5(100)

plt.plot(x_list,y_list,'o-')
plt.show()

在这里插入图片描述

x_left,x_right,y_upper,y_lower
(29, 25, 23, 23)

随机游走中醉汉问题是一个经典的数学问题,描述了一个醉汉在二维空间中随机移动的情况。这个问题的启示包括:

  • 随机性的重要性: 醉汉问题突显了随机性在某些情况下的重要性。尽管醉汉在每一步都做出随机决策,但最终却可能会收敛到一个确定的分布。这说明了在某些系统中,即使存在随机性,也可能会出现一定的稳定性或可预测性
  • 扩展到其他领域: 醉汉问题的概念不仅仅局限于数学领域,还可以应用于其他领域,如物理学、计算机科学和金融学等。在物理学中,它可以用来模拟分子在液体中的随机运动;在计算机科学中,可以用来设计随机算法;在金融学中,可以用来模拟资产价格的随机波动。
  • 随机过程的理解: 醉汉问题是理解随机过程的一个很好的例子。通过研究醉汉在空间中的随机移动,可以深入了解随机过程的特性、收敛性以及与概率分布相关的概念。
  • 决策和结果的分离: 尽管醉汉在每一步都做出随机决策,但最终结果却受到其初始位置和随机决策序列的影响。这表明有时决策和结果之间存在一定程度的分离,即好的决策并不总是能够带来好的结果,反之亦然。

概率

  • 虽然目标结果可以预测,但现实总有考虑不到的情况,预测与事实存在偏差很正常。
  • 不可能事件的发生概率为0,但概率为0的事件不一定是不可能事件。
  • 在概率模型中,总是将概率最高的那一个作为预测结果。
  • 有时所有可能的结果概率值都很小,说明每个可能结果的概率值较为接近,此时可以拒绝回答(预测),这个在一些模型上也有应用。(想一想逻辑回归对概率进行二值化的时候,为什么要选择Sigmod函数)
  • 12
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值