Как я могу заставить R's lapply (и mclapply) восстановить состояние генератора случайных чисел?

R игнорирует настройку .Random.seed внутри лапши. Однако использование set.seed работает нормально.

Некоторый код:

# I can save the state of the RNG for a few seeds
seed.list <- lapply( 1:5, function(x) {
                        set.seed(x)
                        seed.state <- .Random.seed
                        print( rnorm(1) )
                        return( seed.state )}) 
#[1] -0.6264538
#[1] -0.8969145
#[1] -0.9619334

# But I get different numbers if I try to restore 
# the state of the RNG inside of an lapply
tmp.rest.state <-  lapply(1:5, function(x) { 
                        .Random.seed <- seed.list[[x]]
                        print(rnorm(1))})
# [1] -0.2925257
# [1] 0.2587882
# [1] -1.152132

# lapply is just ignoring the assignment of .Random.seed
.Random.seed <- seed.list[[3]]
print( rnorm(1) ) # The last printed value from seed.list
# [1] -0.9619334
print( rnorm(1) ) # The first value in tmp.rest.state
# [1] -0.2925257

Моя цель состоит в том, чтобы запустить MCMC контрольной точки, чтобы их можно было точно возобновить. Я могу легко сохранить состояние генератора случайных чисел, я просто не могу заставить R загрузить его внутри зацикленного цикла!

Есть ли способ заставить R заметить настройку .Random.seed? Или есть более простой способ сделать это?

Если это имеет значение, я использую 64-битный R:

R version 2.15.1 (2012-06-22) -- "Roasted Marshmallows"
Platform: x86_64-pc-linux-gnu (64-bit)

В Ubuntu 12.04 LTS:

nathanvan@nathanvan-N61Jq:~$ uname -a
Linux nathanvan-N61Jq 3.2.0-26-generic #41-Ubuntu SMP Thu Jun 14 17:49:24 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux

person Nathan VanHoudnos    schedule 07.07.2012    source источник
comment
+1 Очень интересный вопрос, спасибо.   -  person Andrie    schedule 07.07.2012


Ответы (1)


Это происходит потому, что .Random.seed оценивается как локальный объект внутри вашего вызова lapply.

Вам нужно присвоить значение .Random.seed в глобальной среде:

tmp.rest.state <- lapply(seed.list, function(x) {
    assign(".Random.seed", x, envir=globalenv())
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555

Причина, по которой ваш код не работает, заключается в том, что .Random.seed назначается в среде анонимной функции в lapply, а rnorm() ищет .Random.seed в глобальной среде.


Для справки, вот моя первая попытка, которая сработает только в некоторых ситуациях:

Вот один из способов исправить это, используя <<-. (Да, я знаю, что это осуждается, но, возможно, оправдано. Альтернативой может быть использование eval() и принудительная оценка в вызывающей среде.

tmp.rest.state <- lapply(seed.list, function(x) {
    .Random.seed <<- x
    print(rnorm(1))
  }
)

[1] -0.6264538
[1] -0.8969145
[1] -0.9619334
[1] 0.2167549
[1] -0.8408555

Обратите внимание, что это решение не будет работать, если ваша lapply() вложена в другую функцию, поскольку <<- оценивается только в родительской среде, а не в глобальной среде.

person Andrie    schedule 07.07.2012
comment
Может быть, вставка .Random.seed в именованную среду повысит универсальность? Или решение эталонного класса? - person IRTFM; 08.07.2012
comment
Также можно использовать .GlobalEnv$.Random.seed <- x или .GlobalEnv[[".Random.seed"]] <- x. - person Josh O'Brien; 08.07.2012
comment
Обратите внимание, что это решение не будет работать, если ваш lapply() вложен в другую функцию, поскольку ‹‹- оценивается только в родительской среде, а не в глобальной среде. Это не совсем верно. <<- сначала посмотрит в родительской среде, существует ли там объект с правильным именем, а затем перейдет в прародительскую среду и так далее. Если переменная не найдена, присваивание происходит в глобальной среде. - person Emil Bode; 19.12.2018