3.3 残差诊断

拟合值

时间序列中的每个观测值都可以用其之前的观测值预测,我们称其为“拟合值”并记作\(\hat{y}_{t|t-1}\),代表基于观测值\(y_{1},\dots,y_{t-1}\)得出的预测值\(y_t\),由于经常用到,有时我们会去掉部分下标并简写成yt,拟合值总是包含到一步预测。

事实上,拟合值通常不是真正的预测值因为包含于预测方法中的任何参数都是利用时间序列中所有可得到的观测值估计出来的,甚至包括未来观测值。例如,假如我们采用平均值方法,拟合值如下给出:

\[ \hat{y}_t = \hat{c} \] 该式中,\(\hat{c}\) 是所有可得观测值的平均值,包括那些在\(t\)时间以后的观测值。相似地,对于趋势法,趋势参数是用所有可得观测值估计出来的,在这种情况下。拟合值如下给出: \[ \hat{y}_t = y_{t-1} + \hat{c} \] 其中 \[ \hat{c} = (y_T-y_1)/(T-1). \] 两种方法中都有参数是用数据估计出来的,\(c\)上的“帽子”说明它是个估计值,当\(c\)的估计值由包含时间\(t\)以后的观测值估计出来时,拟合值不是真正的预测值。另一方面,naïve方法和季节性naïve方法不包括任何参数,因此得到的拟合值是真正的预测值。

残差

时间序列模型中的残差可以理解为是在拟合模型后剩余的值。对于大多数时间序列模型(不是全部),其残差等于观测值和相对应拟合值的差。 \[ e_{t} = y_{t}-\hat{y}_{t}. \]

在检查模型是否充分地捕获数据中的信息方面,残差有着很大的用处。一个好的预测方法产生的残差具有以下特性:

  1. 残差是不相关的。如果残差之间存在相关性,那么残差中包含的数据信息应该被用于计算预测值。
  2. 残差的均值为零,如果残差的均值不为零,那么说明预测是有偏差的。

不满足上述性质的预测方法都应进行相应的改进,当然,这并不意味着满足上述性质的预测方法就不能改进了。对于相同的数据集,也可能存在不同的预测方法,且这些方法都满足上述性质。检查预测方法是否满足这些性质对于检查模型是否使用了所有可用的数据信息是非常重要的,但不能通过这个来选择预测方法。 如果在上述性质中有任意一条不满足,则需要改进预测模型以进行更好的预测。调整有偏差的预测较为容易:如果残差的均值为\(m\),那么只需给所有预测值的加上\(m\),有偏的问题就解决了。但如果是残差之间具有相关性,解决该问题会有些困难,我们将在第9章讨论这个问题。 除了上述的基本性质外,残差最好也满足下列两个性质(但不是必须满足):

  1. 残差的方差是常数
  2. 残差满足正态分布

这两条性质能够让预测区间的计算变得容易(详见 3.5 章节中的示例)。然而,不满足这两条性质的预测方法也不一定需要进行改进。有时,我们可以使用Box-Cox变换让模型满足这两条性质。但除此之外,几乎没有什么方法能够确保模型的残差既有常数方差,又满足正态分布。因此,我们可以使用另一种方法计算得到预测区间,我们将在后面的章节讨论该方法。

示例:预测谷歌公司每日收盘价

对于股票市场的价格和指数,最好的预测方法往往是naïve方法,也就相当于,每个预测值就等于最后一个观测值,或者可以用公式表达\(\hat{y}_{t} = y_{t-1}\),因此,残差就等于连续观测值之间的差值: \[ e_{t} = y_{t} - \hat{y}_{t} = y_{t} - y_{t-1}. \]

下图显示了谷歌每日股票收盘价。由于2013年10月18日谷歌公司第三季度出人意料的优秀业绩,谷歌的股价上涨了12%,也因此在图中股价有一个大跳跃。

autoplot(goog200) + xlab("天") + ylab("收盘价(美元)") +
  ggtitle("谷歌公司每日股价(截止至2013年12月6日)")+
  theme(text = element_text(family = "STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))
谷歌公司每日股价(截止至2013年12月6日)。

图 3.4: 谷歌公司每日股价(截止至2013年12月6日)。

使用naïve方法预测这一序列计算得到的残差图如图 3.5 所示,前一个图中出现的意外价格跳跃导致了下图中出现那个很大的正残差。

res <- residuals(naive(goog200))
autoplot(res) + xlab("天") + ylab("") +
  ggtitle("Naïve方法的残差")+
  theme(text = element_text(family = "STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))
使用naïve方法预测谷歌公司股价计算得到的残差直方图,对于一个正态分布来说,图中显示右尾有些长。

图 3.5: 使用naïve方法预测谷歌公司股价计算得到的残差直方图,对于一个正态分布来说,图中显示右尾有些长。

gghistogram(res) + ggtitle("残差直方图")+
  theme(text = element_text(family = "STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))
使用naïve方法预测谷歌公司股价计算得到的残差直方图,对于一个正态分布来说,图中显示右尾有些长。

图 3.6: 使用naïve方法预测谷歌公司股价计算得到的残差直方图,对于一个正态分布来说,图中显示右尾有些长。

ggAcf(res) + ggtitle("残差ACF图")+
  theme(text = element_text(family = "STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))
使用naïve方法预测谷歌公司股价计算得到的残差ACF图,无相关性表明预测效果很好。

图 3.7: 使用naïve方法预测谷歌公司股价计算得到的残差ACF图,无相关性表明预测效果很好。

这些图表明使用naïve方法进行预测似乎可以解释所有可用的数据信息。残差的均值十分接近零,且残差序列之间没有显著相关性。残差的时间图表明,除去一个异常值外,残差的变化在历史数据上大致保持不变,因此可以将残差方差视为一个常数。这一结论在残差直方图中也可以得出,同时残差直方图说明残差的分布可能不符合正态分布,因为即使忽略掉异常值,残差分布的右尾也有些太长了。因此,使用这种方法进行预测可能已经相当好了,但如果假定残差符合正态分布,进而计算得到的预测区间可能有些不够准确。

复合自相关检验

除了观察ACF图之外,我们也可以将一整列\(r_k\)值作为一组进行更为正式的自相关检验,而不是把这些\(r_k\)值单独地看待。

注意,\(r_k\)是滞后于\(k\)的自相关函数。当我们在ACF图中观测是否每个尖峰都在规定的范围内时,我们已经暗含地进行了多次假设检验,每个假设被拒绝的概率很小。但实际上并不存在自相关的情况下,当进行了足够多的检验时,至少会出现一次原假设被拒绝的情况的可能性很高,我们也可能会得出结论:残差存在一些剩余自相关。

为了克服这个问题,我们检验\(h\)的自相关函数是否与预期的白噪声过程存在明显的差别,这种对于一组自相关函数的检验被称为复合检验,这个词来源于法语,原意是指含有很多东西的手提箱。 基于下式,类似这样的检验叫做Box-Pierce检验

\[ Q = T \sum_{k=1}^h r_k^2, \] 其中\(h\)是能够考虑到的最大滞后项个数,\(T\)是观测值的数量。如果每个\(r_k\)的值都接近于0,那么\(Q\)值就较小;如果存在一些非常大的\(r_k\)值(无论正负),那么Q指就较大。对于非周期性的数据集,我们建议取\(h=10\);对于周期性的数据集,则取\(h=2m\)(其中m是周期)。然而,如果\(h\)的值过大,检验的效果就不够理想了。因此,如果\(h\)的值大于\(T/5\),则取\(h=T/5\)。 一个相关的(更为精确的)检验叫做Ljung-Box检验,基于下式: \[ Q^* = T(T+2) \sum_{k=1}^h (T-k)^{-1}r_k^2. \]

\(Q^*\)的值较大,则表明自相关函数并不来自于白噪声序列 。 那么多大的\(Q^*\)值算大呢?如果一个自相关函数确实来自于白噪声序列,那么\(Q\)\(Q^*\)均服从自由度为(h-K)的\(\chi^2\)分布,其中\(K\)是模型中参数的个数,如果\(Q\)\(Q^*\)是从原始数据中计算出来的(而不是模型中的残差),则取\(K=0\).

以谷歌公司股票价格为例,navie模型中没有参数,因此也取\(K=0\)

# lag=h and fitdf=K
Box.test(res, lag=10, fitdf=0)
#> 
#>  Box-Pierce test
#> 
#> data:  res
#> X-squared = 11, df = 10, p-value = 0.4

Box.test(res,lag=10, fitdf=0, type="Lj")
#> 
#>  Box-Ljung test
#> 
#> data:  res
#> X-squared = 11, df = 10, p-value = 0.4

对于\(Q\)\(Q^*\),结果都是无意义的(即\(p\)-values非常大)。因此,我们可以得出结论:残差与白噪声序列不可区分。 所有这些检验残差的方法,在R中都被打包成一个函数,这个函数能够产生时间图、ACF图和残差直方图(与叠加正态分布进行对比),还能够以正确的自由度进行Ljung-Box检验:

checkresiduals(naive(goog200))

#> 
#>  Ljung-Box test
#> 
#> data:  Residuals from Naive method
#> Q* = 11, df = 10, p-value = 0.4
#> 
#> Model df: 0.   Total lags used: 10