我从Msc开始学习R软件包,但是我在练习中遇到了问题。练习是这样的:
“假设我们要使用基本的蒙特卡洛方法来估计∫x2(在1到0之间确定)。本质上,我们将飞镖扔到曲线上并计算落在曲线下方的飞镖的数量。方法包括:
1)初始化:hits = 0
2)(1:N中的i): 生成两个随机数U1,U2,介于0和1之间。如果U2 <(U1)^ 2,则hits = hits + 1结尾。
3)区域估计=点击次数/ N
使用循环提供R代码以实现此Monte-Carlo算法。您的功能需要多少时间?提供更有效的代码,避免前面的循环。说明通过矢量化代码可以提高的效率。”
我有这些代码,但我认为我做错了。
montecarlo <- function(N){
hits=0
for (i in 1:N){
U1 <- runif(1, 0, 1)
U2 <- runif(1, 0, 1)
if (U2 < (U1)^2){
hits = hits+1}}
return(hits/N)
}
montecarlo2 <- function(N){
hits=0
U1 <- runif (1:N, 0, 1)
U2 <- runif (1:N, 0, 1)
hits= hits+1 [U2<(U1)^2]
return(hits/N)
}
对于第一个带有循环的方法,我已经获得(例如):
> montecarlo(23)
[1] 0.3478261
> montecarlo(852)
[1] 0.3591549
> montecarlo(8563255)
[1] 0.3332472
你能帮我吗?非常感谢:
答案 0 :(得分:5)
其中一种方式:
montecarlo_for <- function(N) {
hits <- 0
for (i in 1:N) {
U1 <- runif(1)
U2 <- runif(1)
if (U2 < (U1) ^ 2) hits <- hits + 1
}
return(hits / N)
}
矢量化
montecarlo_vec <- function(N) {
sum(runif(N) < runif(N)^2) / N
}
例如使用microbenchmark
软件包比较速度:
microbenchmark::microbenchmark(times = 50,
montecarlo_for(1e5),
montecarlo_vec(1e5)
)
我的机器上的速度比较显示,向量化方法大约快100倍(平均和中值时间如下所示):
Unit: milliseconds
expr mean median
montecarlo_for(1e+05) 509.927001 497.238904
montecarlo_vec(1e+05) 5.214527 4.922007
只是为了好玩,如果您想看看算法随着样本数量的增加收敛到结果(1/3)的速度有多快:
plot(sapply(1:1000, montecarlo_vec), type = "line")
答案 1 :(得分:1)
这是我发现有助于估计积分的一种方法。请考虑以下内容:
因此,如果我们在支撑A上有一个分布G,那么我们可以用分布G中的样本估计f(x)在A上的积分。函数f不必严格为正。
在您的情况下,让X均匀分布,然后
因为支撑中的所有x的g(x)= 1。所以你可以用
来估计积分N = 100000
mean(runif(N)^2)
您还可以让X为beta随机变量,并使用来估计积分
x = rbeta(N, 2, 1)
fx = x^2
gx = dbeta(x, 2, 1)
mean(fx / gx)
这是在正实线上估算函数的另一个示例。
f = function(x)
abs(sin(x)) / (x+1)^2
x = rgamma(N, 2, 1/4)
fx = f(x)
gx = dgamma(x, 2, 1/4)
mean(fx / gx)
我不记得所有理论(何时使用这种方法可能会有一些限制),但是通常,如果您可以在与积分相同的支持下从任何分布中进行抽样,则可以估算出积分如上。而且,如果您选择的G的密度与函数f更加“接近”,则您的蒙特卡洛误差就越小。