R:set.seed()的怪异行为

big*_*377 9 random r seed

当我在set.seed(0)和set.seed(1)时在R中发生奇怪的事情;

set.seed(0)
sample(1:100,size=10,replace=TRUE)
#### [1] 90 27 38 58 91 21 90 95 67 63


set.seed(1)
sample(1:100,size=10,replace=TRUE)
#### [1] 27 38 58 91 21 90 95 67 63  7
Run Code Online (Sandbox Code Playgroud)

当将种子从0更改为1时,我得到完全相同的序列,但移过1个单元格!

请注意,如果我执行set.seed(2),我会得到一个看起来完全不同(随机?)的向量.

set.seed(2)
sample(1:100,size=10,replace=TRUE)
#### [1] 19 71 58 17 95 95 13 84 47 55
Run Code Online (Sandbox Code Playgroud)

谁知道这里发生了什么?

Chr*_*den 15

这适用于Mersenne-Twister RNG的R实现.

set.seed()获取提供的种子并对其进行加密(在C函数RNG_Init中):

for(j = 0; j < 50; j++)
  seed = (69069 * seed + 1);
Run Code Online (Sandbox Code Playgroud)

那个扰乱的数字(seed)然后被扰乱625次以填写Mersenne-Twister的初始状态:

for(j = 0; j < RNG_Table[kind].n_seed; j++) {
  seed = (69069 * seed + 1);
  RNG_Table[kind].i_seed[j] = seed;
}
Run Code Online (Sandbox Code Playgroud)

我们可以使用.Random.seed检查RNG的初始状态:

set.seed(0)
x <- .Random.seed

set.seed(1)
y <- .Random.seed

table(x %in% y)
Run Code Online (Sandbox Code Playgroud)

你可以从表中看到有很多重叠.比较这个seed = 3:

set.seed(3)
z <- .Random.seed

table(z %in% x)
table(z %in% y)
Run Code Online (Sandbox Code Playgroud)

回到0和1的情况,如果我们检查状态本身(忽略向量的前两个元素不适用于我们正在看的东西),你可以看到状态被一个偏移:

x[3:10]
# 1280795612 -169270483 -442010614 -603558397 -222347416 1489374793  865871222
# 1734802815

y[3:10] 
# -169270483 -442010614 -603558397 -222347416 1489374793  865871222 1734802815
# 98005428
Run Code Online (Sandbox Code Playgroud)

由于选择的值sample()基于这些数字,因此您会得到奇怪的行为.

  • 请注意,如果你`set.seed(69070)`那么你得到一个额外的移位1(考虑到上面的第一个for循环,这是有意义的).我们可以扩展循环以找到下一个移位1,等等.0,1组合很有意思,彼此相邻,没有看到循环,任何人都不可能偶然比较1和69070. (2认同)