R时间序列预测:为ARIMA选择傅立叶对与回归器时遇到问题

机器算法验证 r 时间序列 预测 有马
2022-03-16 10:52:46

我一直在研究一些不同的时间序列预测,并且我已经开始在我的分析中注意到一个趋势(请原谅双关语)。对于我迄今为止使用过的大约 5-7 个数据集,允许多个季节性时段以及假日假人选项会很有帮助。我尝试了各种方法并且通常坚持使用回归器tbats一直auto.arima()给我带来问题。至此,很明显我在 R 中工作。

在我走得太远之前,让我提供一些示例数据。希望以下链接有效:https ://gist.github.com/JaredRayWolf/c8cb601dd26ec72a64d0 。

该数据产生以下时间序列图: 时间序列图 大幅下降是在圣诞节和新年前后,但也有较小的下降在感恩节前后。在下面的代码中,我将此数据集命名为traindata

现在,从长远来看, ets“平原”auto.arima看起来并不那么热,因为它们仅限于一个季节性时期(我选择每周)。然而,对于我的测试集,我认为它们在当月的数据中表现相当不错(劳动节周末除外)。话虽如此,预测一年将是理想的。

接下来我尝试tbats了每周和每年的季节性周期。这导致以下预测: TBATS 预测

现在这看起来很不错。从肉眼来看,它在考虑每周和每年的季节性时段以及圣诞节和新年的影响方面看起来很棒(因为它们显然每年都在相同的日期)。如果我可以将假期(及其周围的日子)包括为虚拟变量,那将是最好的。因此,我尝试auto.arima使用xreg回归器。

对于带有回归量的 ARIMA,我遵循了 Hyndman 博士对傅立叶函数的建议(在此处给出:http ://robjhyndman.com/hyndsight/longseasonality/ )以及他对傅立叶项数量的选择(在此处给出:http ://robjhyndman.com/hyndsight/forecasting-weekly-data/

我的代码如下:

fourier <- function(t,terms,period)
{
  n <- length(t)
  X <- matrix(,nrow=n,ncol=2*terms)
  for(i in 1:terms)
  {
    X[,2*i-1] <- sin(2*pi*i*t/period)
    X[,2*i] <- cos(2*pi*i*t/period)
  }
  colnames(X) <- paste(paste(c("S","C"),rep(1:terms,rep(2,terms)),sep=""),period,sep="_")
  return(X)
}

fcdaysout<-365
m1<-7
m2<-30.4375
m3<-365.25

hol<-cbind(traindata$CPY_HOL, traindata$DAY_BEFORE_CPY_HOL, traindata$DAY_AFTER_CPY_HOL)
hol<-as.matrix(hol)

n <- nrow(traindata)
bestfit <- list(aicc=Inf)
bestk <- 0

for(i in 1:m1)
{
    fake_xreg = cbind(fourier(1:n,i,m1), fourier(1:n,i,m3), hol)
    fit <- auto.arima(traindata$ACTIVE_LOADS, xreg = fake_xreg, max.p=10, max.q=10, max.d=2, stepwise=FALSE, ic="aicc", allowdrift=TRUE)
	if(fit$aicc < bestfit$aicc)
    {
        bestfit <- fit
        bestk <- i
    }
    else
    {
    }
}

k <- bestk
k
##k<-3

xreg<-cbind(fourier(1:n,k,m1), fourier(1:n,k,m3), hol)
xreg<-as.matrix(xreg)

aacov_fit <- auto.arima(traindata$ACTIVE_LOADS, xreg = xreg, max.p=10, max.q=10, max.d=2, stepwise=FALSE, ic="aic", allowdrift=TRUE)
summary(aacov_fit)

我的问题出现在 for 循环内部,以确定k最小化 AIC 的傅立叶项数。k>3在我使用回归器对 ARIMA 进行的所有尝试中,它总是在(或者i>3如果我们在我的循环中谈论)时产生错误。错误是Error in solve.default(res$hessian * n.used, A) : system is computationally singular: reciprocal condition number = 1.39139e-34. 简单的设置k=3为我的测试集提供了一些不错的结果,但在接下来的一年里,它似乎没有充分捕捉到年底左右的急剧下降,并且比想象中的要平滑得多,正如这个预测所证明的那样:带协变量的 AutoArima (k=3)

我认为这种一般的平滑度是由于傅立叶对的数量很少。我的代码中是否存在疏忽,因为我只是在彻底搞砸 Hyndman 博士提供的程序?或者是否存在一个理论问题,我试图为我试图解释的多个季节找到超过 3 对傅立叶项?有没有更好的方法来包含多个季节性和虚拟变量?

任何帮助将这些协变量带入具有适当数量的傅立叶项的 arima 模型将不胜感激。如果没有,我至少想知道我正在尝试的东西是否可以通过更多的傅立叶对来实现。

3个回答

您正在碰壁,因为您已经耗尽了第一个傅立叶变换的限制fourier(1:n,i,m1)正如上面 RandomDude 正确指出的那样,变换i次数应小于半周期 (m1)。

但是,如果使用您的代码运行 2 个周期 - 一个用于i,另一个用于jj那么第二个季节性周期的变换数将是哪里fourier(1:n,j,m3),您仍然有很大的模型改进空间。

这就是我从您的数据中得到的,即使没有假人,仅基于 AR、MA 和数据季节性:

library(forecast)
y <- msts(ts, c(7,365)) # multiseasonal ts
fit <- auto.arima(y, seasonal=F, xreg=fourier(y, K=c(3,30)))
fit_f <- forecast(fit, xreg= fourierf(y, K=c(3,30), 180), 180)
plot(fit_f)

在此处输入图像描述

我怀疑添加假期后性能甚至会有所改善。

fourier()您不使用预测包中的功能是否有原因?当您尝试构建季节性时间序列对象的傅立叶项时,您K必须小于period/2否则你会得到一个错误:

fourier(ts(test, frequency=7),4) #3 works, 4+ doesn't
Error in ...fourier(x, K, 1:length(x)) : 
  K must be not be greater than period/2

引用自?fourier()

傅立叶(x,K)

当 x 是 ts 对象时,K 的值应该是一个整数,并指定要返回的正弦和余弦项的数量。因此,返回的矩阵有 2*K 列。

我没有理论解释+我没有足够的声誉在您的帖子下发表评论(答案是唯一的选择)。希望我还能以某种方式帮助你!

基于 AICc 值的傅里叶对优化。这是针对没有周末的数据的年度和每月季节性。0:10 和 1:20 的范围应针对不同的季节期间进行相应更改。或增加以进行更广泛的搜索。

msts_test <- msts( test , seasonal.periods = c(21.66,260))


my_aic_df <- matrix(ncol = 10 , nrow = 20)


for(i in 1:10){ 

   for(j in 1:20){ 

   fn <- fourier( msts_test , K=  c(i , j) )

   FourierFit <- auto.arima( msts_test , seasonal=FALSE,  xreg=fn )

   my_aic_df[(j),(i+1)] <- FourierFit$aicc

   }
}

 which(my_aic_df == min(my_aic_df), arr.ind = TRUE)