Как мне установить.Seed для моделирования в R для достижения воспроизводимости в ОС Windows

#r #windows #seeding #reproducible-research

#r #Windows #заполнение #воспроизводимый-исследование

Вопрос:

У меня есть моделирование, выполненное с помощью приведенной ниже функции в R :

 ## Load packages and prepare multicore process
library(forecast)
library(future.apply)
plan(multisession)
library(parallel)
library(foreach)
library(doParallel)
n_cores <- detectCores()
cl <- makeCluster(n_cores)
registerDoParallel(cores = detectCores())
set.seed(1)
bootstrap1 <- function(n, phi){
  ts <- arima.sim(n, model = list(ar=phi, order = c(1, 1, 0)), sd = 1)
  #ts <- numeric(n)
  #ts[1] <- rnorm(1)
  #for(i in 2:length(ts))
  #  ts[i] <- 2 * ts[i - 1]   rnorm(1)
  ########################################################
  ## create a vector of block sizes
  t <- length(ts)    # the length of the time series
  lb <- seq(n-2) 1   # vector of block sizes to be 1 < l < n (i.e to be between 1 and n exclusively)
  ########################################################
  ## This section create matrix to store block means
  BOOTSTRAP <- matrix(nrow = 1, ncol = length(lb))
  colnames(BOOTSTRAP) <-lb
  #BOOTSTRAP <- list(length(lb))
  ########################################################
  ## This section use foreach function to do detail in the brace
  BOOTSTRAP <- foreach(b = 1:length(lb), .combine = 'cbind') %dopar%{
    l <- lb[b]# block size at each instance 
    m <- ceiling(t / l)                                 # number of blocks
    blk <- split(ts, rep(1:m, each=l, length.out = t))  # divides the series into blocks
    ######################################################
    res<-sample(blk, replace=T, 1000)        # resamples the blocks
    res.unlist <- unlist(res, use.names = FALSE)   # unlist the bootstrap series
    train <- head(res.unlist, round(length(res.unlist) - 10)) # Train set
    test <- tail(res.unlist, length(res.unlist) - length(train)) # Test set
    nfuture <- forecast::forecast(train, model = forecast::auto.arima(train), lambda=0, biasadj=TRUE, h = length(test))$mean        # makes the `forecast of test set
    RMSE <- Metrics::rmse(test, nfuture)      # RETURN RMSE
    BOOTSTRAP[b] <- RMSE
  }
  BOOTSTRAPS <- matrix(BOOTSTRAP, nrow = 1, ncol = length(lb))
  colnames(BOOTSTRAPS) <- lb
  BOOTSTRAPS
  return(list("BOOTSTRAPS" = BOOTSTRAPS))
}
  

Я использую for loop для печати его результата три раза.

 for (i in 1:3)  { set.seed(1)
  print(bootstrap1(10, 0.5))
}
  

У меня есть следующий результат:

 ##            2        3        4         5         6        7         8        9
##[1,] 1.207381 1.447382 1.282099 0.9311434 0.8481634 1.006494 0.9829584 1.205194
##            2        3       4        5         6        7        8        9
##[1,] 1.404846 1.262756 1.50738 1.188452 0.8981125 1.001651 1.349721 1.579556
##            2        3        4        5         6       7         8        9
##[1,] 1.265196 1.080703 1.074807 1.430653 0.9166268 1.12537 0.9492137 1.201763
  

Если мне придется запускать это несколько раз, я получу другой результат.

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

Комментарии:

1. Я получаю те же числа, что и результаты в for цикле для всех 3 раундов, но также получил предупреждение executing %dopar% sequentially: no parallel backend registered

Ответ №1:

Мы могли бы указать kind in set.seed . Если мы делаем это внутри цикла, он вернет те же значения

 for (i in 1:3)  {
    set.seed(1, kind = "L'Ecuyer-CMRG")
   print(bootstrap1(10, 0.5))
 }
#$BOOTSTRAPS
#            2        3        4        5        6        7        8        9
#[1,] 4.189426 6.428085 3.672116 3.893026 2.685741 3.821201 3.286509 4.062811

#$BOOTSTRAPS
#            2        3        4        5        6        7        8        9
#[1,] 4.189426 6.428085 3.672116 3.893026 2.685741 3.821201 3.286509 4.062811

#$BOOTSTRAPS
#            2        3        4        5        6        7        8        9
#[1,] 4.189426 6.428085 3.672116 3.893026 2.685741 3.821201 3.286509 4.062811
  

Если предполагается возвращать разные значения для каждой итерации в for цикле и получать тот же результат при последующих запусках, укажите set.seed вне цикла

1) Первый запуск

 set.seed(1, kind = "L'Ecuyer-CMRG")
for (i in 1:3)  {    
    print(bootstrap1(10, 0.5))
  }
#$BOOTSTRAPS
#            2        3        4        5        6        7        8        9
#[1,] 4.189426 6.428085 3.672116 3.893026 2.685741 3.821201 3.286509 4.062811

#$BOOTSTRAPS
#            2        3        4       5        6        7        8        9
#[1,] 1.476428 1.806258 2.071091 2.09906 2.014298 1.032776 2.573738 1.831142

#$BOOTSTRAPS
#            2        3        4        5       6        7        8        9
#[1,] 2.248546 1.838302 2.345557 1.696614 2.06357 1.502569 1.912556 1.906049
  

2) Второй запуск

 set.seed(1, kind = "L'Ecuyer-CMRG")
for (i in 1:3)  {    
    print(bootstrap1(10, 0.5))
  }
#$BOOTSTRAPS
#            2        3        4        5        6        7        8        9
#[1,] 4.189426 6.428085 3.672116 3.893026 2.685741 3.821201 3.286509 4.062811

#$BOOTSTRAPS
#            2        3        4       5        6        7        8        9
#[1,] 1.476428 1.806258 2.071091 2.09906 2.014298 1.032776 2.573738 1.831142

#$BOOTSTRAPS
#            2        3        4        5       6        7        8        9
#[1,] 2.248546 1.838302 2.345557 1.696614 2.06357 1.502569 1.912556 1.906049
  

Согласно ?set.seed

«L’Ecuyer-CMRG»: — «Комбинированный многократно рекурсивный генератор’ от L’Ecuyer (1999), каждый элемент которого представляет собой мультипликативный генератор обратной связи с тремя целочисленными элементами: таким образом, начальное значение представляет собой (подписанный) целочисленный вектор длиной 6. Период составляет около 2 ^ 191. 6 элементов начального числа внутренне рассматриваются как 32-разрядные целые числа без знака. Ни первые три, ни последние три не должны быть равны нулю, и они ограничены значениями менее 4294967087 и 4294944443 соответственно. Это само по себе не особенно интересно, но обеспечивает основу для нескольких потоков, используемых в параллельном пакете.

Комментарии:

1. Я скопировал ваш код и запустил его несколько раз, но все еще не могу получить воспроизводимый результат, пожалуйста, проверьте для меня еще раз, чего мне может не хватать.

2. Я боролся с приведенными вами примерами и не могу получить какую-либо форму воспроизводимого результата.

3. Я на Windows, может ли это быть причиной, по которой это не работает?

4. @DanielJames — В Windows я думаю, что значение set.seed() должно быть передано каждому работнику в кластере, но я не помню, как это сделать.

5. @DanielJames я тестировал его на Mac.