R: странное поведение set.seed()

Странная вещь происходит, когда в R я делаю set.seed(0) и set.seed(1);

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

При изменении начального числа с 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

Кто-нибудь знает, что здесь происходит?


person bigO6377    schedule 11.02.2014    source источник
comment
Кроме того, для seed требуется целое число > is.integer(0) [1] FALSE   -  person rawr    schedule 12.02.2014
comment
@rawr - вас ввели в заблуждение: 0 - это двойное число, следовательно, is.integer(0) - ЛОЖЬ, а is.integer(0L) - ИСТИНА. Но set.seed заставит ввод с плавающей запятой быть целым числом. Так что дело не в этом.   -  person Carl Witthoft    schedule 12.02.2014
comment
интересно .. спасибо Карл   -  person rawr    schedule 12.02.2014


Ответы (2)


Это относится к реализации RNG Mersenne-Twister RNG.

set.seed() берет предоставленное начальное число и перемешивает его (в функции C RNG_Init):

for(j = 0; j < 50; j++)
  seed = (69069 * seed + 1);

Это зашифрованное число (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;
}

Мы можем проверить начальное состояние RNG, используя .Random.seed:

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

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

table(x %in% y)

Из таблицы видно, что много совпадений. Сравните это с seed = 3:

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

table(z %in% x)
table(z %in% y)

Возвращаясь к случаю 0 и 1, если мы исследуем само состояние (игнорируя первые два элемента вектора, которые не относятся к тому, что мы смотрим), вы можете увидеть, что состояние смещено на единицу:

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

y[3:10] 
# -169270483 -442010614 -603558397 -222347416 1489374793  865871222 1734802815
# 98005428

Поскольку значения, выбранные sample(), основаны на этих числах, вы получаете странное поведение.

person Christopher Louden    schedule 11.02.2014
comment
Спасибо! Это, безусловно, вносит некоторую ясность в этот вопрос. Мне придется внимательно изучить этот код, чтобы увидеть, как/почему 0 и 1 получаются такими похожими. - person bigO6377; 12.02.2014
comment
Добро пожаловать. Имейте в виду, что максимальное целое число равно 2 ^ 32 - 1 и что число будет переполнено до отрицательного значения. - person Christopher Louden; 12.02.2014
comment
Обратите внимание, что если вы set.seed(69070), то вы получите дополнительный сдвиг на 1 (имеет смысл, учитывая 1-й цикл for выше). Мы могли бы расширить цикл, чтобы найти следующий сдвиг на 1 и т. д. Комбинация 0,1 просто интересна рядом друг с другом, не видя цикла, маловероятно, что кто-то случайно сравнит 1 и 69070. - person Greg Snow; 12.02.2014
comment
@bigO6377 Глядя на math.sci .hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html похоже, что авторы МП знают о проблеме и исправили ее (улучшена инициализация -- не знаю точно, когда ), так что вы должны спросить ребят из R, могут ли они обновить свою версию - person loreb; 12.02.2014
comment
Согласно wellington.pm.org/archive/200704/randomness/mt19937.pl они исправили это как минимум 7 лет назад... - person loreb; 12.02.2014

Как видно из другого ответа, семена 0 и 1 приводят к почти одинаковым начальным состояниям. Кроме того, Mersenne Twister PRNG имеет серьезное ограничение — "почти похожие начальные состояния потребуется много времени, чтобы расходиться"

Поэтому рекомендуется использовать альтернативы, такие как WELL PRNG (который можно найти в пакете randtoolbox)

person Nishanth    schedule 12.02.2014