【问题标题】:Monte Carlo integration in R : getting the wrong answer [using Hit or Miss]R中的蒙特卡洛积分:得到错误的答案[使用命中或未命中]
【发布时间】:2014-02-25 00:13:55
【问题描述】:

所以我使用蒙特卡罗方法来评估一堆函数的定积分。 首先,

    y = x ^ (-0.5) ; for x in [0.01,1]

为此,我在 R 中的代码如下所示

#
s <- NULL

m<- 100
a<- 0.01
b<- 1
set.seed(5)
x<-runif(m,a,b)
y<-runif(m,0,1)

for (i in 1:m){
if(y[i]<(x[i]^(-0.5))){
s[i] <- 1
}
else{
s[i] <-0
}
}


nn<-sum(s==1)*(b-a)/m
print(nn)
#

答案 (nn):0.99

实际答案:1.8

我无法弄清楚我哪里出了问题。我是不是做错了什么?

【问题讨论】:

    标签: r statistics simulation


    【解决方案1】:

    一个小于 1 的负数次方的数总是大于任何小于 1 的数,所以当你得到一个全为 1 的向量时,你不应该感到惊讶。

    您使用的矩形太短(高度为 1)。实际上,它应该是 10 高(因为 0.01^-0.5=10)是最大值。

    然后你把矩形的总面积乘以s的平均值,所以修改后的代码是这样的:

    s <- NULL
    
    m<- 100
    a<- 0.01
    b<- 1
    set.seed(5)
    x<-runif(m,a,b)
    y<-10*runif(m,0,1)
    
    for (i in 1:m){
        if(y[i]<(x[i]^(-0.5))){
            s[i] <- 1
        }
        else{
            s[i] <-0
        }
    }
    
    nn<-sum(s)*(b-a)/m*10#note that the addition of the area of the rectangle
    print(nn)
    

    我得到了 1.683 的结果,这更接近真实答案。

    编辑:做了一个多余的乘法,答案稍作修改

    【讨论】:

    • 这很有帮助。我从来没有想过必须根据最小值/最大值来改变考虑中的矩形。我还有另一个问题。相同的代码 - 矢量化,并且不使用任何“for”循环,给了我一个截然不同的答案。知道为什么吗?这是代码:m&lt;-100000 a&lt;-0.01 b&lt;-1 set.seed(7063257) x&lt;-runif(m,a,b) y&lt;-10*runif(m,0,1) s&lt;-ifelse(y&lt;(x^(-0.05)),1,0) s&lt;-sum(s)*10*(b-a)/m print(s) 我得到大约 1.038
    • 你的力量多了一个零:-0.05 而不是 -0.5。如果这得到纠正,您的代码就可以工作
    【解决方案2】:

    正如 user1362215 指出的那样,您的函数应该包含在矩形中。如果增加 n,您将更接近解决方案。这是一个矢量化的解决方案。结果在范围内。

    # Hit and miss
    
    f <- function(x) x ^ (-0.5)
    
    n <- 1000000
    a <- 0.01
    b <- 1
    
    #ceiling(max(f((seq(0.01,1,by=0.001)))))
    #[1] 10
    
    set.seed(5)
    x <- runif(n,a,b)
    y <- 10*runif(n,0,1)
    R <- sum(y < f(x))/n
    (b-a)*10*R
    
    #[1] 1.805701
    
    
    # Repeat a few times to look at the distribution
    set.seed(5)
    n <- 100000
    r <- replicate(1000,sum(10*runif(n,0,1) < f(runif(n,a,b)))/n *(b-a)*10)
    hist(r)
    summary(r)
    
    #   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    #  1.755   1.792   1.800   1.800   1.809   1.845 
    
    
    
    # Sample mean method for comparison
    set.seed(5)
    r <- replicate(1000, mean(f(runif(n, a,b)))*(b-a))
    hist(r)
    summary(r)
    
    #   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    #  1.788   1.798   1.800   1.800   1.803   1.813 
    

    重新编辑:我假设 x*2 + y^2, [-1,1] 您指的是一个圆而不是函数 f(z)。所以真的要通过模拟来估计单位圆的面积/Pi。

    f2 <- function(x)   sqrt(1-x^2)
    
    s <- seq(-1 , 1 ,by=0.001)
    plot(s,f2(s))
    # Get the max value of function within the range
    c <- ceiling(max(f2(s)))
    # [1] 1
    
    n <- 1000000
    a <- -1
    b <- 1
    
    set.seed(5)
    x <- runif(n,a,b)
    y <- c*runif(n,0,1)
    R <- sum(y < f2(x))/n
    
    (b-a)*c*R
    #[1] 1.57063 # multiply it by 2 to get full area
    
    pi/2
    #[1] 1.570796
    

    【讨论】:

    • 干得好,包括分配行为!
    • 太棒了。谢谢你。另一个问题 - 如何选择与长度相乘的值?我的意思是,对于这个函数,正如@user1362215 指出的那样,我需要执行“10*runif ...”,而不仅仅是基于最大值的“runif”。假设我有一个类似 "x^2 + y^2" 的函数,而不是 [x,y from -1 to 1] ,这是否意味着我必须考虑 "2*runif" ?
    • @Raaj;是的,这取决于功能 - 我只会寻找整个范围内的最大值(如果可能,请避免任何差异)。我相信其他人更适合在这里提供建议
    • Re: x^2 + y^2 [x,y : -1 to 1] 当我手动求解时,我最终得到 8/3 或 2.6667。当我使用 MC 解决时,我得到 3.2 我注意到当我更改最大上限时,该值会发生应有的变化。但是,我只是想知道这是否是 MC 可以给我的最佳估计,因为差异似乎太大了!因此,我询问了如何在上面的代码中选择“c”值(函数的最大值)
    • 增加 c 应该不会改变太多结果 - 运行上面的编辑代码更改 c=10。您是否要计算圆的面积(对于单位圆 x*2 + y*2 = 1)?答案应该是 Pi。
    【解决方案3】:

    接受/拒绝的 Monte Carlo 替代方法是统一生成 x 值,平均得到的 y = f(x) 值以估计平均高度,然后将其乘以区间长度以获得估计面积。我对 R 不太了解,所以这里用 Ruby 来说明算法:

    def f(x)
      x ** -0.5
    end
    
    sum = 0.0
    10000.times { sum += f(0.01 + 0.99 * rand) }
    print (1.0 - 0.01) * (sum / 10000)
    

    我得到的结果在 1.8 +/- 0.02 范围内

    您还可以通过使用对立随机变量来提高估算器的精度 - 对于您生成的每个 x,还可以使用与 x 的中位数镜像的对称 x 值。

    使用@user20650 的代码指导如何在 R 中执行此操作,您可以估计 Pi / 2 如下:

    f <- function(x)    sqrt(1-x^2)
    n <- 100000
    a <- -1
    b <- 1
    range <- b-a
    set.seed(5)
    r <- replicate(1000, mean(f(runif(n,a,b))) * range)
    hist(r)
    summary(r)
    #   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
    #  1.566   1.570   1.571   1.571   1.572   1.575 
    

    这种方法不需要边界函数,通常它比接受/拒绝方法产生更高的精度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-26
      • 2020-07-05
      • 2017-04-19
      • 2014-03-30
      • 2011-11-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多