我有以下R脚本需要超过24小时,但最后还是运行在Windows 10的10-gigabyte ram和core M7。该脚本执行以下操作:
这是我想要做的 R
A. 我已经生成了一个 50 时间序列数据集。
B. 我将相同的时间序列数据集切成以下大小的块:2,3,...,48,49使我有 48 个不同的时间序列,这些时间序列是从上面的第 1 步形成的。
C.我划分的每个48-时间序列数据集成train和test套所以可以使用rmse功能在Metrics包以获得均方根误差(RMSE),用于形成在步骤2中的48子系列。
D. 然后根据它们的块大小将每个系列的 RMSE 制成表格
E. 我ARIMA为每个 48 个不同的时间序列数据集获得了最佳模型。
我的 R 脚本
# simulate arima(1,0,0)
library(forecast)
library(Metrics)
n=50
phi <- 0.5
set.seed(1)
wn <- rnorm(n, mean=0, sd=1)
ar1 <- sqrt((wn[1])^2/(1-phi^2))
for(i in 2:n){
ar1[i] <- ar1[i - 1] * phi + wn[i]
}
ts <- ar1
t <- length(ts) # the length of the time series
li <- seq(n-2)+1 # vector of block sizes to be 1 < l < n (i.e to be between 1 and n exclusively)
# vector to store block means
RMSEblk <- matrix(nrow = 1, ncol = length(li))
colnames(RMSEblk) <-li
for (b in 1:length(li)){
l <- li[b]# block size
m <- ceiling(t / l) # number of blocks
blk <- split(ts, rep(1:m, each=l, length.out = t)) # divides the series into blocks
# initialize vector to receive result from for loop
singleblock <- vector()
for(i in 1:1000){
res<-sample(blk, replace=T, 10000) # resamples the blocks
res.unlist<-unlist(res, use.names = F) # unlist the bootstrap series
# Split the series into train and test set
train <- head(res.unlist, round(length(res.unlist) * 0.6))
h <- length(res.unlist) - length(train)
test <- tail(res.unlist, h)
# Forecast for train set
model <- auto.arima(train)
future <- forecast(test, model=model,h=h)
nfuture <- as.numeric(future$mean) # makes the `future` object a vector
RMSE <- rmse(test, nfuture) # use the `rmse` function from `Metrics` package
singleblock[i] <- RMSE # Assign RMSE value to final result vector element i
}
RMSEblk[b] <- mean(singleblock) # store into matrix
}
RMSEblk
Run Code Online (Sandbox Code Playgroud)
该R脚本实际运行,但需要 24 多个小时才能完成。loops(10000 和 1000)中的运行次数是使任务完美所需的最小值。
请问我该怎么做才能在更短的时间内完成脚本?
tl;dr你可能不得不以某种方式并行化这个。
一个问题是您正在增长一个对象;也就是说,首先分配一个零长度向量 ( singleblock <- vector()),然后一次增加一个元素 ( singleblock[i] <- RMSE)。正如R Inferno 的第 2 章所讨论的,这是非常低效的。对于这个示例,它慢了 5 倍。
f1 <- function(x) { p <- numeric(0); for (i in 1:1000) p[i] <- 0 }
f2 <- function(x) { p <- numeric(1000); for (i in 1:1000) p[i] <- 0 }
microbenchmark(f1(),f2())
## Unit: microseconds
## expr min lq mean median uq max neval cld
## f1() 202.519 207.2105 249.84095 210.574 221.340 3504.95 100 b
## f2() 40.274 40.6710 69.83741 40.9615 42.8275 2811.779 100 a
Run Code Online (Sandbox Code Playgroud)
但是:这并不重要。低效版本(增加向量)的中位时间为 210 微秒。
microbenchmark(auto.arima(train),times=20L)
## Unit: milliseconds
## expr min lq mean median uq max neval
## auto.arima(train) 630.7335 648.3471 679.2703 657.6697 668.0563 829.1648 20
Run Code Online (Sandbox Code Playgroud)
您的auto.arima()通话需要大约 660毫秒- 大约长 3000 倍。microbenchmark对预测步骤使用类似的调用可得出大约 20 毫秒的中值时间。
你可以做更正式的分析,或者像这里所示的那样一点一点地继续,但我在你的代码中没有看到任何看起来需要很长时间的东西(我可能会检查sample()下一个,但我怀疑它与auto.arima().)
除非你能找到更快的版本auto.arima()(我对此表示怀疑),或者精简(例如限制搜索空间),否则你唯一剩下的选择就是并行化。您可以使用许多不同的工具在许多不同的级别上执行此操作,但首先要查看的将是auto.arima的并行选项。您可能会选择并行化循环(在“R 中的并行计算”上进行网络搜索会提供大量资源);请注意,尝试在多个级别进行并行化可能会咬你。
PS 粗略计算(48000 * 660 毫秒)给出了大约 9 小时 - 这仅占时间的 1/3 左右(我预计它会达到 80% 左右);也许你的处理器比我的慢?