蒙特卡洛方法原理与应用 统计量近似分布与分位数计算 python画图演示

本文介绍了蒙特卡洛方法的基本原理和起源,并通过实例展示了如何利用该方法进行统计量分布和分位数计算。通过Python编程实现,探讨了样本容量变化对计算误差的影响以及分位数对随机数初始值的敏感性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

一 蒙特卡洛概率方法的初步介绍与基本原理

1.1 蒙特卡洛方法的定义
1.2 蒙特卡洛方法的起源
1.3 蒙特卡洛方法的举例

二 用蒙特卡洛进行统计量分布和分位数计算

2.1 数理统计问题的描述
2.2 正态分布与指数分布
2.3 经验分布与概率计算
2.4 解决思路与大概过程

三 蒙特卡洛方法去解决问题的实际具体过程

3.1 相应分布随机数获取
3.2 近似分布函数的绘画
3.3 目标统计量的分位数
3.4 样本容量变化的误差
3.5 分位数与随机性关系

四 本篇文章相关参考资料与参考文献的声明

一 蒙特卡洛概率方法的初步介绍与基本原理

1.1 蒙特卡洛方法的定义

        蒙特卡洛方法又称统计模拟法、随机抽样技术,是一种随机模拟方法,以概率和统计理论方法为基础的一种计算方法,是使用随机数(或更常见的伪随机数)来解决很多计算问题的方法。使用蒙特卡洛方法时,需要将所求解的问题同一定的概率模型相联系,然后用电子计算机实现统计模拟或抽样,以获得问题的近似解。

1.2 蒙特卡洛方法的起源

        蒙特卡洛方法于20世纪40年代美国在第二次世界大战中研制原子弹的"曼哈顿计划"计划的成员S.M.乌拉姆和J.冯·诺伊曼首先提出。数学家冯·诺伊曼用驰名世界的赌城-摩纳哥的Monte Carlo来命名这种方法,为它蒙上了一层神秘色彩。蒙特卡洛方法在金融工程学,宏观经济学,生物医学,计算物理学(如粒子输运计算、量子热力学计算、空气动力学计算、核工程)等领域应用广泛。

1.3 蒙特卡洛方法的举例

        我们可以使用蒙特卡洛方法巧算 π\piπ 的近似值,具体过程为:正方形内部有一个相切的圆,它们的面积之比是 π4\frac{\pi}{4}4π ,如下图所示。

        此时,如果我们在正方形内部产生随机的n个点(n足够大),那么圆形内部的点数量与正方形内的点数量之比,将在概率意义上近似等于圆与正方形的面积之比,假设这个比值为 kkk ,那么便有公式: π=4k\pi = 4kπ=4k

二 用蒙特卡洛进行统计量分布和分位数计算

2.1 数理统计问题的描述

2.2 正态分布与指数分布



2.3 经验分布与概率计算



2.4 解决思路与大概过程

        我们以标准正态分布的案例进行说明,相应指数分布的思路是差不多的。在这一节,我们主要叙述大概步骤,具体的答案在第四章里面给出。
        第一步,从标准正态分布N(0,1)N(0,1)N(0,1)中随机取样获得足够多的mmm个点:x1,x2,...,xmx_{1} ,x_{2},...,x_{m}x1,x2,...,xm
        第二步,将mmm个点随机分成kkk组,每组含nnn个点,并按题中公式算出:t1,t2,...,tkt_{1} ,t_{2},...,t_{k}t1,t2,...,tk
        第三步,对获得的kkk个点t1,t2,...,tkt_{1} ,t_{2},...,t_{k}t1,t2,...,tk,按照经验分布定义求出对应近似分布表达式
        第四步,利用上述获得的经验分布表达式,去完成我们目标统计量分位数计算任务

三 蒙特卡洛方法去解决问题的实际具体过程

3.1 相应分布随机数获取

我们可以利用python代码获取正态分布和指数分布的随机数,相关代码如下:

import numpy as np
import math
import matplotlib.pyplot as plt

# 生成n*10万个标准正态分布随机数和标准指数分布随机数
n = 20
dataX_nor = np.random.normal(0, 1, n * 10 * 10000)
dataX_exp = np.random.exponential(1, n * 10 * 10000)

然后,我们需要对获取到的100万个随机数以每组nnn个形式进行分组,相关代码如下:

# 将生成的正态分布和指数分布随机数按n个一组形式分组
dataZ_nor = np.reshape(dataX_nor, (n * 10 * 10000 // n, n))
dataZ_exp = np.reshape(dataX_exp, (n * 10 * 10000 // n, n))
# 将得到的分组随机数去计算目标统计量T的若干观测值
dataT_nor = np.zeros(n * 10 * 10000 // n, np.float32)  # 创建空数组
dataT_exp = np.zeros(n * 10 * 10000 // n, np.float32)  # 创建空数组
for i in range(n * 10 * 10000 // n):
    sum_nor, sum_exp = 0, 0
    for j in range(n):
        sum_nor += (dataZ_nor[i][j] - dataZ_nor[i].mean()) ** 2
        sum_exp += (dataZ_exp[i][j] - dataZ_exp[i].mean()) ** 2
    dataT_nor[i] = math.sqrt(sum_nor / n) / (dataZ_nor[i].mean() - dataZ_nor[i].min())
    dataT_exp[i] = math.sqrt(sum_exp / n) / (dataZ_exp[i].mean() - dataZ_exp[i].min())
3.2 近似分布函数的绘画

我们可以构造一个程序函数去代表近似分布函数F(x)F(x)F(x),程序函数的输入为xxx和数据集,输出为F(x)F(x)F(x),处理过程按照经验分布的定义即可,相关代码如下:

# 利用程序去表示近似分布函数,输入自变量,输出函数值
def F(x, data):
    k = len(data)
    u = 0
    for index in range(k):
        if x > data[index]:
            u += 1
    return u / k

有了近似分布函数后,我们就可以绘画其近似分布函数的图像了,相关代码如下:

# 绘制函数图像
X = np.linspace(0, 1.5, 150)  # 创建从-1到9的等间隔的100个数据点
Y_nor = np.zeros(len(X), np.float32)  # 创建空数组
Y_exp = np.zeros(len(X), np.float32)  # 创建空数组
for index in range(len(X)):
    Y_nor[index] = F(X[index], dataT_nor)
    Y_exp[index] = F(X[index], dataT_exp)
plt.plot(X, Y_nor)  # 绘制函数图像
plt.xlabel('x')  # 设置x轴标签
plt.ylabel('y')  # 设置y轴标签
plt.title('Function-Nor')  # 设置图像标题
plt.grid(True)  # 显示网格线
plt.show()  # 显示图像

有了上述的步骤和代码,我们大致得到了如下近似分布曲线,其中标有NorNorNor的曲线计算数据来源正态分布,标有ExpExpExp的曲线计算数据来自于指数分布,两者均满足n=10n=10n=10

3.3 目标统计量的分位数


从近似分布曲线图像中,我们很容易大致估计所求分位数在区间(0,1)(0,1)(0,1)中,根据经验分布和顺序统计量相关知识,我们很容易得到公式 tα=T(kα)t_{\alpha}=T_{(k\alpha )}tα=T(kα) ,我们可以对 t1,t2,...,tkt_{1} ,t_{2},...,t_{k}t1,t2,...,tk 排序后,按照此公式取相应的值,相关代码如下:

# 定义函数计算统计量分位数
def A(alpha, data):
    k = len(data)
    data_sort = np.sort(data)  # 排序
    return data_sort[int(k * alpha)]

n=10n=10n=10,根据程序运行结果,我们得到:

标准正态分布标准指数分布
α=0.01\alpha =0.01α=0.010.39365330.56543356
α=0.05\alpha =0.05α=0.050.43707950.65696585
α=0.10\alpha =0.10α=0.100.46595870.7118661
3.4 样本容量变化的误差

为了观察分位数值与样本容量关系,我们分别取值n=10,n=20,...,n=70n=10,n=20,...,n=70n=10,n=20,...,n=70进行观察。
对于标准正态分布,结果如下:

α\alphaα \ nn=10n=10n=10n=20n=20n=20n=30n=30n=30n=40n=40n=40n=50n=50n=50n=60n=60n=60n=70n=70n=70
0.010.393650.338510.315500.304160.296740.291480.28938
0.050.437080.381080.357660.344270.335170.327630.32317
0.100.465960.408430.383080.368310.357590.349420.34489

对于参数为1的标准指数分布,结果如下:

α\alphaα \ nn=10n=10n=10n=20n=20n=20n=30n=30n=30n=40n=40n=40n=50n=50n=50n=60n=60n=60n=70n=70n=70
0.010.565430.641180.690190.719260.744420.760870.77441
0.050.656970.722400.761460.786830.804690.818020.82034
0.100.711870.768910.802470.823760.838930.847430.85112

通过上述的运行结果,我们容易发现,随着nnn值的增大,计算结果趋向稳定,并且呈现单调递增或单调递减的规律,据此可以猜测计算误差正在变小。

3.5 分位数与随机性关系

        作为题外要求的探讨,我们新增了一个研究项目:我们计算的分位数结果与初始随机数有何关系?如果初始随机数选取变化了,那么结果是否大幅变化?在这一节,我们探究分位数计算结果是否对随机数初始值敏感,为此我们设定n=100,α=0.05n=100,\alpha = 0.05n=100,α=0.05,然后不断改变初始随机数来观察计算结果的变化,相关表格如下:

随机结果1随机结果2随机结果3随机结果4随机结果5
标准正态分布0.314740.309830.310640.309780.31054
标准指数分布0.843810.849880.852040.845500.85045

        通过上述表格,我们容易发现,虽然计算结果有所波动,但大致都落在一定合理范围,呈现明显的稳定性。

四 本篇文章相关参考资料与参考文献的声明

  1. 蒙特卡洛方法的介绍与原理来自包括百度百科等互联网资料站点
  2. 用蒙特卡洛进行统计量分布和分位数计算部分参考韦卫老师课件
  3. 编程语言为python,编辑器为pycharm,环境为anaconda+Win10
  4. 文章中的数理统计题目为本人研究生作业,里面代码为本人亲自写

整体代码如下,某些代码在获取不同结果时有轻微改动:

import numpy as np
import math
import matplotlib.pyplot as plt

# 生成n*10万个标准正态分布随机数和标准指数分布随机数
n = 100
dataX_nor = np.random.normal(0, 1, n * 10 * 10000)
dataX_exp = np.random.exponential(1, n * 10 * 10000)
# 将生成的正态分布和指数分布随机数按n个一组形式分组
dataZ_nor = np.reshape(dataX_nor, (n * 10 * 10000 // n, n))
dataZ_exp = np.reshape(dataX_exp, (n * 10 * 10000 // n, n))
# 将得到的分组随机数去计算目标统计量T的若干观测值
dataT_nor = np.zeros(n * 10 * 10000 // n, np.float32)  # 创建空数组
dataT_exp = np.zeros(n * 10 * 10000 // n, np.float32)  # 创建空数组
for i in range(n * 10 * 10000 // n):
    sum_nor, sum_exp = 0, 0
    for j in range(n):
        sum_nor += (dataZ_nor[i][j] - dataZ_nor[i].mean()) ** 2
        sum_exp += (dataZ_exp[i][j] - dataZ_exp[i].mean()) ** 2
    dataT_nor[i] = math.sqrt(sum_nor / n) / (dataZ_nor[i].mean() - dataZ_nor[i].min())
    dataT_exp[i] = math.sqrt(sum_exp / n) / (dataZ_exp[i].mean() - dataZ_exp[i].min())


# 利用程序去表示近似分布函数,输入自变量,输出函数值
def F(x, data):
    k = len(data)
    u = 0
    for index in range(k):
        if x > data[index]:
            u += 1
    return u / k


# 定义函数计算统计量分位数
def A(alpha, data):
    k = len(data)
    data_sort = np.sort(data)  # 排序
    return data_sort[int(k * alpha)]


print(A(0.05, dataT_nor))
print(A(0.05, dataT_exp))
# 绘制函数图像
X = np.linspace(0, 2, 200)  # 创建从-1到9的等间隔的100个数据点
Y_nor = np.zeros(len(X), np.float32)  # 创建空数组
Y_exp = np.zeros(len(X), np.float32)  # 创建空数组
for index in range(len(X)):
    Y_nor[index] = F(X[index], dataT_nor)
    Y_exp[index] = F(X[index], dataT_exp)
plt.plot(X, Y_exp)  # 绘制函数图像
plt.xlabel('x')  # 设置x轴标签
plt.ylabel('y')  # 设置y轴标签
plt.title('Function-Exp')  # 设置图像标题
plt.grid(True)  # 显示网格线
plt.show()  # 显示图像

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

梦星辰.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值