为什么我的循环要花很长时间才能完成?

Why is my loop taking forever to complete?

我是 运行 一个从 2 个指数生成正态分布的算法,如下所示:

set.seed(69420)
j = 1 
Z = c()

# Algorithm
while(j <= 10000){ Y1 <- rexp(1); Y2 <- rexp(1)
    if(Y2 - (Y1 -1)^2/2 >= 0 ){
            X = Y1
            U <- runif(1,0,1)
            if(U > 0.5){
                    Z[j] = X
            } else {
                    Z[j] = -X
            }
            j = j+1
    }
}

然后要求我修改代码如下:“当我们接受样本Y1(如X=Y1)时,随机变量Y=Y2-(Y1-1)2/2也服从指数分布比率为 1,并且它独立于 Y1。修改您的代码以将 Y 作为所需样本之一进行回收。“

我编写了以下代码来完成上述任务。

set.seed(69420)
j = 1
Z = c()
count = 0
Y2 <- rexp(1)
#Algorithm
while(j <= 50){
    Y1 <- rexp(1)
    Y = Y2 - (Y1 -1)^2/2
    if(Y >= 0){
        X = Y1
        Y2 = Y
        U <- runif(1,0,1)
        if(U > 0.5){
            Z[j] = X
        }else {
            Z[j] = -X
        }
        j = j+1
    }
    else if(Y < 0 & j == 1){
       Y2 <- rexp(1)
    }
}

但是,我的循环会一直保持 运行,甚至生成 50 次迭代也需要 5 分钟。有什么我做错的导致长时间 运行 的吗?另外,任何人都可以建议一种对上述代码进行矢量化的方法,以便减少我的处理时间吗?感谢任何帮助。

编辑:在下面发布整个问题以获得更好的解释。

使用拒绝方法,我们可以从标准高斯生成样本 使用来自指数分布 Exp(1) 的样本的分布 N(0,1)。这 算法如下:

  1. 从 Exp(1) 生成 Y1、Y2、独立样本。
  2. 如果 Y2 - (Y1 -1)^2 / 2 >= 0,则设置 X = Y1。否则,返回步骤 1。
  3. 从统一的 U(0,1) 生成样本 U。如果 U > 0.5,则设置 Z = X。 否则,设置 Z = -X。 变量 Z 服从高斯分布。

a) 在 R 中实现算法。在单独的文件中提供您的代码,rejection.R。

b) 使用您的代码生成 10000 个高斯分布样本并报告样本均值和标准差。

c) 修改您的代码以计算指数和均匀样本的数量 您需要分布以获得 10000 个标准高斯样本。 运行 代码 10 次并报告所需样本的平均数量。

d) 当我们在步骤2中接受样本Y1时,随机变量Y = Y2 - (Y1 -1)2 / 2 也服从速率为1的指数分布,与Y1无关。修改您的代码以回收 Y 作为步骤 1 中所需的示例之一。在单独的文件中提交您的代码,rejection2.R.

e) 计算您的代码现在使用了多少样本。 运行 代码 10 次和 报告所需的平均样本数。

我认为您对措辞感到困惑。关键是你应该在每次迭代的循环中收获 Y,它应该是一个指数分布的变量,平均值大约为 1:

set.seed(69420)
j = 1 
Z = c()
Y = c()

# Algorithm
while(j <= 10000){ Y1 <- rexp(1); Y2 <- rexp(1)
    if(Y2 - (Y1 -1)^2/2 >= 0 ){
            X = Y1
            Y[j] <- Y2 - (Y1 -1)^2 / 2
            U <- runif(1,0,1)
            if(U > 0.5){
                    Z[j] = X
            } else {
                    Z[j] = -X
            }
            j = j+1
    }
}

所以 Z 应该服从正态分布:

hist(Z)

Y 呈指数分布

hist(Y)

Y 的均值应该接近 1:

mean(Y)
#> [1] 0.9870445

编辑

根据来自 OP 的更多信息,如果 Y 被拒绝,正确的算法只是从指数分布中采样 Y2:

set.seed(69420)
j = 1
Z = c()
count = 0
Y2 <- rexp(1)
#Algorithm
while(j <= 10000){
    Y1 <- rexp(1)
    Y = Y2 - (Y1 -1)^2/2
    if(Y >= 0){
        X = Y1
        Y2 = Y
        U <- runif(1,0,1)
        if(U > 0.5){
            Z[j] = X
        }else {
            Z[j] = -X
        }
        j = j+1
    }
    else {
       Y2 <- rexp(1)
    }
}

mean(Z)
#> [1] -0.00591165

sd(Z)
#> [1] 0.9961794

reprex package (v2.0.1)

于 2022-03-27 创建