R
当rbinom()
使用种子与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
同样,我发现尽管使用prob
和size
的值,但这种模式仍然存在。任何人都可以向我解释这个谜吗?这引起了相当大的问题,因为结果应该是相同的,因为种子由于某种原因在prob=0.5
时使用/计算的方式不同而不是其他情况。
答案 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
的调用次数不一样(两个与一个。)
因此,对于给定的size
(n
),您的随机种子可能最终处于不同的状态,具体取决于prob
(p
)的值:是否{ {1}}或不。{/ p>
考虑到这一点,您在示例中获得的所有结果现在都应该有意义:
size * prob >= 30
答案 1 :(得分:15)
我将在这个问题上采取逆向立场,并声称期望不合适,文档也不支持。文档没有声明通过调用.Random.seed
可以预期哪些副作用(特别是rbinom
),或者在各种情况下这些副作用可能会或可能不相同。
rbinom
有三个参数:n
,size
和prob
。您的期望是,对于在调用rbinom
之前的随机种子集,.Random.seed
在针对给定rbinom
和任何n后将是相同的> size
和prob
的值(或size
和prob
的任何有限值)。你当然意识到n
的不同值会有所不同。 rbinom
不保证或暗示。
在不知道函数的内部结构的情况下,这是不可知的;正如other answer所示,算法根据size
和prob
的乘积而有所不同。并且内部可能会发生变化,因此这些具体细节可能会发生变化。
至少,在这种情况下,每次调用{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 相同的输入/参数(包括种子)将始终给出相同的结果。只有大多数(或只有一些)参数相同时,期望相同的结果是不切合实际的,除非所有被调用的函数都做出这些保证。