天天看点

常见时序预测模型的R实现 三

常见时序预测模型的R实现 三

ETS模型

接下来说说ETS模型,在R的forecast库中有实现。

> library(fpp2)
Loading required package: forecast
Loading required package: fma
Loading required package: expsmooth
Loading required package: ggplot2
           

作者Rob Hyndman是个H-index 54,citation过两万的大牛。他故意用这三个字母来使这个模型的名字能顾名思义(reminiscent),既可以理解为Error, Trend and Seasonality,又可以解作ExponenTial Smoothing模型。前者揭示了模型的三个组成部分,后者则描述了模型的工作原理。准确的说,ETS实际上是一整个系列的算法,可以基于这三个组成部分任意组合,而Hyndman写的forecast库中可以用ets()方法自动选择三个component的组合。

之所以要从这个模型写起,是因为这个模型既足够强大,又足够简明。它可以预测以下几种时间序列:

  • 无趋势(trend),无季节性(seasonality) 比如我上个月跑了十次5公里,根据这十次时间估计我接下来一次要跑多久
  • 有趋势,无季节性 比如我刚开始学打字,一开始打1000个词要4个小时,以后随着熟练程度递减,预测下一次时间
  • 有趋势,有季节性 比如零售业的销售数据,趋势体现的可能是整个行业的冷暖,季节性则跟气温、假日有关
  • 无趋势,有季节性 比如近十年某地气温的变化,十年这样的短周期里也许体现不出大的趋势变化,但季节性是显著的

不仅如此,由于它的error component既可以是additive的又可以是multiplicative的,它还能预测有季节性且在每个周期内幅度有变化的序列。比如电力供应,由于用的起空调之类制冷设备的家庭变多了,季节性的振幅可能是逐渐递增的。

最简单的ETS

最简单的ETS是ses模型,即simple exponential smoothing。这个模型只能解决没趋势也没季节性的时序。它的公式如下:

常见时序预测模型的R实现 三

公式是从Hyndman的书上抄来的。这个公式的设计基于怎样的考虑呢?Hyndman是这么说的。设想两个极端情况,一个情况是永远只采用当下的值来预测下一个值。假设数据完全没有任何规律,这也不失为一个方案吧。另一个情况是,对所有观测到的点作平均,这样预测值其实是样本集的均值。起码这样搞能让训练集上的方差小,而且用到所有点了,但不能反映出很多序列里recency很重要的特点。近期的观测值的确往往比远古观测值更有意义。然后ses就出现了:hey,我就是折中方案。我给近期的观测值更高的权重,但也用到所有过去的点。如果alpha值为1,则相当于把除当下值Yt以外的所有点权重都赋为0了。假如alpha为0.5,那权重就是个标准的底为0.5的指数函数。而无论alpha是多少,权重decay的速度都是由(1-alpha)的指数函数决定的,所以叫exponential smoothing。让alpha充分的接近0的话,各个点位的权重就会更平均,衰减速度更慢。

虽然应用场景有限,ses的确是个很精致的方案。非常不幸的是,它完全木有办法对趋势建模。看个例子

> x_st = ts(1:10,start=c(1,1),frequency=5)
> autoplot(x_st)
           
常见时序预测模型的R实现 三

上ses会发生什么呢?ses可以用h参数指定预测多少个时间点,用alpha指定公式中的权重参数。我们先看一下alpha=1的情况,也即使用前一个值预测下一个值。注意由于alpha值域在0和1之间,这里用了0.9999作为近似

> autoplot(ses(x_st,h=4,alpha=0.9999))
           
常见时序预测模型的R实现 三

如所预料,它取了最近的值,10,作为接下来4个点的预测值。再换alpha=0.5试试

> autoplot(ses(x_st,h=4,alpha=0.5))
           
常见时序预测模型的R实现 三

当alpha充分接近0时,预测值逼近观测值均值。这一点在公式中看不出来,但应该跟y0有关。具体可以看源码,这里不深入。

总结一下,ses对未来的预测来自对过去观测值赋予不同权重的求和,权重衰减函数是个指数函数,体现的其实是观测值的分布特性。它的预测曲线是个常数,与X轴平行,无法反映出历史数据中的趋势。

关于趋势 Trend

不能处理趋势,这可用性就相当不靠谱了。为了解决这个问题,有个叫Holt Winter的人给ses的模型加了一个component,

常见时序预测模型的R实现 三

公式依然抄自Hyndman的书。这里公式已经略有些复杂,可以在纸上自己展开,但不太方便打字了。这里理解的关键在于,alpha依然是用于确定观测值衰减速度的参数,但对于过去的点还考虑了每个点处的趋势量。趋势量本身也是采用了权重来估计的,并不仅采用过去一个点到当前点的变化趋势,而是把之前每个点的趋势都用一个指数衰减函数引入。这样的设计可以使曲线平滑。看一下案例,还是用之前的数据例子

autoplot(hw(x_st,h=4))
           
常见时序预测模型的R实现 三

可见这个线形趋势被很好地capture了。换个数据集

> x_st = ts((1:10)^2,start=c(1,1),frequency=5)
> autoplot(hw(x_st,h=4))
           
常见时序预测模型的R实现 三

显然,非线性趋势也可以被capture到,只是由于未指定alpha值,自动选择的alpha显然考虑了比最近一个值更多的点,故而第一个预测值小于最后一个观测到的值,这和人类的直觉不符。我们可以通过调整hw()方法的参数来解决这个问题。

关于季节 Seasonality

解决了trend,是否就完满了呢?显然不是这样。再来一个数据集

> x = ts(rep((-2:2)^2,4),start=c(1,1),frequency = 5)
> autoplot(x)
           
常见时序预测模型的R实现 三

认为制造了一个周期为5的seasonal的数据集。上holt-winter算法试试看:

常见时序预测模型的R实现 三

第一眼会觉得很奇怪,我们并没有给出seasonal component啊,为什么这个模型会成功重构历史数据的模式?注意到Holt-Winters' additive method了么?原来forecast这个库里实现的是改进后的holt-winters方法,这个版本有一个seasonality的component,而且整出俩版本:

常见时序预测模型的R实现 三

常见时序预测模型的R实现 三

公式依然是从Hyndman祖师爷那里抄来的。第一个是multiplicative版本,第二个是additive版本。前者能更好的解决振幅动荡迅速变大的时序数据。

看到这里,ets的故事基本讲完了。漏过了一个维度:dampened trend,但这个component也是ets方法能够自动估计是否需要的,大致含义就是允许趋势逐渐减弱回归到水平。

总结

用祖师爷Hyndman的表格做个总结

常见时序预测模型的R实现 三

实际应用中我们只需要ets()基本就够了

> fit = ets(x)
> checkresiduals(fit)
           

由于是用完美的数学函数生成的数据集,可以看到罕见的0残值:

常见时序预测模型的R实现 三

注意图中提到的ETS(A,N,A),对应上表可以搞清楚这个自动估计的ETS模型用了哪些components。第一个A是error,说明用的是additive error,第二个N表示没有trend,第三个A表示有additive seasonality。这完美匹配我们之前手动用hw()得到的预测模型。

局限与不足

在应用中,我发觉ETS起码有两个不足。第一,对周期长的序列,由于要估计的参数极多,会无法handle或异常慢。第二,无法方便的嵌入external variables。这些在下一篇讨论ARIMA时再进一步讨论。

上一篇 常用时序预测模型之准备知识    下一篇 常用时序预测模型之ARIMA

继续阅读