前言

 

二十世纪最伟大的10大算法之一,数学家冯·诺伊曼用驰名世界的赌城摩纳哥的Monte Carlo—来命名这种方法,为它蒙上了一层神秘色彩。所谓蒙特卡洛方法,简单地说就是将问题转化成一个概率问题.并用计算机模拟产生一堆随机数据,之后就是对随机数据的统计工作了! 

蒙特卡洛模拟方法=建立概率模型+计算机模拟+数理统计

什么是MCMC,什么时候使用它?

Markov Chain Monte Carlo,以下简称MCMC,MCMC只是蒙特卡洛方法的一种,尽管可以将许多其他常用方法看作是MCMC的简单特例。

实例分析

1.应用蒙特卡洛模拟方法计算Π值

1)基本原理

R语言蒙特卡洛模拟 r语言蒙特卡洛模拟f分布_算法

P=圆的面积/正方形的面积

P=Π/4

2)用计算机模拟,产生0—1之间的二维的随机数

R语言蒙特卡洛模拟 r语言蒙特卡洛模拟f分布_算法_02

在正方形的内部产生10000个点,统计好多个点(红色)落在圆中,算得一个比值(相当于古典概率)

3)对产生的随机数样本进行统计分析,算出pi值,并计算误差

这里我们看计算公式

P=Π/4,如果将比值乘上4,就可以得到pi值,即:

R语言蒙特卡洛模拟 r语言蒙特卡洛模拟f分布_算法_03

那么问题来了,怎么让计算机知道哪些点在圆中,哪些点在圆外???

计算该点到圆心的距离,然后与R(半径)比较大小即可。

2.代码实现

想对你说的话都在代码里面

# 生成10000个点
# 圆心
n = 10000
center = c(2.5,2.5)
# 半径
radius = 2.5
# distance From Center
dfc = function(a){
  sqrt(sum((center - a)^2))
  # 欧式距离计算公式
}
# 设生成n个点
n = 10000
# 生成2n个区间是[0,5]的均匀分布产生的随机数作为A矩阵的元素

# A 是n行2列
A = matrix(runif(n*2,min = 0,max = 5),nrow = n,ncol = 2,byrow = T)
# 对矩阵的每行的元素使用求距离函数,得到向量B
# B 是存放这点到圆心的距离,注意B是向量
B = apply(A, 1, dfc)
# 求向量b中的元素值(距离)小于半径的个数

num = mean(B < radius)
# 这是一个逻辑表达式的结果要么为0,要么为1
# 所以对这个向量求均值,就得到了比例
print(num)


# 绘图
# 设置背景色
par(bg = 'beige')
# 回值模型生成的所有点,让横纵轴不显示名称
# asp = 1的色湖之是为了不使后面的draw.circle函数绘制元的时候出现偏差
plot(A,col='azure3',asp=1,xlab = '',ylab = '',main = 'MC method application')

# 添加四条线,勾勒出正方形
abline(h=0,col='goldenrod4',lty = 'dotdash',lwd=3)
abline(h=5,col='goldenrod4',lty = 'dotdash',lwd=3)
abline(v=0,col='goldenrod4',lty = 'dotdash',lwd=3)
abline(v=5,col='goldenrod4',lty = 'dotdash',lwd=3)


# 绘制圆内和边缘上的点
points(A[B<radius,],col='aquamarine3')
#导入绘圆的包
library(plotrix)
draw.circle(2.5,2.5,2.5,border='coral2',lty='dashed',lwd=3)
# 添加圆心
points(x=2.5,y=2.5,col='brown1',pch=19,cex=1.5,lwd=1.5)
# 美化
points(x=2.5,y=2.5,col='olivedrab3',pch=11,cex=3,lwd=3)

R语言蒙特卡洛模拟 r语言蒙特卡洛模拟f分布_r语言_04

# 模拟多次,用循环
# 创建向量 
piVec = c()
# 循环2000次
for(i in 1:2000){
  n = i
  # i个区间是在[0,5]的均匀分布产生的随机数构成n行2列的矩阵A
  A = matrix(runif(n*2,min=0,max=5),nrow = n,ncol=2,byrow=T)
  # 求点到圆心的距离
  # B 是存放这点到圆心的距离,注意B是向量
  b = apply(A, 1, dfc)
  # 求向量b中的元素值(距离)小于半径的个数
  
  d = subset(b,b<radius)
  # 得到比例
  num = length(d)/length(b)
  piVec[i]=num*4
}
  # 这是一个逻辑表达式的结果要么为0,要么为1
  # 所以对这个向量求均值,就得到了比例
library(data.table)
  # 将piVec转为数据框
Pi = data.frame(piVec)
Pi = data.table(Pi)
  # ind列中储存的是模拟次数
Pi[,ind:=seq(0,1999)]
  # error列是误差
Pi[,error:=abs(pi-piVec)]
Pi = data.frame(Pi)
  # pi数据捐给的三列分别为序号、实际值、误差
names(Pi) = c('guess','ind','error')
  # 画出误差
library(ggplot2)
  # x轴是模拟次数,y是误差
ggplot(Pi,aes(x=ind,y=error))+
  geom_line(colour='#388E8E')+
  ggtitle('Error')+
  xlab('Sample Size')+
  ylab('Error')

R语言蒙特卡洛模拟 r语言蒙特卡洛模拟f分布_随机数_05