r中rbinom(prob = 0.5)的种子行为不稳定

时间:2013-09-20 01:35:18

标签: r random

Rrbinom()使用种子与prob=0.5结合使用{}时,我发现了我认为不稳定的行为(但我希望有一个简单的解释)用过的。一般想法:对我来说,如果我设置种子,运行rbinom()一次(即进行一个随机过程),尽管设置了prob的值,随机 种子应该改变一个增量。然后,如果我再次将种子设置为相同的值,并再次运行另一个随机过程(例如rbinom(),但可能具有不同的prob值),则种子应再次更改为相同价值与之前的单一随机过程相同。

我发现只要我R使用任何rbinom()prob!=0.5就会这样做。这是一个例子:

比较种子向量.Random.seed,得出除0.5之外的两个概率:

set.seed(234908)
x <- rbinom(n=1,size=60,prob=0.4)
temp1 <- .Random.seed

set.seed(234908)
x <- rbinom(n=1,size=60,prob=0.3)
temp2 <- .Random.seed

any(temp1!=temp2)
> [1] FALSE

比较种子向量.Random.seed,对于prob = 0.5与prob!= 0.5:

set.seed(234908)
x <- rbinom(n=1,size=60,prob=0.5)
temp1 <- .Random.seed

set.seed(234908)
x <- rbinom(n=1,size=60,prob=0.3)
temp2 <- .Random.seed
any(temp1!=temp2)
> [1] TRUE

temp1==temp2
> [1]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
> [8]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
...

我发现这是prob=0.5与所有其他概率的所有比较 在集合{0.1,0.2,...,0.9}。同样,如果我比较prob的任何值 {0.1,0.2,...,0.9}不是0.5,.Random.seed向量总是逐个元素相等。这些事实也适用于size内的奇数或偶数rbinom()

让它变得更奇怪(我道歉这有点令人费解 - 它与我的函数编写方式有关),当我使用在向量中保存为元素的概率时,如果0.5是第一个元素我也有同样的问题,但不是第二个。以下是此案例的示例:

第一种情况:0.5是向量中引用的第一个概率

set.seed(234908)
MNAR <- c(0.5,0.3)
x <- rbinom(n=1,size=60,prob=MNAR[1])
y <- rbinom(n=1,size=50,prob=MNAR[2])
temp1 <- .Random.seed

set.seed(234908)
MNAR <- c(0.1,0.3)
x <- rbinom(n=1,size=60,prob=MNAR[1])
y <- rbinom(n=1,size=50,prob=MNAR[2])
temp2 <- .Random.seed

any(temp1!=temp2)
> [1] TRUE

any(temp1!=temp2)
> [1]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE  TRUE
> [8]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE

第二种情况:0.5是向量中引用的第二个概率

set.seed(234908)
MNAR <- c(0.3,0.5)
x <- rbinom(n=1,size=60,prob=MNAR[1])
y <- rbinom(n=1,size=50,prob=MNAR[2])
temp1 <- .Random.seed

set.seed(234908)
MNAR <- c(0.1,0.3)
x <- rbinom(n=1,size=60,prob=MNAR[1])
y <- rbinom(n=1,size=50,prob=MNAR[2])
temp2 <- .Random.seed

any(temp1!=temp2)
> [1] FALSE

同样,我发现尽管使用probsize的值,但这种模式仍然存在。任何人都可以向我解释这个谜吗?这引起了相当大的问题,因为结果应该是相同的,因为种子由于某种原因在prob=0.5时使用/计算的方式不同而不是其他情况。

2 个答案:

答案 0 :(得分:39)

让我们把我们的评论转化为答案。感谢Ben Bolker让我们走上正确的轨道,并附上代码链接:https://svn.r-project.org/R/trunk/src/nmath/rbinom.c以及跟踪调用unif_rand()的位置的建议。

快速扫描,似乎代码分为两部分,由注释分隔:

/*-------------------------- np = n*p >= 30 : ------------------- */

/*---------------------- np = n*p < 30 : ------------------------- */

在其中每个中,unif_rand的调用次数不一样(两个与一个。)

因此,对于给定的sizen),您的随机种子可能最终处于不同的状态,具体取决于probp)的值:是否{ {1}}或不。{/ p>

考虑到这一点,您在示例中获得的所有结果现在都应该有意义:

size * prob >= 30

答案 1 :(得分:15)

我将在这个问题上采取逆向立场,并声称期望不合适,文档也不支持。文档没有声明通过调用.Random.seed可以预期哪些副作用(特别是rbinom),或者在各种情况下这些副作用可能会或可能不相同。

rbinom有三个参数:nsizeprob。您的期望是,对于在调用rbinom之前的随机种子集,.Random.seed在针对给定rbinom任何n后将是相同的> sizeprob的值(或sizeprob的任何有限值)。你当然意识到n的不同值会有所不同。 rbinom不保证或暗示。

在不知道函数的内部结构的情况下,这是不可知的;正如other answer所示,算法根据sizeprob的乘积而有所不同。并且内部可能会发生变化,因此这些具体细节可能会发生变化。

至少,在这种情况下,每次调用{em>相同 .Random.seed {{1} rbinom之后,生成的n都会相同} size。我可以构建一个甚至不是真的病理函数:

prob

基本上,此函数查看第二个时间的十分之一是否为奇数或甚至决定是否绘制随机数。运行此功能,seedtweak <- function() { if(floor(as.POSIXlt(Sys.time())$sec * 10) %% 2) { runif(1) } invisible(NULL) } 可能会也可能不会更改:

.Random.seed

你能做到的最好(应该?)希望一组给定的代码与 all 相同的输入/参数(包括种子)将始终给出相同的结果。只有大多数(或只有一些)参数相同时,期望相同的结果是不切合实际的,除非所有被调用的函数都做出这些保证。