【问题标题】:Batch Forecasting; using apply() function instead of for loop. apply() function gives different point forecast批量预测;使用 apply() 函数而不是 for 循环。 apply() 函数给出不同的点预测
【发布时间】:2023-04-05 01:54:01
【问题描述】:

到目前为止,当我有多个时间序列要预测时,我使用的是 Hyndman 教授的 this 方法。但是当我有大量 ts 时,它就相当慢了。

现在我正在尝试使用apply()函数如下

library(forecast)

fc_func <- function(y){
  forecast(auto.arima(y),h=12)$mean
}

retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)

  frc<- apply(retail,2 ,fc_func)

它似乎运行良好,但是当我使用for 循环时,如下所示:

ns <- ncol(retail)
h <- 12
fcast <- matrix(NA,nrow=h,ncol=ns)
for(i in 1:ns){
  fcast[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
}

我得到不同的点预测。是什么原因?

编辑:我通过更改“fc_func”函数修复了它。现在它返回与for 循环相同的结果,但现在它也和for 循环一样慢

fc_func <- function(x){

ts(x,f=12,s=1982+3/12)->y

 forecast(auto.arima(y),h=12)$mean
}

retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)

  frc<- apply(retail,2 ,fc_func)

【问题讨论】:

  • 我认为不应该是这种情况:D 我会尝试首先检查两个版本中的输入数据是否相同。也许通过在 for 循环中的 apply 和 retail[,i] 中打印 y 并比较它们。然后我会比较每个变量的两个版本的直接输出,再次打印它们。如果输入和输出没有差异,则必须与数据在最终对象中的存储方式有关。
  • 代码是可重新应用的,我想任何人都会看到这两种方法返回不同的点预测,尽管它们使用相同的预测函数。
  • 是的,只需添加一点 1 即可使其运行 :) 然而,这很奇怪,我将添加我的想法作为答案,所以我可以显示更吸引人的代码
  • 我明白了:)。已更正

标签: r for-loop apply forecasting


【解决方案1】:

问题是apply() 操作time series 对象的类,retail。作为 apply 系列的初级版本,apply() 最适合用于简单的矩阵对象。它会在调用时将其输入转换为带有as.matrix() 的矩阵对象,因此经常警告apply() 不要用于数据帧。

根据?apply 文档:

如果 X 不是一个数组,而是一个具有非 null 暗淡的类的对象 值(例如数据框),应用尝试将其强制为数组 如果它是二维的(例如,数据帧),则通过 as.matrix 或通过 as.array

所以apply在处理成fc_func之前不会保留其输入的类对象:

class(retail)
# [1] "mts"    "ts"     "matrix" 

当使用运行速度与for 一样慢的sapply 时可以看到这一点,并且在删除dimnames 时返回的结果与for 循环完全相同:

# LOOP VERSION
ns <- ncol(retail)
h <- 12
fcast1 <- matrix(NA,nrow=h,ncol=ns)

for(i in 1:ns) {
  fcast1[,i] <- forecast(auto.arima(retail[,i]), h=h)$mean
}

# SAPPLY VERSION
frc_test <- sapply(retail, fc_func, USE.NAMES = FALSE)
dimnames(frc_test) <- NULL

identical(frc_test, fcast1)
# [1] TRUE

【讨论】:

  • 有没有办法改善这个问题?
  • 原谅我,但这不是你的问题。我相信你问的原因是:我得到不同的点预测。原因是什么? 绝对不要使用apply 进行此调用。
  • 至于性能,看并行处理。我看到?auto.arima 有一个 num.cores 参数。
  • 感谢您的建议。我会重新排列这个问题,也许会发布一个新问题。
【解决方案2】:

为了调试,我在应用程序中添加了一些打印。有趣的是class(y)

library(forecast)

fc_func <- function(y){
  print(length(y))
  print(class(y))
  #print(y)
  forecast(auto.arima(y),h=12)$mean
}

retail <- read.csv("https://robjhyndman.com/data/ausretail.csv",header=FALSE)
retail <- ts(retail[,-1],f=12,s=1982+3/12)

retail2 = retail

#retail = retail2[1:333,1:42]

frc<- apply(retail,2 ,fc_func)

所有 y 在应用时都以数字形式出现。

> frc<- apply(retail,2 ,fc_func)
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333
[1] "numeric"
[1] 333

这在for循环中是不同的:

ns <- ncol(retail)
h <- 12
fcast1 <- matrix(NA,nrow=h,ncol=ns)
for(i in 1:ns){
  print(length(retail[,i]))
  print(class(retail[,i]))
  #print(retail[,i])
  fcast1[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
}

这里的变量作为 ts 传递给 auto.arima。

> for(i in 1:ns){
+   print(length(retail[,i]))
+   print(class(retail[,i]))
+   #print(retail[,i])
+   fcast1[,i] <- forecast(auto.arima(retail[,i]),h=h)$mean
+ }
[1] 333
[1] "ts"
[1] 333
[1] "ts"
[1] 333
[1] "ts"
[1] 333

我猜这会导致差异,因为当我将零售减少到一个简单的矩阵时

retail = retail[1:NROW(retail), 1:NCOL(retail)] 

再次运行 for 循环,我得到了与应用版本完全相同的结果。

all.equal(frc, fcast1)

所以我猜你必须在将变量发送到预测函数之前再次将变量转换为 fc_func 中的 ts。

作为一种解决方法(并且因为我不知道如何将 y 转换为所需的 ts 对象),您可以使用 sapply 版本:

fc_func2 <- function(y){

  forecast(auto.arima(retail[,y]),h=12)$mean
}

frc2 <- sapply(1:NCOL(retail), fc_func2)

它应该给出所需的值,但我不确定它是否比循环版本快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多