3.2 变换和调整

调整历史数据通常会使预测更加简单。 本节我们将会介绍四种调整方法:日历调整、人口调整、通胀调整和数学变换。这些调整和变换的目的是通过去除数据变化的已知来源或增加整个数据集的一致性来简化历史数据的模式。更简单的数据模式往往可以让我们得到更精确的预测结果。

日历调整

季节性数据中的某些变化可能是来自简单的日历效应。这种情况下,在拟合预测模型之前消除这些变化因素往往会使预测更简单。monthdays()函数可以计算每个月或每个季度所包含的天数。

例如,假如你正在研究某农场每月的牛奶产量,一年之中,除了季节性变化因素以外,每月牛奶产量还会由于每月的天数不同而发生变化。

dframe <- cbind(月均 = milk, 日均=milk/monthdays(milk))
  autoplot(dframe, facet=TRUE) +
    xlab("年") + ylab("英镑") +
    ggtitle("每头奶牛牛奶产量的预测") +
    theme(text=element_text(family="STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))
每头奶牛的月度牛奶产量预测。

图 3.3: 每头奶牛的月度牛奶产量预测。

可以看到,日均产量图的季节性模式比月均产量图更简洁明了。日均产量图有效消除了不同月份天数不同造成的影响。简单的模式往往更易于建立模型并得出更精确的预测结果。 对于交易天数随着月份改变的销售数据,我们可以做相似的调整。在这种情况下,可以用每个交易日的销量而非每月的总销量来建立模型。

人口调整

任何受人口数量影响的数据都可以调整为人均数据,换句话说,考虑每人(或每千人,或每百万人)而非所有人。 假如你正在研究某区域内医院床位数量随着时间变化的情况,那么通过考虑每千人的床位数量来去除人口数量变化的影响,结果就更容易解释。这样你就能看出床位数量是否有实际的增长,或者床位数量的增长是否完全由人口数量增长所导致。很有可能出现床位总数量增长但每千人的床位数量却在下降的情况,这是由于人口增长速度快于医院床位数量增长速度造成的。对于大多数受人口数量变化影响的数据,最好的选择是采用人均数据而非总量数据。

通胀调整

受货币价值影响的数据在建立模型之前经过最好经过通胀调整。例如,由于通货膨胀的影响,一座新房的平均价格在过去的几十年里提高了很多,一座标价20万美元的房子并不等同于二十年前标价20万美元的房子。因此金融时间序列数据经常进行调整以便所有价格都以某一固定年份的美元价值标价。例如,房价数据可以用2000年的美元标价。

进行通货膨胀调整需要用到一种价格指数,我们把它记作\(z_{t}\)\(t\)年的原始房价记作 \(y_{t}\) ,以2000年美元价值调整后的房价记作 \(x_{t}\),则 \(x_{t} = y_{t}/z_{t} * z_{2000}\) 。价格指数通常由政府部门制定,对于消费品,常用的价格指数是消费物价指数(Consumer Price Index,CPI)。

数学变换

如果数据数值范围发生变化,而数据的波动变化也会随之变大变小,那么变换会很有用。例如,对数变换经常是有用的。我们把原始观测值记作 \(y_{1},\dots,y_{T}\) ,变换后的观测值记作 \(w_{1}, \dots, w_{T}\),则 \(w_t = \log(y_t)\)。对数变换之所以有用,是因为它们易于解释:对数值的变化是原始值的相对(或百分比)变化。假设进行以10为底的对数变换,那么对数值加1相当于原始值乘以10。对数变换的另一个特点在于能够限制在原来测度下的预测值为正数。

有时候其他变换也会被用到(虽然它们不是那么容易解释),例如平方根和立方根变换,它们也被称作幂变换,因为可以以 \(w_{t} = y_{t}^p\) 的形式表示。

“Box-cox变换”是一个既包含对数变换,又包含幂变换的依赖于参数 \(\lambda\) 的变换族,其定义如下: \[ w_t = \begin{cases} \log(y_t) & \text{if $\lambda=0$}; \\ (y_t^\lambda-1)/\lambda & \text{otherwise}. \end{cases} \]

Box-cox变换中的对数变换通常以自然对数\(e\)为底,因此如果\(\lambda=0\),进行自然对数变换,否则,进行幂变换,然后简单缩放。

如果 \(\lambda=1\), 那么 \(w_t = y_t-1\), 变换后的数据向下移动,但是时间序列的形状没有改变。但是对于所有其他的\(\lambda\)值,时间序列的形状会改变。

使用下方的滑动按钮查看\(\lambda\)的变化对澳大利亚月度用电需求数据变换的影响:

合适的\(\lambda\)值使得在整个时间序列范围内,周期性变化大小差不多相同,因此让预测更加简单。在此例中,\(\lambda=0.30\) 的变换效果相当好,虽然在0-0.5之间的所有\(\lambda\) 值得出了相似的变换结果。

BoxCox.lambda() 函数会给你选择一个合适的\(\lambda\)值。

(lambda <- BoxCox.lambda(elec))
#> [1] 0.2654
autoplot(BoxCox(elec,lambda))

选择好变换以后,我们需要利用变换后的数据进行预测,得出预测值后,我们需要进行逆变换得到原始测度上的预测值。逆Box-Cox变换如下表示: \[\begin{equation} \tag{3.1} y_{t} = \begin{cases} \exp(w_{t}) & \text{if $\lambda=0$};\\ (\lambda w_t+1)^{1/\lambda} & \text{otherwise}. \end{cases} \end{equation}\]

幂变换的特点

  • 如果出现部分 \(y_{t}\le0\),除非给所有观测值加上一个常数,否则不能进行幂变换,。
  • 选择一个简单的\(\lambda\)值会让解释更容易。
  • 预测结果对\(\lambda\)值相对不敏感
  • 很多情况下不需要进行变换
  • 有时候变换对于预测结果影响不大,但对预测区间有很大影响。

偏差调整(Bias Adjustments)

进行数学变换例如Box-Cox变换的一个问题在于逆变换后得到的预测值不是预测分布的平均值,事实上,它通常是预测分布的中位数。(假定变换空间上的分布是对称的)很多情况下,这可以接受,但有时需要预测均值。例如,你可能希望汇总各地区的销售预测值来形成全国预测值,这是中位数做不到的,但是平均数可以做到。

对于Box-Cox变换,逆变换的均值如下给出: \[\begin{equation} \tag{3.2} y_t = \begin{cases} \exp(w_t)\left[1 + \frac{\sigma_h^2}{2}\right] & \mbox{如果} \lambda=0 \mbox{;}\\ (\lambda w_t+1)^{1/\lambda}\left[1 + \frac{\sigma_h^2(1-\lambda)}{2(\lambda w_t+1)^{2}}\right] & \mbox{否则;} \end{cases} \end{equation}\] \(\sigma_h^2\)\(h\)步预测方差,预测方差越大,均值和中位数之间的差异越大。

公式 (3.1) 给出的简单逆变换预测与公式 (3.2) 给出的均值变换之间的差异叫做偏差(Bias),当我们用均值而非中位数时,称预测点是经过“偏差调整”(Bias-adjusted)的。下面的例子给出了偏差调整起到的作用。在这个例子中我们利用趋势法(Drift method)进行对数变换 \((\lambda=0)\) 来预测每年的鸡蛋平均价格,对数变换可以保证预测值和预测区间为正。

fc <- rwf(eggs, drift=TRUE, lambda=0, h=50, level=80)
fc2 <- rwf(eggs, drift=TRUE, lambda=0, h=50, level=80, biasadj=TRUE)
autoplot(eggs) +
  autolayer(fc, series="简单逆变换") +
  autolayer(fc2$mean, series="偏差调整") +
  guides(colour=guide_legend(title="预测")) +
    theme(text=element_text(family="STHeiti"))+
  theme(plot.title = element_text(hjust = 0.5))

蓝线表示预测值中位数而红色线表示预测值均值,请注意当我们使用偏差调整时,倾斜的预测分布如何拉升预测点。 偏差调整并不会默认进行,如果你想让预测结果为均值而非中位数,在选择Box-Cox变换参数时令 biasadj=TRUE