#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.